示例#1
0
jresult_t cdc_open_data_pipes(uwh_cdc_dev_h dev_ctx)
{
    jresult_t rc = 0;
    jcdc_dev_softc_t *sc = (jcdc_dev_softc_t *)dev_ctx;
    DECLARE_FNAME("cdc_open_data_pipes");

    DBG_V(DHOST_CDC_GENERAL, ("%s: Entered\n", fname));

    /* Open bulk pipes */
    rc = usbd_open_pipe(sc->d_iface, sc->bulk_ep_in, 
        USBD_EXCLUSIVE_USE, &sc->bulk_pipe_in);
    if (rc)
    {
        DBG_E(DHOST_CDC_GENERAL, ("%s: Error opening bulk in pipe.\n",
            fname));
        return rc;
    }
    
    rc = usbd_open_pipe(sc->d_iface, sc->bulk_ep_out, 
        USBD_EXCLUSIVE_USE, &sc->bulk_pipe_out);
    if (rc)
    {
        DBG_E(DHOST_CDC_GENERAL, ("%s: Error opening bulk out pipe.\n",
            fname));
        usbd_close_pipe(sc->bulk_pipe_in);
    }

    return rc;
}
示例#2
0
int
urioopen(dev_t dev, int flag, int mode, struct lwp *l)
{
	struct urio_softc *sc;
	usbd_status err;

	sc = device_lookup_private(&urio_cd, URIOUNIT(dev));
	if (sc == NULL)
		return ENXIO;

	DPRINTFN(5, ("urioopen: flag=%d, mode=%d, unit=%d\n",
		     flag, mode, URIOUNIT(dev)));

	if (sc->sc_dying)
		return (EIO);

	if (sc->sc_in_pipe != NULL)
		return (EBUSY);

	if ((flag & (FWRITE|FREAD)) != (FWRITE|FREAD))
		return (EACCES);

	err = usbd_open_pipe(sc->sc_iface, sc->sc_in_addr, 0, &sc->sc_in_pipe);
	if (err)
		return (EIO);
	err = usbd_open_pipe(sc->sc_iface, sc->sc_out_addr,0,&sc->sc_out_pipe);
	if (err) {
		usbd_close_pipe(sc->sc_in_pipe);
		sc->sc_in_pipe = NULL;
		return (EIO);
	}

	return (0);
}
示例#3
0
/* Return     : None                                                                */
int parse_descriptors(pModule_data_t pModule)
{
   _uint32  eix;
   usbd_descriptors_t	* pDesc;
   struct usbd_desc_node *ifc, *ept;

   if(verbosity >=3)
     printf("Try to get interface descriptors %i, %i, %i\n",
	    (int)(pModule -> pInstance -> config),
	    (int)(pModule -> pInstance -> iface),
	    (int)(pModule -> pInstance -> alternate));
   if( usbd_interface_descriptor( pModule -> pDevice, 
				  pModule -> pInstance -> config, 
				  pModule -> pInstance -> iface, 
				  pModule -> pInstance -> alternate, 
				  &ifc ) ) 
      { // Trace interfaces
      for( eix = 0; 
	  ( pDesc = usbd_parse_descriptors( pModule -> pDevice, ifc, USB_DESC_ENDPOINT, eix, &ept ) ) != NULL; 
	  ++eix ) 
	  {
	  switch( pDesc->endpoint.bmAttributes ) 
	      {
	      case USB_ATTRIB_CONTROL:
		   usbd_open_pipe( pModule -> pDevice, pDesc, &(pModule -> ep_cntl));
		   pModule -> ep_cnt_size = pDesc -> endpoint.wMaxPacketSize; // Size of input buffer
		   pModule -> ep_cnt_buf = usbd_alloc( pModule -> ep_cnt_size);
		   break;

      	      case USB_ATTRIB_ISOCHRONOUS:
	    	   break;

      	      case USB_ATTRIB_BULK:
		   break;

	      case USB_ATTRIB_INTERRUPT:
		   // Can have two endpoints: IN & OUT
		   switch( pDesc -> endpoint.bEndpointAddress & USB_ENDPOINT_IN ) 
		       {
			case USB_ENDPOINT_OUT:
		            break;
			case USB_ENDPOINT_IN:
			    if( EOK == usbd_open_pipe( pModule -> pDevice, 
					               pDesc,
					               &(pModule -> ep_int )))
			        {
				pModule -> ep_int_size = pDesc -> endpoint.wMaxPacketSize; // Size of input buffer
				}
		            break;
			}
		    break;
	      }
	   }
      }
   return( ( pModule -> ep_int && pModule -> ep_cntl) ? EOK : ENODEV );
}
示例#4
0
文件: umidi.c 项目: bluhm/sys
/* alloc/free pipe */
static usbd_status
alloc_pipe(struct umidi_endpoint *ep)
{
	struct umidi_softc *sc = ep->sc;
	usbd_status err;

	DPRINTF(("%s: alloc_pipe %p\n", sc->sc_dev.dv_xname, ep));
	SIMPLEQ_INIT(&ep->intrq);
	ep->pending = 0;
	ep->busy = 0;
	ep->used = 0;
	ep->xfer = usbd_alloc_xfer(sc->sc_udev);
	if (ep->xfer == NULL)
		return USBD_NOMEM;
	ep->buffer = usbd_alloc_buffer(ep->xfer, ep->packetsize);
	if (ep->buffer == NULL) {
		usbd_free_xfer(ep->xfer);
		return USBD_NOMEM;
	}
	err = usbd_open_pipe(sc->sc_iface, ep->addr, 0, &ep->pipe);
	if (err != USBD_NORMAL_COMPLETION) {
		usbd_free_xfer(ep->xfer);
		return err;
	}
	return USBD_NORMAL_COMPLETION;
}
static int
auvitek_start_xfer(struct auvitek_softc *sc)
{
	struct auvitek_xfer *ax = &sc->sc_ax;
	uint32_t vframe_len, uframe_len, nframes;
	usbd_status err;
	int i;

	err = usbd_set_interface(sc->sc_isoc_iface, AUVITEK_XFER_ALTNO);
	if (err != USBD_NORMAL_COMPLETION) {
		aprint_error_dev(sc->sc_dev, "couldn't set altno %d: %s\n",
		    AUVITEK_XFER_ALTNO, usbd_errstr(err));
		return EIO;
	}

	vframe_len = 720 * 480 * 2;
	uframe_len = ax->ax_maxpktlen;
	nframes = (vframe_len + uframe_len - 1) / uframe_len;
	nframes = (nframes + 7) & ~7;

	ax->ax_nframes = nframes;
	ax->ax_uframe_len = uframe_len;
	for (i = 0; i < AUVITEK_NISOC_XFERS; i++) {
		struct auvitek_isoc *isoc = &ax->ax_i[i];
		isoc->i_ax = ax;
		isoc->i_frlengths =
		    kmem_alloc(sizeof(isoc->i_frlengths[0]) * nframes,
			KM_SLEEP);
	}

	err = usbd_open_pipe(sc->sc_isoc_iface, ax->ax_endpt,
	    USBD_EXCLUSIVE_USE, &ax->ax_pipe);
	if (err != USBD_NORMAL_COMPLETION) {
		aprint_error_dev(sc->sc_dev, "couldn't open pipe: %s\n",
		    usbd_errstr(err));
		return EIO;
	}

	for (i = 0; i < AUVITEK_NISOC_XFERS; i++) {
		struct auvitek_isoc *isoc = &ax->ax_i[i];

		isoc->i_xfer = usbd_alloc_xfer(sc->sc_udev);
		if (isoc->i_xfer == NULL) {
			aprint_error_dev(sc->sc_dev,
			    "couldn't allocate usb xfer\n");
			return ENOMEM;
		}

		isoc->i_buf = usbd_alloc_buffer(isoc->i_xfer,
						nframes * uframe_len);
		if (isoc->i_buf == NULL) {
			aprint_error_dev(sc->sc_dev,
			    "couldn't allocate usb xfer buffer\n");
			return ENOMEM;
		}
	}

	return auvitek_isoc_start(sc);
}
示例#6
0
int
ugl_openpipes(struct ugl_softc *sc)
{
	struct ugl_chain	*c;
	usbd_status		err;
	int			i;

	/* Open RX and TX pipes. */
	err = usbd_open_pipe(sc->sc_iface, sc->sc_ed[UGL_ENDPT_RX],
	    USBD_EXCLUSIVE_USE, &sc->sc_ep[UGL_ENDPT_RX]);
	if (err) {
		printf("%s: open rx pipe failed: %s\n",
		    sc->sc_dev.dv_xname, usbd_errstr(err));
		return (EIO);
	}
	err = usbd_open_pipe(sc->sc_iface, sc->sc_ed[UGL_ENDPT_TX],
	    USBD_EXCLUSIVE_USE, &sc->sc_ep[UGL_ENDPT_TX]);
	if (err) {
		printf("%s: open tx pipe failed: %s\n",
		    sc->sc_dev.dv_xname, usbd_errstr(err));
		return (EIO);
	}
	err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_ed[UGL_ENDPT_INTR],
	    USBD_EXCLUSIVE_USE, &sc->sc_ep[UGL_ENDPT_INTR], sc,
	    sc->sc_ibuf, UGL_INTR_PKTLEN, ugl_intr,
	    UGL_INTR_INTERVAL);
	if (err) {
		printf("%s: open intr pipe failed: %s\n",
		    sc->sc_dev.dv_xname, usbd_errstr(err));
		return (EIO);
	}

	/* Start up the receive pipe. */
	for (i = 0; i < UGL_RX_LIST_CNT; i++) {
		c = &sc->sc_cdata.ugl_rx_chain[i];
		usbd_setup_xfer(c->ugl_xfer, sc->sc_ep[UGL_ENDPT_RX],
		    c, c->ugl_buf, UGL_BUFSZ,
		    USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT,
		    ugl_rxeof);
		usbd_transfer(c->ugl_xfer);
	}

	return (0);
}
示例#7
0
int
urioopen(struct dev_open_args *ap)
{
    cdev_t dev = ap->a_head.a_dev;
#if (USBDI >= 1)
    struct urio_softc * sc;
#endif
    int unit = URIOUNIT(dev);
    sc = devclass_get_softc(urio_devclass, unit);
    if (sc == NULL)
        return (ENXIO);

    DPRINTFN(5, ("urioopen: flag=%d, mode=%d, unit=%d\n",
                 ap->a_oflags, ap->a_devtype, unit));

    if (sc->sc_opened)
        return EBUSY;

    if ((ap->a_oflags & (FWRITE|FREAD)) != (FWRITE|FREAD))
        return EACCES;

    sc->sc_opened = 1;
    sc->sc_pipeh_in = 0;
    sc->sc_pipeh_out = 0;
    if (usbd_open_pipe(sc->sc_iface,
                       sc->sc_epaddr[RIO_IN], 0, &sc->sc_pipeh_in)
            != USBD_NORMAL_COMPLETION)
    {
        sc->sc_pipeh_in = 0;
        return EIO;
    };
    if (usbd_open_pipe(sc->sc_iface,
                       sc->sc_epaddr[RIO_OUT], 0, &sc->sc_pipeh_out)
            != USBD_NORMAL_COMPLETION)
    {
        usbd_close_pipe(sc->sc_pipeh_in);
        sc->sc_pipeh_in = 0;
        sc->sc_pipeh_out = 0;
        return EIO;
    };
    return 0;
}
示例#8
0
int
kue_open_pipes(struct kue_softc *sc)
{
	usbd_status		err;
	struct kue_chain	*c;
	int			i;

	DPRINTFN(5,("%s: %s: enter\n", sc->kue_dev.dv_xname,__func__));

	/* Open RX and TX pipes. */
	err = usbd_open_pipe(sc->kue_iface, sc->kue_ed[KUE_ENDPT_RX],
	    USBD_EXCLUSIVE_USE, &sc->kue_ep[KUE_ENDPT_RX]);
	if (err) {
		printf("%s: open rx pipe failed: %s\n",
		    sc->kue_dev.dv_xname, usbd_errstr(err));
		return (EIO);
	}

	err = usbd_open_pipe(sc->kue_iface, sc->kue_ed[KUE_ENDPT_TX],
	    USBD_EXCLUSIVE_USE, &sc->kue_ep[KUE_ENDPT_TX]);
	if (err) {
		printf("%s: open tx pipe failed: %s\n",
		    sc->kue_dev.dv_xname, usbd_errstr(err));
		return (EIO);
	}

	/* Start up the receive pipe. */
	for (i = 0; i < KUE_RX_LIST_CNT; i++) {
		c = &sc->kue_cdata.kue_rx_chain[i];
		usbd_setup_xfer(c->kue_xfer, sc->kue_ep[KUE_ENDPT_RX],
		    c, c->kue_buf, KUE_BUFSZ,
		    USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT,
		    kue_rxeof);
		DPRINTFN(5,("%s: %s: start read\n", sc->kue_dev.dv_xname,
			    __func__));
		usbd_transfer(c->kue_xfer);
	}

	return (0);
}
/* alloc/free pipe */
static usbd_status
alloc_pipe(struct umidi_endpoint *ep)
{
	struct umidi_softc *sc = ep->sc;
	usbd_status err;
	usb_endpoint_descriptor_t *epd;
	
	epd = usbd_get_endpoint_descriptor(sc->sc_iface, ep->addr);
	/*
	 * For output, an improvement would be to have a buffer bigger than
	 * wMaxPacketSize by num_jacks-1 additional packet slots; that would
	 * allow out_solicit to fill the buffer to the full packet size in
	 * all cases. But to use usbd_alloc_buffer to get a slightly larger
	 * buffer would not be a good way to do that, because if the addition
	 * would make the buffer exceed USB_MEM_SMALL then a substantially
	 * larger block may be wastefully allocated. Some flavor of double
	 * buffering could serve the same purpose, but would increase the
	 * code complexity, so for now I will live with the current slight
	 * penalty of reducing max transfer size by (num_open-num_scheduled)
	 * packet slots.
	 */
	ep->buffer_size = UGETW(epd->wMaxPacketSize);
	ep->buffer_size -= ep->buffer_size % UMIDI_PACKET_SIZE;

	DPRINTF(("%s: alloc_pipe %p, buffer size %u\n",
	        USBDEVNAME(sc->sc_dev), ep, ep->buffer_size));
	ep->num_scheduled = 0;
	ep->this_schedule = 0;
	ep->next_schedule = 0;
	ep->soliciting = 0;
	ep->armed = 0;
	ep->xfer = usbd_alloc_xfer(sc->sc_udev);
	if (ep->xfer == NULL) {
	    err = USBD_NOMEM;
	    goto quit;
	}
	ep->buffer = usbd_alloc_buffer(ep->xfer, ep->buffer_size);
	if (ep->buffer == NULL) {
	    usbd_free_xfer(ep->xfer);
	    err = USBD_NOMEM;
	    goto quit;
	}
	ep->next_slot = ep->buffer;
	err = usbd_open_pipe(sc->sc_iface, ep->addr, 0, &ep->pipe);
	if (err)
	    usbd_free_xfer(ep->xfer);
	ep->solicit_cookie = softint_establish(SOFTINT_CLOCK, out_solicit, ep);
quit:
	return err;
}
示例#10
0
int
urioopen(dev_t dev, int flag, int mode, struct proc *p)
{
	struct urio_softc *sc;
	usbd_status err;

	if (URIOUNIT(dev) >= urio_cd.cd_ndevs)
		return (ENXIO);
	sc = urio_cd.cd_devs[URIOUNIT(dev)];
	if (sc == NULL)
		return (ENXIO);

	DPRINTFN(5, ("urioopen: flag=%d, mode=%d, unit=%d\n",
		     flag, mode, URIOUNIT(dev)));

	if (usbd_is_dying(sc->sc_udev))
		return (EIO);

	if (sc->sc_in_pipe != NULL)
		return (EBUSY);

	if ((flag & (FWRITE|FREAD)) != (FWRITE|FREAD))
		return (EACCES);

	err = usbd_open_pipe(sc->sc_iface, sc->sc_in_addr, 0, &sc->sc_in_pipe);
	if (err)
		return (EIO);
	err = usbd_open_pipe(sc->sc_iface, sc->sc_out_addr,0,&sc->sc_out_pipe);
	if (err) {
		usbd_close_pipe(sc->sc_in_pipe);
		sc->sc_in_pipe = NULL;
		return (EIO);
	}

	return (0);
}
示例#11
0
void
emdtv_dtv_attach(struct emdtv_softc *sc)
{
	usb_endpoint_descriptor_t *ed;
	usbd_status status;
	int i;

	for (i = 0; i < EMDTV_NXFERS; i++) {
		sc->sc_ix[i].ix_altix = (i & 1) ?
		    &sc->sc_ix[i - 1] : &sc->sc_ix[i + 1];
		sc->sc_ix[i].ix_sc = sc;
	}

	ed = usbd_interface2endpoint_descriptor(sc->sc_iface, 3);
	if (ed == NULL) {
		aprint_error_dev(sc->sc_dev, "couldn't find endpoint 3\n");
		return;
	}
	sc->sc_isoc_maxpacketsize = UGETW(ed->wMaxPacketSize);
	sc->sc_isoc_buflen = sc->sc_isoc_maxpacketsize * EMDTV_NFRAMES;

	aprint_debug_dev(sc->sc_dev, "calling usbd_open_pipe, ep 0x%02x\n",
	    ed->bEndpointAddress);
	status = usbd_open_pipe(sc->sc_iface,
	    ed->bEndpointAddress, USBD_EXCLUSIVE_USE|USBD_MPSAFE,
	    &sc->sc_isoc_pipe);
	if (status != USBD_NORMAL_COMPLETION) {
		aprint_error_dev(sc->sc_dev, "couldn't open isoc pipe\n");
		usbd_set_interface(sc->sc_iface, 0);
		return;
	}

	emdtv_write_1(sc, UR_GET_STATUS, 0x48, 0x00);
	emdtv_write_1(sc, UR_GET_STATUS, 0x12, 0x77);
	usbd_delay_ms(sc->sc_udev, 6);

	emdtv_gpio_ctl(sc, EMDTV_GPIO_ANALOG_ON, false);
	emdtv_gpio_ctl(sc, EMDTV_GPIO_TS1_ON, true);
	emdtv_gpio_ctl(sc, EMDTV_GPIO_TUNER1_ON, true);
	emdtv_gpio_ctl(sc, EMDTV_GPIO_DEMOD1_RESET, true);
	usbd_delay_ms(sc->sc_udev, 100);

	emdtv_dtv_rescan(sc, NULL, NULL);
}
示例#12
0
文件: if_cdce.c 项目: MarginC/kame
Static void
cdce_init(void *xsc)
{
    struct cdce_softc	*sc = xsc;
    struct ifnet		*ifp = GET_IFP(sc);
    struct ue_chain	*c;
    usbd_status		 err;
    int			 i;

    if (ifp->if_flags & IFF_RUNNING)
        return;

    CDCE_LOCK(sc);
    cdce_reset(sc);

    if (usb_ether_tx_list_init(sc, &sc->cdce_cdata,
                               sc->cdce_udev) == ENOBUFS) {
        printf("%s: tx list init failed\n", USBDEVNAME(sc->cdce_dev));
        CDCE_UNLOCK(sc);
        return;
    }

    if (usb_ether_rx_list_init(sc, &sc->cdce_cdata,
                               sc->cdce_udev) == ENOBUFS) {
        printf("%s: rx list init failed\n", USBDEVNAME(sc->cdce_dev));
        CDCE_UNLOCK(sc);
        return;
    }

    /* Maybe set multicast / broadcast here??? */

    err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkin_no,
                         USBD_EXCLUSIVE_USE, &sc->cdce_bulkin_pipe);
    if (err) {
        printf("%s: open rx pipe failed: %s\n", USBDEVNAME(sc->cdce_dev),
               usbd_errstr(err));
        CDCE_UNLOCK(sc);
        return;
    }

    err = usbd_open_pipe(sc->cdce_data_iface, sc->cdce_bulkout_no,
                         USBD_EXCLUSIVE_USE, &sc->cdce_bulkout_pipe);
    if (err) {
        printf("%s: open tx pipe failed: %s\n", USBDEVNAME(sc->cdce_dev),
               usbd_errstr(err));
        CDCE_UNLOCK(sc);
        return;
    }

    for (i = 0; i < UE_RX_LIST_CNT; i++) {
        c = &sc->cdce_cdata.ue_rx_chain[i];
        usbd_setup_xfer(c->ue_xfer, sc->cdce_bulkin_pipe, c,
                        mtod(c->ue_mbuf, char *), UE_BUFSZ, USBD_SHORT_XFER_OK,
                        USBD_NO_TIMEOUT, cdce_rxeof);
        usbd_transfer(c->ue_xfer);
    }

    ifp->if_flags |= IFF_RUNNING;
    ifp->if_flags &= ~IFF_OACTIVE;

    CDCE_UNLOCK(sc);

    return;
}
示例#13
0
文件: udsir.c 项目: ryo/netbsd-src
/* ARGSUSED */
static int
udsir_open(void *h, int flag, int mode, struct lwp *l)
{
	struct udsir_softc *sc = h;
	int error;
	usbd_status err;

	DPRINTFN(0, ("%s: sc=%p\n", __func__, sc));

	err = usbd_open_pipe(sc->sc_iface, sc->sc_rd_addr, 0, &sc->sc_rd_pipe);
	if (err != USBD_NORMAL_COMPLETION) {
		error = EIO;
		goto bad1;
	}
	err = usbd_open_pipe(sc->sc_iface, sc->sc_wr_addr, 0, &sc->sc_wr_pipe);
	if (err != USBD_NORMAL_COMPLETION) {
		error = EIO;
		goto bad2;
	}
	error = usbd_create_xfer(sc->sc_rd_pipe, sc->sc_rd_maxpsz,
	    USBD_SHORT_XFER_OK, 0, &sc->sc_rd_xfer);
	if (error)
		 goto bad3;

	error = usbd_create_xfer(sc->sc_wr_pipe, IRDA_MAX_FRAME_SIZE,
	    USBD_FORCE_SHORT_XFER, 0, &sc->sc_wr_xfer);
	if (error)
		goto bad4;

	sc->sc_rd_buf = usbd_get_buffer(sc->sc_rd_xfer);
	sc->sc_wr_buf = usbd_get_buffer(sc->sc_wr_xfer);

	sc->sc_ur_buf = kmem_alloc(IRDA_MAX_FRAME_SIZE, KM_SLEEP);
	if (sc->sc_ur_buf == NULL) {
		error = ENOMEM;
		goto bad5;
	}

	sc->sc_rd_index = sc->sc_rd_count = 0;
	sc->sc_closing = 0;
	sc->sc_rd_readinprogress = 0;
	sc->sc_rd_expectdataticks = 0;
	sc->sc_ur_framelen = 0;
	sc->sc_rd_err = 0;
	sc->sc_wr_stalewrite = 0;
	sc->sc_direction = udir_idle;
	sc->sc_params.speed = 0;
	sc->sc_params.ebofs = 0;
	sc->sc_params.maxsize = min(sc->sc_rd_maxpsz, sc->sc_wr_maxpsz);

	deframe_init(&sc->sc_framestate, sc->sc_ur_buf, IRDA_MAX_FRAME_SIZE);

	/* Increment reference for thread */
	sc->sc_refcnt++;

	error = kthread_create(PRI_NONE, 0, NULL, udsir_thread, sc,
	    &sc->sc_thread, "%s", device_xname(sc->sc_dev));
	if (error) {
		sc->sc_refcnt--;
		goto bad5;
	}

	return 0;

 bad5:
	usbd_destroy_xfer(sc->sc_wr_xfer);
	sc->sc_wr_xfer = NULL;
 bad4:
	usbd_destroy_xfer(sc->sc_rd_xfer);
	sc->sc_rd_xfer = NULL;
 bad3:
	usbd_close_pipe(sc->sc_wr_pipe);
	sc->sc_wr_pipe = NULL;
 bad2:
	usbd_close_pipe(sc->sc_rd_pipe);
	sc->sc_rd_pipe = NULL;
 bad1:
	return error;
}
示例#14
0
void
smsc_init(void *xsc)
{
	struct smsc_softc	*sc = xsc;
	struct ifnet		*ifp = &sc->sc_ac.ac_if;
	struct smsc_chain	*c;
	usbd_status		 err;
	int			 s, i;
	
	s = splnet();

	/* Cancel pending I/O */
	smsc_stop(sc);

	/* Reset the ethernet interface. */
	smsc_reset(sc);

	/* Init RX ring. */
	if (smsc_rx_list_init(sc) == ENOBUFS) {
		printf("%s: rx list init failed\n", sc->sc_dev.dv_xname);
		splx(s);
		return;
	}

	/* Init TX ring. */
	if (smsc_tx_list_init(sc) == ENOBUFS) {
		printf("%s: tx list init failed\n", sc->sc_dev.dv_xname);
		splx(s);
		return;
	}

	/* Program promiscuous mode and multicast filters. */
	smsc_iff(sc);

	/* Open RX and TX pipes. */
	err = usbd_open_pipe(sc->sc_iface, sc->sc_ed[SMSC_ENDPT_RX],
	    USBD_EXCLUSIVE_USE, &sc->sc_ep[SMSC_ENDPT_RX]);
	if (err) {
		printf("%s: open rx pipe failed: %s\n",
		    sc->sc_dev.dv_xname, usbd_errstr(err));
		splx(s);
		return;
	}

	err = usbd_open_pipe(sc->sc_iface, sc->sc_ed[SMSC_ENDPT_TX],
	    USBD_EXCLUSIVE_USE, &sc->sc_ep[SMSC_ENDPT_TX]);
	if (err) {
		printf("%s: open tx pipe failed: %s\n",
		    sc->sc_dev.dv_xname, usbd_errstr(err));
		splx(s);
		return;
	}

	/* Start up the receive pipe. */
	for (i = 0; i < SMSC_RX_LIST_CNT; i++) {
		c = &sc->sc_cdata.rx_chain[i];
		usbd_setup_xfer(c->sc_xfer, sc->sc_ep[SMSC_ENDPT_RX],
		    c, c->sc_buf, sc->sc_bufsz,
		    USBD_SHORT_XFER_OK | USBD_NO_COPY,
		    USBD_NO_TIMEOUT, smsc_rxeof);
		usbd_transfer(c->sc_xfer);
	}

	/* TCP/UDP checksum offload engines. */
	smsc_sethwcsum(sc);

	/* Indicate we are up and running. */
	ifp->if_flags |= IFF_RUNNING;
	ifp->if_flags &= ~IFF_OACTIVE;

	timeout_add_sec(&sc->sc_stat_ch, 1);

	splx(s);
}
示例#15
0
static int
atausb_attach(device_t dev)
{
    struct atausb_softc *sc = device_get_softc(dev);
    struct usb_attach_arg *uaa = device_get_ivars(dev);
    usb_interface_descriptor_t *id;
    usb_endpoint_descriptor_t *ed;
    usbd_device_handle udev;
    usb_device_request_t request;
    char devinfo[1024], *proto, *subclass;
    u_int8_t maxlun;
    int err, i;

    sc->dev = dev;
    usbd_devinfo(uaa->device, 0, devinfo);
    device_set_desc_copy(dev, devinfo);
    sc->bulkin = sc->bulkout = sc->bulkirq = -1;
    sc->bulkin_pipe = sc->bulkout_pipe= sc->bulkirq_pipe = NULL;
    sc->iface = uaa->iface;
    sc->ifaceno = uaa->ifaceno;
    sc->maxlun = 0;
    sc->timeout = 5000;
    sc->locked_ch = NULL;
    sc->restart_ch = NULL;
    spin_init(&sc->locked_mtx); 

    id = usbd_get_interface_descriptor(sc->iface);
    switch (id->bInterfaceProtocol) {
    case UIPROTO_MASS_BBB:
    case UIPROTO_MASS_BBB_OLD:
	    proto = "Bulk-Only";
	    break;
    case UIPROTO_MASS_CBI:
	    proto = "CBI";
	    break;
    case UIPROTO_MASS_CBI_I:
	    proto = "CBI with CCI";
	    break;
    default:
	    proto = "Unknown";
    }
    switch (id->bInterfaceSubClass) {
    case UISUBCLASS_RBC:
	    subclass = "RBC";
	    break;
    case UISUBCLASS_QIC157:
    case UISUBCLASS_SFF8020I:
    case UISUBCLASS_SFF8070I:
	    subclass = "ATAPI";
	    break;
    case UISUBCLASS_SCSI:
	    subclass = "SCSI";
	    break;
    case UISUBCLASS_UFI:
	    subclass = "UFI";
	    break;
    default:
	    subclass = "Unknown";
    }
    device_printf(dev, "using %s over %s\n", subclass, proto);
    if (strcmp(proto, "Bulk-Only") ||
	(strcmp(subclass, "ATAPI") && strcmp(subclass, "SCSI")))
	return ENXIO;

    for (i = 0 ; i < id->bNumEndpoints ; i++) {
	if (!(ed = usbd_interface2endpoint_descriptor(sc->iface, i))) {
	    device_printf(sc->dev, "could not read endpoint descriptor\n");
	    return ENXIO;
	}
	if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
	    (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) {
	    sc->bulkin = ed->bEndpointAddress;
	}
	if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
	           (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) {
	    sc->bulkout = ed->bEndpointAddress;
	}
	if (id->bInterfaceProtocol == UIPROTO_MASS_CBI_I &&
	           UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
	           (ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT) {
	    sc->bulkirq = ed->bEndpointAddress;
	}
    }

    /* check whether we found at least the endpoints we need */
    if (!sc->bulkin || !sc->bulkout) {
	device_printf(sc->dev, "needed endpoints not found (%d,%d)\n",
		      sc->bulkin, sc->bulkout);
	atausb_detach(dev);
	return ENXIO;
    }

    /* open the pipes */
    if (usbd_open_pipe(sc->iface, sc->bulkout,
		       USBD_EXCLUSIVE_USE, &sc->bulkout_pipe)) {
	device_printf(sc->dev, "cannot open bulkout pipe (%d)\n", sc->bulkout);
	atausb_detach(dev);
	return ENXIO;
    }
    if (usbd_open_pipe(sc->iface, sc->bulkin,
		       USBD_EXCLUSIVE_USE, &sc->bulkin_pipe)) {
	device_printf(sc->dev, "cannot open bulkin pipe (%d)\n", sc->bulkin);
	atausb_detach(dev);
	return ENXIO;
    }
    if (id->bInterfaceProtocol == UIPROTO_MASS_CBI_I) {
	if (usbd_open_pipe(sc->iface, sc->bulkirq,
			   USBD_EXCLUSIVE_USE, &sc->bulkirq_pipe)) {
	    device_printf(sc->dev, "cannot open bulkirq pipe (%d)\n",
	    		  sc->bulkirq);
	    atausb_detach(dev);
	    return ENXIO;
	}
    }
    sc->state = ATAUSB_S_ATTACH;

    /* alloc needed number of transfer handles */
    for (i = 0; i < ATAUSB_T_MAX; i++) {
	sc->transfer[i] = usbd_alloc_xfer(uaa->device);
	if (!sc->transfer[i]) {
	    device_printf(sc->dev, "out of memory\n");
	    atausb_detach(dev);
	    return ENXIO;
	}
    }

    /* driver is ready to process requests here */
    sc->state = ATAUSB_S_IDLE;

    /* get number of devices so we can add matching channels */
    usbd_interface2device_handle(sc->iface, &udev);
    request.bmRequestType = UT_READ_CLASS_INTERFACE;
    request.bRequest = 0xfe; /* GET_MAX_LUN; */
    USETW(request.wValue, 0);
    USETW(request.wIndex, sc->ifaceno);
    USETW(request.wLength, sizeof(maxlun));
    switch ((err = usbd_do_request(udev, &request, &maxlun))) {
    case USBD_NORMAL_COMPLETION:
	if (bootverbose)
	    device_printf(sc->dev, "maxlun=%d\n", maxlun);
	sc->maxlun = maxlun;
	break;
    default:
	if (bootverbose)
	    device_printf(sc->dev, "get maxlun not supported %s\n",
	usbd_errstr(err));
    }

    /* ata channels are children to this USB control device */
    for (i = 0; i <= sc->maxlun; i++) {
	/* XXX TGEN devclass_find_free_unit() implementation */
	int freeunit = 2;
	while (freeunit < devclass_get_maxunit(ata_devclass) &&
	       devclass_get_device(ata_devclass, freeunit) != NULL)
	    freeunit++;
	if (!device_add_child(sc->dev, "ata", freeunit)) {
	    device_printf(sc->dev, "failed to attach ata child device\n");
	    atausb_detach(dev);
	    return ENXIO;
	}
    }
    bus_generic_attach(sc->dev);
    return 0;
}
示例#16
0
Static int
ucomopen(dev_t dev, int flag, int mode, usb_proc_ptr p)
{
	int unit = UCOMUNIT(dev);
	struct ucom_softc *sc;
	usbd_status err;
	struct tty *tp;
	int s;
	int error;

	USB_GET_SC_OPEN(ucom, unit, sc);

	if (sc->sc_dying)
		return (ENXIO);

	tp = sc->sc_tty;

	DPRINTF(("%s: ucomopen: tp = %p\n", USBDEVNAME(sc->sc_dev), tp));

	if (ISSET(tp->t_state, TS_ISOPEN) &&
	    ISSET(tp->t_state, TS_XCLUDE) &&
	    suser(p))
		return (EBUSY);

	/*
	 * Do the following iff this is a first open.
	 */
	s = spltty();
	while (sc->sc_opening)
		tsleep(&sc->sc_opening, PRIBIO, "ucomop", 0);
	sc->sc_opening = 1;

	if (!ISSET(tp->t_state, TS_ISOPEN)) {
		struct termios t;

		sc->sc_poll = 0;
		sc->sc_lsr = sc->sc_msr = sc->sc_mcr = 0;

		tp->t_dev = dev;

		/*
		 * Initialize the termios status to the defaults.  Add in the
		 * sticky bits from TIOCSFLAGS.
		 */
		t.c_ispeed = 0;
		t.c_ospeed = TTYDEF_SPEED;
		t.c_cflag = TTYDEF_CFLAG;
		/* Make sure ucomparam() will do something. */
		tp->t_ospeed = 0;
		(void)ucomparam(tp, &t);
		tp->t_iflag = TTYDEF_IFLAG;
		tp->t_oflag = TTYDEF_OFLAG;
		tp->t_lflag = TTYDEF_LFLAG;
		ttychars(tp);
		ttsetwater(tp);

		/*
		 * Turn on DTR.  We must always do this, even if carrier is not
		 * present, because otherwise we'd have to use TIOCSDTR
		 * immediately after setting CLOCAL, which applications do not
		 * expect.  We always assert DTR while the device is open
		 * unless explicitly requested to deassert it.
		 */
		(void)ucomctl(sc, TIOCM_DTR | TIOCM_RTS, DMBIS);

		/* Device specific open */
		if (sc->sc_callback->ucom_open != NULL) {
			error = sc->sc_callback->ucom_open(sc->sc_parent,
							   sc->sc_portno);
			if (error) {
				ucom_cleanup(sc);
				sc->sc_opening = 0;
				wakeup(&sc->sc_opening);
				splx(s);
				return (error);
			}
		}

		DPRINTF(("ucomopen: open pipes in = %d out = %d\n",
			 sc->sc_bulkin_no, sc->sc_bulkout_no));

		/* Open the bulk pipes */
		/* Bulk-in pipe */
		err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkin_no, 0,
				     &sc->sc_bulkin_pipe);
		if (err) {
			printf("%s: open bulk in error (addr %d): %s\n",
			       USBDEVNAME(sc->sc_dev), sc->sc_bulkin_no,
			       usbd_errstr(err));
			error = EIO;
			goto fail_0;
		}
		/* Bulk-out pipe */
		err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkout_no,
				     USBD_EXCLUSIVE_USE, &sc->sc_bulkout_pipe);
		if (err) {
			printf("%s: open bulk out error (addr %d): %s\n",
			       USBDEVNAME(sc->sc_dev), sc->sc_bulkout_no,
			       usbd_errstr(err));
			error = EIO;
			goto fail_1;
		}

		/* Allocate a request and an input buffer and start reading. */
		sc->sc_ixfer = usbd_alloc_xfer(sc->sc_udev);
		if (sc->sc_ixfer == NULL) {
			error = ENOMEM;
			goto fail_2;
		}

		sc->sc_ibuf = usbd_alloc_buffer(sc->sc_ixfer,
						sc->sc_ibufsizepad);
		if (sc->sc_ibuf == NULL) {
			error = ENOMEM;
			goto fail_3;
		}

		sc->sc_oxfer = usbd_alloc_xfer(sc->sc_udev);
		if (sc->sc_oxfer == NULL) {
			error = ENOMEM;
			goto fail_3;
		}

		sc->sc_obuf = usbd_alloc_buffer(sc->sc_oxfer,
						sc->sc_obufsize +
						sc->sc_opkthdrlen);
		if (sc->sc_obuf == NULL) {
			error = ENOMEM;
			goto fail_4;
		}

		/*
		 * Handle initial DCD.
		 */
		if (ISSET(sc->sc_msr, UMSR_DCD) ||
		    (minor(dev) & UCOM_CALLOUT_MASK))
			(*linesw[tp->t_line].l_modem)(tp, 1);

		ucomstartread(sc);
	}

	sc->sc_opening = 0;
	wakeup(&sc->sc_opening);
	splx(s);

	error = ttyopen(dev, tp);
	if (error)
		goto bad;

	error = (*linesw[tp->t_line].l_open)(dev, tp);
	if (error)
		goto bad;

	disc_optim(tp, &tp->t_termios, sc);

	DPRINTF(("%s: ucomopen: success\n", USBDEVNAME(sc->sc_dev)));

	sc->sc_poll = 1;
	sc->sc_refcnt++;

	return (0);

fail_4:
	usbd_free_xfer(sc->sc_oxfer);
	sc->sc_oxfer = NULL;
fail_3:
	usbd_free_xfer(sc->sc_ixfer);
	sc->sc_ixfer = NULL;
fail_2:
	usbd_close_pipe(sc->sc_bulkout_pipe);
	sc->sc_bulkout_pipe = NULL;
fail_1:
	usbd_close_pipe(sc->sc_bulkin_pipe);
	sc->sc_bulkin_pipe = NULL;
fail_0:
	sc->sc_opening = 0;
	wakeup(&sc->sc_opening);
	splx(s);
	return (error);

bad:
	if (!ISSET(tp->t_state, TS_ISOPEN)) {
		/*
		 * We failed to open the device, and nobody else had it opened.
		 * Clean up the state as appropriate.
		 */
		ucom_cleanup(sc);
	}

	DPRINTF(("%s: ucomopen: failed\n", USBDEVNAME(sc->sc_dev)));

	return (error);
}
示例#17
0
int
wi_usb_open_pipes(struct wi_usb_softc *sc)
{
	usbd_status		err;
	int			error = 0;
	struct wi_usb_chain	*c;
	int			i;

	DPRINTFN(10,("%s: %s: enter\n", sc->wi_usb_dev.dv_xname,__func__));

	sc->wi_usb_refcnt++;

	/* Open RX and TX pipes. */
	err = usbd_open_pipe(sc->wi_usb_iface, sc->wi_usb_ed[WI_USB_ENDPT_RX],
	    USBD_EXCLUSIVE_USE, &sc->wi_usb_ep[WI_USB_ENDPT_RX]);
	if (err) {
		printf("%s: open rx pipe failed: %s\n",
		    sc->wi_usb_dev.dv_xname, usbd_errstr(err));
		error = EIO;
		goto done;
	}

	err = usbd_open_pipe(sc->wi_usb_iface, sc->wi_usb_ed[WI_USB_ENDPT_TX],
	    USBD_EXCLUSIVE_USE, &sc->wi_usb_ep[WI_USB_ENDPT_TX]);
	if (err) {
		printf("%s: open tx pipe failed: %s\n",
		    sc->wi_usb_dev.dv_xname, usbd_errstr(err));
		error = EIO;
		goto done;
	}

	/* is this used? */
	err = usbd_open_pipe_intr(sc->wi_usb_iface,
	    sc->wi_usb_ed[WI_USB_ENDPT_INTR], USBD_EXCLUSIVE_USE,
	    &sc->wi_usb_ep[WI_USB_ENDPT_INTR], sc, &sc->wi_usb_ibuf,
	    WI_USB_INTR_PKTLEN, wi_usb_intr, WI_USB_INTR_INTERVAL);
	if (err) {
		printf("%s: open intr pipe failed: %s\n",
		    sc->wi_usb_dev.dv_xname, usbd_errstr(err));
		error = EIO;
		goto done;
	}

	/* Start up the receive pipe. */
	for (i = 0; i < WI_USB_RX_LIST_CNT; i++) {
		c = &sc->wi_usb_rx_chain[i];
		usbd_setup_xfer(c->wi_usb_xfer, sc->wi_usb_ep[WI_USB_ENDPT_RX],
		    c, c->wi_usb_buf, WI_USB_BUFSZ,
		    USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT,
		    wi_usb_rxeof);
		DPRINTFN(10,("%s: %s: start read\n", sc->wi_usb_dev.dv_xname,
			    __func__));
		usbd_transfer(c->wi_usb_xfer);
	}

done:
	if (--sc->wi_usb_refcnt < 0)
		usb_detach_wakeup(&sc->wi_usb_dev);

	return (error);
}
示例#18
0
int
ucomopen(dev_t dev, int flag, int mode, struct proc *p)
{
	int unit = UCOMUNIT(dev);
	usbd_status err;
	struct ucom_softc *sc;
	struct tty *tp;
	struct termios t;
	int s;
	int error;

	if (unit >= ucom_cd.cd_ndevs)
		return (ENXIO);
	sc = ucom_cd.cd_devs[unit];
	if (sc == NULL)
		return (ENXIO);

	if (sc->sc_dying)
		return (EIO);

	if (ISSET(sc->sc_dev.dv_flags, DVF_ACTIVE) == 0)
		return (ENXIO);

	/* open the pipes if this is the first open */
	ucom_lock(sc);
	if (sc->sc_open++ == 0) {
		s = splusb();

		DPRINTF(("ucomopen: open pipes in=%d out=%d\n",
		    sc->sc_bulkin_no, sc->sc_bulkout_no));
		DPRINTF(("ucomopen: hid %p pipes in=%p out=%p\n",
		    sc->sc_uhidev, sc->sc_ipipe, sc->sc_opipe));

		if (sc->sc_bulkin_no != -1) {

			/* Open the bulk pipes */
			err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkin_no, 0,
			    &sc->sc_bulkin_pipe);
			if (err) {
				DPRINTF(("%s: open bulk out error (addr %d), err=%s\n",
				    sc->sc_dev.dv_xname, sc->sc_bulkin_no,
				    usbd_errstr(err)));
				error = EIO;
				goto fail_0;
			}
			err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkout_no,
			    USBD_EXCLUSIVE_USE, &sc->sc_bulkout_pipe);
			if (err) {
				DPRINTF(("%s: open bulk in error (addr %d), err=%s\n",
				    sc->sc_dev.dv_xname, sc->sc_bulkout_no,
				    usbd_errstr(err)));
				error = EIO;
				goto fail_1;
			}

			/* Allocate a request and an input buffer and start reading. */
			sc->sc_ixfer = usbd_alloc_xfer(sc->sc_udev);
			if (sc->sc_ixfer == NULL) {
				error = ENOMEM;
				goto fail_2;
			}

			sc->sc_ibuf = usbd_alloc_buffer(sc->sc_ixfer,
			    sc->sc_ibufsizepad);
			if (sc->sc_ibuf == NULL) {
				error = ENOMEM;
				goto fail_2;
			}

			sc->sc_oxfer = usbd_alloc_xfer(sc->sc_udev);
			if (sc->sc_oxfer == NULL) {
				error = ENOMEM;
				goto fail_3;
			}
		} else {
			/*
			 * input/output pipes and xfers already allocated
			 * as is the input buffer.
			 */
			sc->sc_ipipe = sc->sc_uhidev->sc_ipipe;
			sc->sc_ixfer = sc->sc_uhidev->sc_ixfer;
			sc->sc_opipe = sc->sc_uhidev->sc_opipe;
			sc->sc_oxfer = sc->sc_uhidev->sc_oxfer;
		}

		sc->sc_obuf = usbd_alloc_buffer(sc->sc_oxfer,
		    sc->sc_obufsize + sc->sc_opkthdrlen);
		if (sc->sc_obuf == NULL) {
			error = ENOMEM;
			goto fail_4;
		}

		if (sc->sc_methods->ucom_open != NULL) {
			error = sc->sc_methods->ucom_open(sc->sc_parent,
			    sc->sc_portno);
			if (error) {
				ucom_cleanup(sc);
				splx(s);
				ucom_unlock(sc);
				return (error);
			}
		}

		ucom_status_change(sc);

		ucomstartread(sc);

		splx(s);
	}
	ucom_unlock(sc);

	s = spltty();
	tp = sc->sc_tty;
	splx(s);

	DPRINTF(("ucomopen: unit=%d, tp=%p\n", unit, tp));

	tp->t_dev = dev;
	if (!ISSET(tp->t_state, TS_ISOPEN)) {
		SET(tp->t_state, TS_WOPEN);
		ttychars(tp);

		/*
		 * Initialize the termios status to the defaults.  Add in the
		 * sticky bits from TIOCSFLAGS.
		 */
		t.c_ispeed = 0;
		t.c_ospeed = TTYDEF_SPEED;
		t.c_cflag = TTYDEF_CFLAG;
		if (ISSET(sc->sc_swflags, TIOCFLAG_CLOCAL))
			SET(t.c_cflag, CLOCAL);
		if (ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS))
			SET(t.c_cflag, CRTSCTS);
		if (ISSET(sc->sc_swflags, TIOCFLAG_MDMBUF))
			SET(t.c_cflag, MDMBUF);

		/* Make sure ucomparam() will do something. */
		tp->t_ospeed = 0;
		(void) ucomparam(tp, &t);
		tp->t_iflag = TTYDEF_IFLAG;
		tp->t_oflag = TTYDEF_OFLAG;
		tp->t_lflag = TTYDEF_LFLAG;

		s = spltty();
		ttsetwater(tp);

		/*
		 * Turn on DTR.  We must always do this, even if carrier is not
		 * present, because otherwise we'd have to use TIOCSDTR
		 * immediately after setting CLOCAL, which applications do not
		 * expect.  We always assert DTR while the device is open
		 * unless explicitly requested to deassert it.
		 */
		ucom_dtr(sc, 1);

		/* XXX CLR(sc->sc_rx_flags, RX_ANY_BLOCK);*/
		ucom_hwiflow(sc);

		if (ISSET(sc->sc_swflags, TIOCFLAG_SOFTCAR) || UCOMCUA(dev) ||
		    ISSET(sc->sc_msr, UMSR_DCD) || ISSET(tp->t_cflag, MDMBUF))
			SET(tp->t_state, TS_CARR_ON);
		else
			CLR(tp->t_state, TS_CARR_ON);
	} else if (ISSET(tp->t_state, TS_XCLUDE) && p->p_ucred->cr_uid != 0) {
		error = EBUSY;
		goto bad;
	} else
		s = spltty();

	if (UCOMCUA(dev)) {
		if (ISSET(tp->t_state, TS_ISOPEN)) {
			/* Someone is already dialed in */
			error = EBUSY;
			goto bad1;
		}
		sc->sc_cua = 1;
	} else {
		/* tty (not cua) device, wait for carrier */
		if (ISSET(flag, O_NONBLOCK)) {
			if (sc->sc_cua) {
				error = EBUSY;
				goto bad1;
			}
		} else {
			while (sc->sc_cua || (!ISSET(tp->t_cflag, CLOCAL) &&
			    !ISSET(tp->t_state, TS_CARR_ON))) {
				SET(tp->t_state, TS_WOPEN);
				error = ttysleep(tp, &tp->t_rawq,
				    TTIPRI | PCATCH, ttopen, 0);
				/*
				 * If TS_WOPEN has been reset, that means the
				 * cua device has been closed.  We don't want
				 * to fail in that case, so just go around
				 * again.
				 */
				if (error && ISSET(tp->t_state, TS_WOPEN)) {
					CLR(tp->t_state, TS_WOPEN);
					goto bad1;
				}
			}
		}
	}
	splx(s);

	error = ttyopen(UCOMUNIT(dev), tp);
	if (error)
		goto bad;

	error = (*LINESW(tp, l_open))(dev, tp);
	if (error)
		goto bad;

	return (0);

fail_4:
	if (sc->sc_uhidev == NULL)
		usbd_free_xfer(sc->sc_oxfer);
	sc->sc_oxfer = NULL;
fail_3:
	usbd_free_xfer(sc->sc_ixfer);
	sc->sc_ixfer = NULL;
fail_2:
	usbd_close_pipe(sc->sc_bulkout_pipe);
	sc->sc_bulkout_pipe = NULL;
fail_1:
	usbd_close_pipe(sc->sc_bulkin_pipe);
	sc->sc_bulkin_pipe = NULL;
fail_0:
	splx(s);
	ucom_unlock(sc);
	return (error);

bad1:
	splx(s);
bad:
	ucom_lock(sc);
	ucom_cleanup(sc);
	ucom_unlock(sc);

	return (error);
}
示例#19
0
文件: ugen.c 项目: SylvestreG/bitrig
int
ugenopen(dev_t dev, int flag, int mode, struct proc *p)
{
	struct ugen_softc *sc;
	int unit = UGENUNIT(dev);
	int endpt = UGENENDPOINT(dev);
	usb_endpoint_descriptor_t *edesc;
	struct ugen_endpoint *sce;
	int dir, isize;
	usbd_status err;
	struct usbd_xfer *xfer;
	void *buf;
	int i, j;

	if (unit >= ugen_cd.cd_ndevs)
		return (ENXIO);
	sc = ugen_cd.cd_devs[unit];
	if (sc == NULL)
		return (ENXIO);

	DPRINTFN(5, ("ugenopen: flag=%d, mode=%d, unit=%d endpt=%d\n",
		     flag, mode, unit, endpt));

	if (sc == NULL || usbd_is_dying(sc->sc_udev))
		return (ENXIO);

	if (sc->sc_is_open[endpt])
		return (EBUSY);

	if (endpt == USB_CONTROL_ENDPOINT) {
		sc->sc_is_open[USB_CONTROL_ENDPOINT] = 1;
		return (0);
	}

	/* Make sure there are pipes for all directions. */
	for (dir = OUT; dir <= IN; dir++) {
		if (flag & (dir == OUT ? FWRITE : FREAD)) {
			sce = &sc->sc_endpoints[endpt][dir];
			if (sce == 0 || sce->edesc == 0)
				return (ENXIO);
		}
	}

	/* Actually open the pipes. */
	/* XXX Should back out properly if it fails. */
	for (dir = OUT; dir <= IN; dir++) {
		if (!(flag & (dir == OUT ? FWRITE : FREAD)))
			continue;
		sce = &sc->sc_endpoints[endpt][dir];
		sce->state = 0;
		sce->timeout = USBD_NO_TIMEOUT;
		DPRINTFN(5, ("ugenopen: sc=%p, endpt=%d, dir=%d, sce=%p\n",
			     sc, endpt, dir, sce));
		edesc = sce->edesc;
		switch (edesc->bmAttributes & UE_XFERTYPE) {
		case UE_INTERRUPT:
			if (dir == OUT) {
				err = usbd_open_pipe(sce->iface,
				    edesc->bEndpointAddress, 0, &sce->pipeh);
				if (err)
					return (EIO);
				break;
			}
			isize = UGETW(edesc->wMaxPacketSize);
			if (isize == 0)	/* shouldn't happen */
				return (EINVAL);
			sce->ibuf = malloc(isize, M_USBDEV, M_WAITOK);
			DPRINTFN(5, ("ugenopen: intr endpt=%d,isize=%d\n",
				     endpt, isize));
			clalloc(&sce->q, UGEN_IBSIZE, 0);
			err = usbd_open_pipe_intr(sce->iface,
				  edesc->bEndpointAddress,
				  USBD_SHORT_XFER_OK, &sce->pipeh, sce,
				  sce->ibuf, isize, ugenintr,
				  USBD_DEFAULT_INTERVAL);
			if (err) {
				free(sce->ibuf, M_USBDEV, 0);
				clfree(&sce->q);
				return (EIO);
			}
			DPRINTFN(5, ("ugenopen: interrupt open done\n"));
			break;
		case UE_BULK:
			err = usbd_open_pipe(sce->iface,
				  edesc->bEndpointAddress, 0, &sce->pipeh);
			if (err)
				return (EIO);
			break;
		case UE_ISOCHRONOUS:
			if (dir == OUT)
				return (EINVAL);
			isize = UGETW(edesc->wMaxPacketSize);
			if (isize == 0)	/* shouldn't happen */
				return (EINVAL);
			sce->ibuf = malloc(isize * UGEN_NISOFRAMES,
				M_USBDEV, M_WAITOK);
			sce->cur = sce->fill = sce->ibuf;
			sce->limit = sce->ibuf + isize * UGEN_NISOFRAMES;
			DPRINTFN(5, ("ugenopen: isoc endpt=%d, isize=%d\n",
				     endpt, isize));
			err = usbd_open_pipe(sce->iface,
				  edesc->bEndpointAddress, 0, &sce->pipeh);
			if (err) {
				free(sce->ibuf, M_USBDEV, 0);
				return (EIO);
			}
			for(i = 0; i < UGEN_NISOREQS; ++i) {
				sce->isoreqs[i].sce = sce;
				xfer = usbd_alloc_xfer(sc->sc_udev);
				if (xfer == 0)
					goto bad;
				sce->isoreqs[i].xfer = xfer;
				buf = usbd_alloc_buffer
					(xfer, isize * UGEN_NISORFRMS);
				if (buf == 0) {
					i++;
					goto bad;
				}
				sce->isoreqs[i].dmabuf = buf;
				for(j = 0; j < UGEN_NISORFRMS; ++j)
					sce->isoreqs[i].sizes[j] = isize;
				usbd_setup_isoc_xfer
					(xfer, sce->pipeh, &sce->isoreqs[i],
					 sce->isoreqs[i].sizes,
					 UGEN_NISORFRMS, USBD_NO_COPY,
					 ugen_isoc_rintr);
				(void)usbd_transfer(xfer);
			}
			DPRINTFN(5, ("ugenopen: isoc open done\n"));
			break;
		bad:
			while (--i >= 0) /* implicit buffer free */
				usbd_free_xfer(sce->isoreqs[i].xfer);
			return (ENOMEM);
		case UE_CONTROL:
			sce->timeout = USBD_DEFAULT_TIMEOUT;
			return (EINVAL);
		}
	}
	sc->sc_is_open[endpt] = 1;
	return (0);
}
示例#20
0
int
ucomopen(dev_t dev, int flag, int mode, struct lwp *l)
{
	int unit = UCOMUNIT(dev);
	usbd_status err;
	struct ucom_softc *sc = device_lookup_private(&ucom_cd, unit);
	struct ucom_buffer *ub;
	struct tty *tp;
	int s, i;
	int error;

	if (sc == NULL)
		return (ENXIO);

	if (sc->sc_dying)
		return (EIO);

	if (!device_is_active(sc->sc_dev))
		return (ENXIO);

	tp = sc->sc_tty;

	DPRINTF(("ucomopen: unit=%d, tp=%p\n", unit, tp));

	if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp))
		return (EBUSY);

	s = spltty();

	/*
	 * Do the following iff this is a first open.
	 */
	while (sc->sc_opening)
		tsleep(&sc->sc_opening, PRIBIO, "ucomop", 0);

	if (sc->sc_dying) {
		splx(s);
		return (EIO);
	}
	sc->sc_opening = 1;

	if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
		struct termios t;

		tp->t_dev = dev;

		if (sc->sc_methods->ucom_open != NULL) {
			error = sc->sc_methods->ucom_open(sc->sc_parent,
							  sc->sc_portno);
			if (error) {
				ucom_cleanup(sc);
				sc->sc_opening = 0;
				wakeup(&sc->sc_opening);
				splx(s);
				return (error);
			}
		}

		ucom_status_change(sc);

		/*
		 * Initialize the termios status to the defaults.  Add in the
		 * sticky bits from TIOCSFLAGS.
		 */
		t.c_ispeed = 0;
		t.c_ospeed = TTYDEF_SPEED;
		t.c_cflag = TTYDEF_CFLAG;
		if (ISSET(sc->sc_swflags, TIOCFLAG_CLOCAL))
			SET(t.c_cflag, CLOCAL);
		if (ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS))
			SET(t.c_cflag, CRTSCTS);
		if (ISSET(sc->sc_swflags, TIOCFLAG_MDMBUF))
			SET(t.c_cflag, MDMBUF);
		/* Make sure ucomparam() will do something. */
		tp->t_ospeed = 0;
		(void) ucomparam(tp, &t);
		tp->t_iflag = TTYDEF_IFLAG;
		tp->t_oflag = TTYDEF_OFLAG;
		tp->t_lflag = TTYDEF_LFLAG;
		ttychars(tp);
		ttsetwater(tp);

		/*
		 * Turn on DTR.  We must always do this, even if carrier is not
		 * present, because otherwise we'd have to use TIOCSDTR
		 * immediately after setting CLOCAL, which applications do not
		 * expect.  We always assert DTR while the device is open
		 * unless explicitly requested to deassert it.  Ditto RTS.
		 */
		ucom_dtr(sc, 1);
		ucom_rts(sc, 1);		

		DPRINTF(("ucomopen: open pipes in=%d out=%d\n",
			 sc->sc_bulkin_no, sc->sc_bulkout_no));

		/* Open the bulk pipes */
		err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkin_no,
				     USBD_EXCLUSIVE_USE, &sc->sc_bulkin_pipe);
		if (err) {
			DPRINTF(("%s: open bulk in error (addr %d), err=%s\n",
				 USBDEVNAME(sc->sc_dev), sc->sc_bulkin_no,
				 usbd_errstr(err)));
			error = EIO;
			goto fail_0;
		}
		err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkout_no,
				     USBD_EXCLUSIVE_USE, &sc->sc_bulkout_pipe);
		if (err) {
			DPRINTF(("%s: open bulk out error (addr %d), err=%s\n",
				 USBDEVNAME(sc->sc_dev), sc->sc_bulkout_no,
				 usbd_errstr(err)));
			error = EIO;
			goto fail_1;
		}

		sc->sc_rx_unblock = 0;
		sc->sc_rx_stopped = 0;
		sc->sc_tx_stopped = 0;

		memset(sc->sc_ibuff, 0, sizeof(sc->sc_ibuff));
		memset(sc->sc_obuff, 0, sizeof(sc->sc_obuff));

		SIMPLEQ_INIT(&sc->sc_ibuff_empty);
		SIMPLEQ_INIT(&sc->sc_ibuff_full);
		SIMPLEQ_INIT(&sc->sc_obuff_free);
		SIMPLEQ_INIT(&sc->sc_obuff_full);

		/* Allocate input buffers */
		for (ub = &sc->sc_ibuff[0]; ub != &sc->sc_ibuff[UCOM_IN_BUFFS];
		    ub++) {
			ub->ub_xfer = usbd_alloc_xfer(sc->sc_udev);
			if (ub->ub_xfer == NULL) {
				error = ENOMEM;
				goto fail_2;
			}
			ub->ub_data = usbd_alloc_buffer(ub->ub_xfer,
			    sc->sc_ibufsizepad);
			if (ub->ub_data == NULL) {
				error = ENOMEM;
				goto fail_2;
			}

			if (ucomsubmitread(sc, ub) != USBD_NORMAL_COMPLETION) {
				error = EIO;
				goto fail_2;
			}
		}

		for (ub = &sc->sc_obuff[0]; ub != &sc->sc_obuff[UCOM_OUT_BUFFS];
		    ub++) {
			ub->ub_xfer = usbd_alloc_xfer(sc->sc_udev);
			if (ub->ub_xfer == NULL) {
				error = ENOMEM;
				goto fail_2;
			}
			ub->ub_data = usbd_alloc_buffer(ub->ub_xfer,
			    sc->sc_obufsize);
			if (ub->ub_data == NULL) {
				error = ENOMEM;
				goto fail_2;
			}

			SIMPLEQ_INSERT_TAIL(&sc->sc_obuff_free, ub, ub_link);
		}

	}
	sc->sc_opening = 0;
	wakeup(&sc->sc_opening);
	splx(s);

	error = ttyopen(tp, UCOMDIALOUT(dev), ISSET(flag, O_NONBLOCK));
	if (error)
		goto bad;

	error = (*tp->t_linesw->l_open)(dev, tp);
	if (error)
		goto bad;

	return (0);

fail_2:
	usbd_abort_pipe(sc->sc_bulkin_pipe);
	for (i = 0; i < UCOM_IN_BUFFS; i++) {
		if (sc->sc_ibuff[i].ub_xfer != NULL) {
			usbd_free_xfer(sc->sc_ibuff[i].ub_xfer);
			sc->sc_ibuff[i].ub_xfer = NULL;
			sc->sc_ibuff[i].ub_data = NULL;
		}
	}
	usbd_abort_pipe(sc->sc_bulkout_pipe);
	for (i = 0; i < UCOM_OUT_BUFFS; i++) {
		if (sc->sc_obuff[i].ub_xfer != NULL) {
			usbd_free_xfer(sc->sc_obuff[i].ub_xfer);
			sc->sc_obuff[i].ub_xfer = NULL;
			sc->sc_obuff[i].ub_data = NULL;
		}
	}

	usbd_close_pipe(sc->sc_bulkout_pipe);
	sc->sc_bulkout_pipe = NULL;
fail_1:
	usbd_close_pipe(sc->sc_bulkin_pipe);
	sc->sc_bulkin_pipe = NULL;
fail_0:
	sc->sc_opening = 0;
	wakeup(&sc->sc_opening);
	splx(s);
	return (error);

bad:
	s = spltty();
	CLR(tp->t_state, TS_BUSY);
	if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
		/*
		 * We failed to open the device, and nobody else had it opened.
		 * Clean up the state as appropriate.
		 */
		ucom_cleanup(sc);
	}
	splx(s);

	return (error);
}
示例#21
0
/*
 * Init
 */
static void
lgue_init(void *xsc)
{
	struct lgue_softc *sc;
	struct ifnet *ifp;
	usbd_status err;

	sc = xsc;
	ifp = &sc->lgue_arpcom.ac_if;

	if (ifp->if_flags & IFF_RUNNING)
		return;

	/* Create RX and TX bufs */
	if (sc->lgue_tx_xfer == NULL) {
		sc->lgue_tx_xfer = usbd_alloc_xfer(sc->lgue_udev);
		if (sc->lgue_tx_xfer == NULL) {
			if_printf(ifp, "tx buffer allocate failed\n");
			return;
		}
	}
	sc->lgue_tx_buf = kmalloc(LGUE_BUFSZ, M_USBDEV, M_WAITOK);

	if (sc->lgue_rx_xfer == NULL) {
		sc->lgue_rx_xfer = usbd_alloc_xfer(sc->lgue_udev);
		if (sc->lgue_rx_xfer == NULL) {
			if_printf(ifp, "rx buffer allocate failed\n");
			return;
		}
	}
	sc->lgue_rx_buf = kmalloc(LGUE_BUFSZ, M_USBDEV, M_WAITOK);

	/* Create INTR buf */
	if (sc->lgue_intr_xfer == NULL) {
		sc->lgue_intr_xfer = usbd_alloc_xfer(sc->lgue_udev);
		if (sc->lgue_intr_xfer == NULL) {
			if_printf(ifp, "intr buffer allocate failed\n");
			return;
		}
	}
	sc->lgue_intr_buf = kmalloc(LGUE_BUFSZ, M_USBDEV, M_WAITOK);

	/* Open RX and TX pipes. */
	err = usbd_open_pipe(sc->lgue_data_iface, sc->lgue_ed[LGUE_ENDPT_RX],
	    USBD_EXCLUSIVE_USE, &sc->lgue_ep[LGUE_ENDPT_RX]);
	if (err) {
		if_printf(ifp, "open RX pipe failed: %s\n", usbd_errstr(err));
		return;
	}
	err = usbd_open_pipe(sc->lgue_data_iface, sc->lgue_ed[LGUE_ENDPT_TX],
	    USBD_EXCLUSIVE_USE, &sc->lgue_ep[LGUE_ENDPT_TX]);
	if (err) {
		if_printf(ifp, "open TX pipe failed: %s\n", usbd_errstr(err));
		return;
	}
	/* Open INTR pipe. */
	err = usbd_open_pipe(sc->lgue_ctl_iface, sc->lgue_ed[LGUE_ENDPT_INTR],
	    USBD_EXCLUSIVE_USE, &sc->lgue_ep[LGUE_ENDPT_INTR]);
	if (err) {
		if_printf(ifp, "open INTR pipe failed: %s\n", usbd_errstr(err));
		return;
	}

	/* Create internal queue */
	STAILQ_INIT(&sc->lgue_tx_queue);

	ifp->if_flags |= IFF_RUNNING;
	ifq_clr_oactive(&ifp->if_snd);

	sc->lgue_dying = 0;

	lgue_rxstart(ifp);
	lgue_intrstart(ifp);
}
示例#22
0
int
smsc_init(struct ifnet *ifp)
{
    struct smsc_softc	*sc = ifp->if_softc;
    struct smsc_chain	*c;
    usbd_status		 err;
    int			 s, i;

    if (sc->sc_dying)
        return EIO;

    s = splnet();

    /* Cancel pending I/O */
    if (ifp->if_flags & IFF_RUNNING)
        smsc_stop(ifp, 1);

    /* Reset the ethernet interface. */
    smsc_reset(sc);

    /* Init RX ring. */
    if (smsc_rx_list_init(sc) == ENOBUFS) {
        aprint_error_dev(sc->sc_dev, "rx list init failed\n");
        splx(s);
        return EIO;
    }

    /* Init TX ring. */
    if (smsc_tx_list_init(sc) == ENOBUFS) {
        aprint_error_dev(sc->sc_dev, "tx list init failed\n");
        splx(s);
        return EIO;
    }

    /* Load the multicast filter. */
    smsc_setmulti(sc);

    /* TCP/UDP checksum offload engines. */
    smsc_sethwcsum(sc);

    /* Open RX and TX pipes. */
    err = usbd_open_pipe(sc->sc_iface, sc->sc_ed[SMSC_ENDPT_RX],
                         USBD_EXCLUSIVE_USE, &sc->sc_ep[SMSC_ENDPT_RX]);
    if (err) {
        printf("%s: open rx pipe failed: %s\n",
               device_xname(sc->sc_dev), usbd_errstr(err));
        splx(s);
        return EIO;
    }

    err = usbd_open_pipe(sc->sc_iface, sc->sc_ed[SMSC_ENDPT_TX],
                         USBD_EXCLUSIVE_USE, &sc->sc_ep[SMSC_ENDPT_TX]);
    if (err) {
        printf("%s: open tx pipe failed: %s\n",
               device_xname(sc->sc_dev), usbd_errstr(err));
        splx(s);
        return EIO;
    }

    /* Start up the receive pipe. */
    for (i = 0; i < SMSC_RX_LIST_CNT; i++) {
        c = &sc->sc_cdata.rx_chain[i];
        usbd_setup_xfer(c->sc_xfer, sc->sc_ep[SMSC_ENDPT_RX],
                        c, c->sc_buf, sc->sc_bufsz,
                        USBD_SHORT_XFER_OK | USBD_NO_COPY,
                        USBD_NO_TIMEOUT, smsc_rxeof);
        usbd_transfer(c->sc_xfer);
    }

    /* Indicate we are up and running. */
    ifp->if_flags |= IFF_RUNNING;
    ifp->if_flags &= ~IFF_OACTIVE;

    splx(s);

    callout_reset(&sc->sc_stat_ch, hz, smsc_tick, sc);

    return 0;
}
示例#23
0
int
uhidev_open(struct uhidev *scd)
{
	struct uhidev_softc *sc = scd->sc_parent;
	usbd_status err;
	int error;

	DPRINTF(("uhidev_open: open pipe, state=%d refcnt=%d\n",
		 scd->sc_state, sc->sc_refcnt));

	if (scd->sc_state & UHIDEV_OPEN)
		return (EBUSY);
	scd->sc_state |= UHIDEV_OPEN;
	if (sc->sc_refcnt++)
		return (0);

	if (sc->sc_isize == 0)
		return (0);

	sc->sc_ibuf = malloc(sc->sc_isize, M_USBDEV, M_WAITOK);

	/* Set up input interrupt pipe. */
	DPRINTF(("uhidev_open: isize=%d, ep=0x%02x\n", sc->sc_isize,
	    sc->sc_iep_addr));
		
	err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_iep_addr,
		  USBD_SHORT_XFER_OK, &sc->sc_ipipe, sc, sc->sc_ibuf,
		  sc->sc_isize, uhidev_intr, USBD_DEFAULT_INTERVAL);
	if (err != USBD_NORMAL_COMPLETION) {
		DPRINTF(("uhidopen: usbd_open_pipe_intr failed, "
		    "error=%d\n", err));
		error = EIO;
		goto out1;
	}

	DPRINTF(("uhidev_open: sc->sc_ipipe=%p\n", sc->sc_ipipe));

	sc->sc_ixfer = usbd_alloc_xfer(sc->sc_udev);
	if (sc->sc_ixfer == NULL) {
		DPRINTF(("uhidev_open: couldn't allocate an xfer\n"));
		error = ENOMEM;
		goto out1; // xxxx
	}

	/*
	 * Set up output interrupt pipe if an output interrupt endpoint
	 * exists.
	 */
	if (sc->sc_oep_addr != -1) {
		DPRINTF(("uhidev_open: oep=0x%02x\n", sc->sc_oep_addr));

		err = usbd_open_pipe(sc->sc_iface, sc->sc_oep_addr,
		    0, &sc->sc_opipe);

		if (err != USBD_NORMAL_COMPLETION) {
			DPRINTF(("uhidev_open: usbd_open_pipe failed, "
			    "error=%d\n", err));
			error = EIO;
			goto out2;
		}
		DPRINTF(("uhidev_open: sc->sc_opipe=%p\n", sc->sc_opipe));

		sc->sc_oxfer = usbd_alloc_xfer(sc->sc_udev);
		if (sc->sc_oxfer == NULL) {
			DPRINTF(("uhidev_open: couldn't allocate an xfer\n"));
			error = ENOMEM;
			goto out3;
		}

		sc->sc_owxfer = usbd_alloc_xfer(sc->sc_udev);
		if (sc->sc_owxfer == NULL) {
			DPRINTF(("uhidev_open: couldn't allocate owxfer\n"));
			error = ENOMEM;
			goto out3;
		}
	}
	
	return (0);

out3:
	/* Abort output pipe */
	usbd_close_pipe(sc->sc_opipe);
out2:
	/* Abort input pipe */
	usbd_close_pipe(sc->sc_ipipe);
out1:
	DPRINTF(("uhidev_open: failed in someway"));
	free(sc->sc_ibuf, M_USBDEV);
	scd->sc_state &= ~UHIDEV_OPEN;
	sc->sc_refcnt = 0;
	sc->sc_ipipe = NULL;
	sc->sc_opipe = NULL;
	if (sc->sc_oxfer != NULL) {
		usbd_free_xfer(sc->sc_oxfer);
		sc->sc_oxfer = NULL;
	}
	if (sc->sc_owxfer != NULL) {
		usbd_free_xfer(sc->sc_owxfer);
		sc->sc_owxfer = NULL;
	}
	return (error);
}
示例#24
0
/*******************************************************************************
 *
 * Bluetooth Unit/USB callbacks
 *
 * All of this will be called at the IPL_ we specified above
 */
int
ubt_enable(struct device *self)
{
	struct ubt_softc *sc = device_get_softc(self);
	usbd_status err;
	int i, error;

	DPRINTFN(1, "%s: sc=%p\n", __func__, sc);

	if (sc->sc_enabled)
		return 0;

	crit_enter();

	/* Events */
	sc->sc_evt_buf = kmalloc(UBT_BUFSIZ_EVENT, M_USBDEV, M_NOWAIT);
	if (sc->sc_evt_buf == NULL) {
		error = ENOMEM;
		goto bad;
	}

	err = usbd_open_pipe_intr(sc->sc_iface0,
				  sc->sc_evt_addr,
				  USBD_SHORT_XFER_OK,
				  &sc->sc_evt_pipe,
				  sc,
				  sc->sc_evt_buf,
				  UBT_BUFSIZ_EVENT,
				  ubt_recv_event,
				  UBT_INTR_TIMEOUT);
	if (err != USBD_NORMAL_COMPLETION) {
		error = EIO;
		kprintf("can't open events pipe_intr\n");
		goto bad;
	}

	/* Commands */
	sc->sc_cmd_xfer = usbd_alloc_xfer(sc->sc_udev);
	if (sc->sc_cmd_xfer == NULL) {
		kprintf("can't allocate cmd_xfer\n");
		error = ENOMEM;
		goto bad;
	}
	sc->sc_cmd_buf = usbd_alloc_buffer(sc->sc_cmd_xfer, UBT_BUFSIZ_CMD);
	if (sc->sc_cmd_buf == NULL) {
		kprintf("can't allocate cmd_buf\n");
		error = ENOMEM;
		goto bad;
	}
	sc->sc_cmd_busy = 0;

	/* ACL read */
	err = usbd_open_pipe(sc->sc_iface0, sc->sc_aclrd_addr,
				USBD_EXCLUSIVE_USE, &sc->sc_aclrd_pipe);
	if (err != USBD_NORMAL_COMPLETION) {
		kprintf("can't open aclrd pipe\n");
		error = EIO;
		goto bad;
	}
	sc->sc_aclrd_xfer = usbd_alloc_xfer(sc->sc_udev);
	if (sc->sc_aclrd_xfer == NULL) {
		kprintf("can't allocate aclrd_xfer\n");
		error = ENOMEM;
		goto bad;
	}
	sc->sc_aclrd_buf = usbd_alloc_buffer(sc->sc_aclrd_xfer, UBT_BUFSIZ_ACL);
	if (sc->sc_aclrd_buf == NULL) {
		kprintf("can't allocate aclrd_buf\n");
		error = ENOMEM;
		goto bad;
	}
	sc->sc_aclrd_busy = 0;
	ubt_recv_acl_start(sc);

	/* ACL write */
	err = usbd_open_pipe(sc->sc_iface0, sc->sc_aclwr_addr,
				USBD_EXCLUSIVE_USE, &sc->sc_aclwr_pipe);
	if (err != USBD_NORMAL_COMPLETION) {
		kprintf("can't open aclwr pipe\n");
		error = EIO;
		goto bad;
	}
	sc->sc_aclwr_xfer = usbd_alloc_xfer(sc->sc_udev);
	if (sc->sc_aclwr_xfer == NULL) {
		kprintf("can't allocate aclwr_xfer\n");
		error = ENOMEM;
		goto bad;
	}
	sc->sc_aclwr_buf = usbd_alloc_buffer(sc->sc_aclwr_xfer, UBT_BUFSIZ_ACL);
	if (sc->sc_aclwr_buf == NULL) {
		kprintf("can't allocate aclwr_buf\n");
		error = ENOMEM;
		goto bad;
	}
	sc->sc_aclwr_busy = 0;

	/* SCO read */
	if (sc->sc_scord_size > 0) {
		err = usbd_open_pipe(sc->sc_iface1, sc->sc_scord_addr,
					USBD_EXCLUSIVE_USE, &sc->sc_scord_pipe);
		if (err != USBD_NORMAL_COMPLETION) {
			error = EIO;
			goto bad;
		}

		for (i = 0 ; i < UBT_NXFERS ; i++) {
			sc->sc_scord[i].xfer = usbd_alloc_xfer(sc->sc_udev);
			if (sc->sc_scord[i].xfer == NULL) {
				error = ENOMEM;
				goto bad;
			}
			sc->sc_scord[i].buf = usbd_alloc_buffer(sc->sc_scord[i].xfer,
						sc->sc_scord_size * UBT_NFRAMES);
			if (sc->sc_scord[i].buf == NULL) {
				error = ENOMEM;
				goto bad;
			}
			sc->sc_scord[i].softc = sc;
			sc->sc_scord[i].busy = 0;
			ubt_recv_sco_start1(sc, &sc->sc_scord[i]);
		}
	}

	/* SCO write */
	if (sc->sc_scowr_size > 0) {
		err = usbd_open_pipe(sc->sc_iface1, sc->sc_scowr_addr,
					USBD_EXCLUSIVE_USE, &sc->sc_scowr_pipe);
		if (err != USBD_NORMAL_COMPLETION) {
			error = EIO;
			goto bad;
		}

		for (i = 0 ; i < UBT_NXFERS ; i++) {
			sc->sc_scowr[i].xfer = usbd_alloc_xfer(sc->sc_udev);
			if (sc->sc_scowr[i].xfer == NULL) {
				error = ENOMEM;
				goto bad;
			}
			sc->sc_scowr[i].buf = usbd_alloc_buffer(sc->sc_scowr[i].xfer,
						sc->sc_scowr_size * UBT_NFRAMES);
			if (sc->sc_scowr[i].buf == NULL) {
				error = ENOMEM;
				goto bad;
			}
			sc->sc_scowr[i].softc = sc;
			sc->sc_scowr[i].busy = 0;
		}

		sc->sc_scowr_busy = 0;
	}

	sc->sc_enabled = 1;
	crit_exit();
	return 0;

bad:
	ubt_abortdealloc(sc);
	crit_exit();
	return error;
}
示例#25
0
static int
uticom_download_fw(struct uticom_softc *sc, int pipeno,
    struct usbd_device *dev)
{
	u_char *obuf, *firmware;
	size_t firmware_size;
	int buffer_size, pos;
	uint8_t cs = 0, *buffer;
	usbd_status err;
	struct uticom_fw_header *header;
	struct usbd_xfer *oxfer = 0;
	usbd_status error = 0;
	struct usbd_pipe *pipe;

	error = loadfirmware("tusb3410", &firmware, &firmware_size);
	if (error)
		return (error);

	buffer_size = UTICOM_FW_BUFSZ + sizeof(struct uticom_fw_header);
	buffer = malloc(buffer_size, M_USBDEV, M_WAITOK | M_CANFAIL);

	if (!buffer) {
		printf("%s: uticom_download_fw: out of memory\n",
		    sc->sc_dev.dv_xname);
		free(firmware, M_DEVBUF);
		return ENOMEM;
	}

	memcpy(buffer, firmware, firmware_size);
	memset(buffer + firmware_size, 0xff, buffer_size - firmware_size);

	for (pos = sizeof(struct uticom_fw_header); pos < buffer_size; pos++)
		cs = (uint8_t)(cs + buffer[pos]);

	header = (struct uticom_fw_header*)buffer;
	header->length = (uint16_t)(buffer_size -
	    sizeof(struct uticom_fw_header));
	header->checkSum = cs;

	DPRINTF(("%s: downloading firmware ...\n",
	    sc->sc_dev.dv_xname));

	err = usbd_open_pipe(sc->sc_iface, pipeno, USBD_EXCLUSIVE_USE,
	    &pipe);
	if (err) {
		printf("%s: open bulk out error (addr %d): %s\n",
		    sc->sc_dev.dv_xname, pipeno, usbd_errstr(err));
		error = EIO;
		goto finish;
	}

	oxfer = usbd_alloc_xfer(dev);
	if (oxfer == NULL) {
		error = ENOMEM;
		goto finish;
	}

	obuf = usbd_alloc_buffer(oxfer, buffer_size);
	if (obuf == NULL) {
		error = ENOMEM;
		goto finish;
	}

	memcpy(obuf, buffer, buffer_size);

	usbd_setup_xfer(oxfer, pipe, (void *)sc, obuf, buffer_size,
	    USBD_NO_COPY | USBD_SYNCHRONOUS, USBD_NO_TIMEOUT, 0);
	err = usbd_transfer(oxfer);

	if (err != USBD_NORMAL_COMPLETION)
		printf("%s: uticom_download_fw: error: %s\n",
		    sc->sc_dev.dv_xname, usbd_errstr(err));

finish:
	free(firmware, M_DEVBUF);
	usbd_free_buffer(oxfer);
	usbd_free_xfer(oxfer);
	oxfer = NULL;
	usbd_abort_pipe(pipe);
	usbd_close_pipe(pipe);
	free(buffer, M_USBDEV);
	return err;
}
示例#26
0
int
uirda_open(void *h, int flag, int mode,
    struct lwp *l)
{
	struct uirda_softc *sc = h;
	int error;
	usbd_status err;

	DPRINTF(("%s: sc=%p\n", __func__, sc));

	err = usbd_open_pipe(sc->sc_iface, sc->sc_rd_addr, 0, &sc->sc_rd_pipe);
	if (err) {
		error = EIO;
		goto bad1;
	}
	err = usbd_open_pipe(sc->sc_iface, sc->sc_wr_addr, 0, &sc->sc_wr_pipe);
	if (err) {
		error = EIO;
		goto bad2;
	}
	sc->sc_rd_xfer = usbd_alloc_xfer(sc->sc_udev);
	if (sc->sc_rd_xfer == NULL) {
		error = ENOMEM;
		goto bad3;
	}
	sc->sc_wr_xfer = usbd_alloc_xfer(sc->sc_udev);
	if (sc->sc_wr_xfer == NULL) {
		error = ENOMEM;
		goto bad4;
	}
	sc->sc_rd_buf = usbd_alloc_buffer(sc->sc_rd_xfer,
			    IRDA_MAX_FRAME_SIZE + sc->sc_hdszi);
	if (sc->sc_rd_buf == NULL) {
		error = ENOMEM;
		goto bad5;
	}
	sc->sc_wr_buf = usbd_alloc_buffer(sc->sc_wr_xfer,
			    IRDA_MAX_FRAME_SIZE + UIRDA_OUTPUT_HEADER_SIZE +
				2 + 1 /* worst case ST-UIRDA */);
	if (sc->sc_wr_buf == NULL) {
		error = ENOMEM;
		goto bad5;
	}
	sc->sc_rd_count = 0;
	sc->sc_rd_err = 0;
	sc->sc_params.speed = 0;
	sc->sc_params.ebofs = 0;
	sc->sc_params.maxsize = IRDA_MAX_FRAME_SIZE;
	sc->sc_wr_hdr = -1;

	err = uirda_start_read(sc);
	/* XXX check err */

	return (0);

bad5:
	usbd_free_xfer(sc->sc_wr_xfer);
	sc->sc_wr_xfer = NULL;
bad4:
	usbd_free_xfer(sc->sc_rd_xfer);
	sc->sc_rd_xfer = NULL;
bad3:
	usbd_close_pipe(sc->sc_wr_pipe);
	sc->sc_wr_pipe = NULL;
bad2:
	usbd_close_pipe(sc->sc_rd_pipe);
	sc->sc_rd_pipe = NULL;
bad1:
	return (error);
}
示例#27
0
int
stuirda_fwload(struct uirda_softc *sc) {


	int rc;
	firmware_handle_t fh;
	off_t fwsize;
	usb_device_descriptor_t usbddsc;
	usbd_xfer_handle	fwxfer;
	usbd_pipe_handle	fwpipe;
	usbd_status status;
	usb_device_request_t req;
	char *buffer;
	char *p;
	char fwname[12];
	int n;
	u_int8_t *usbbuf;
	/* size_t bsize; */

	printf("%s: needing to download firmware\n",
		device_xname(sc->sc_dev));

	status = usbd_get_device_desc(sc->sc_udev, &usbddsc);
	if (status) {
		printf("%s: can't get device descriptor, status %d\n",
		    device_xname(sc->sc_dev), status);
		return status;
	}

	rc = usbd_get_class_desc(sc->sc_udev, UDESC_IRDA, 0,
		USB_IRDA_DESCRIPTOR_SIZE, &sc->sc_irdadesc);
	printf("error %d reading class desc\n", rc);

	snprintf(fwname, sizeof(fwname), "4210%02x%02x.sb",
		usbddsc.bcdDevice[1],
		usbddsc.bcdDevice[0]);

	printf("%s: Attempting to load firmware %s\n",
		device_xname(sc->sc_dev), fwname);
	
	rc = firmware_open("stuirda", fwname, &fh);

	if (rc) {
		printf("%s: Cannot load firmware\n",
			device_xname(sc->sc_dev));
		return rc;
	}
	fwsize = firmware_get_size(fh);

	printf("%s: Firmware size %lld\n",
		device_xname(sc->sc_dev), (long long)fwsize);

	buffer = firmware_malloc(fwsize);
	if (buffer == NULL) {
		printf("%s: Cannot load firmware: out of memory\n",
			device_xname(sc->sc_dev));
		goto giveup2;
	}

	rc = firmware_read(fh, 0, buffer, (size_t)fwsize);

	if (rc) {
		printf("%s: Cannot read firmware\n", device_xname(sc->sc_dev));
		goto giveup3;
	}

	for (p = buffer + sizeof("Product Version:");
	    p < buffer + fwsize - 5; p++) {

		if (0x1A == *p)
			break;
	}
	if (0x1a != *p || memcmp(p+1, "STMP", 4) != 0) {
		/* firmware bad */
		printf("%s: Bad firmware\n", device_xname(sc->sc_dev));
		goto giveup3;
	}

	p += 5;

	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
	req.bRequest = 2 /* XXX magic */;
	USETW(req.wValue, 0);
	USETW(req.wIndex, 0);
	USETW(req.wLength, 0);
	rc = usbd_do_request(sc->sc_udev, &req, 0);
	if (rc) {
		printf("%s: Cannot switch to f/w d/l mode, error %d\n",
			device_xname(sc->sc_dev), rc);
		goto giveup3;
	}

	delay(100000);

	rc = usbd_open_pipe(sc->sc_iface, sc->sc_wr_addr, 0, &fwpipe);
	if (rc) {
		printf("%s: Cannot open pipe, rc=%d\n",
		    device_xname(sc->sc_dev), rc);
		goto giveup3;
	}
	fwxfer = usbd_alloc_xfer(sc->sc_udev);
	if (fwxfer == NULL) {
		printf("%s: Cannot alloc xfer\n", device_xname(sc->sc_dev));
		goto giveup4;
	}
	usbbuf = usbd_alloc_buffer(fwxfer, 1024);
	if (usbbuf == NULL) {
		printf("%s: Cannot alloc usb buf\n", device_xname(sc->sc_dev));
		goto giveup5;
	}
	n = (buffer + fwsize - p);
	while (n > 0) {
		if (n > 1023)
			n = 1023;
		memcpy(usbbuf, p, n);
		rc = usbd_bulk_transfer(fwxfer, fwpipe,
		    USBD_SYNCHRONOUS|USBD_FORCE_SHORT_XFER,
		    5000, usbbuf, &n, "uirda-fw-wr");
		printf("%s: write: rc=%d, %d left\n",
		    device_xname(sc->sc_dev), rc, n);
		if (rc) {
			printf("%s: write: rc=%d, %d bytes written\n",
			    device_xname(sc->sc_dev), rc, n);
			goto giveup4;
		}
		printf("%s: written %d\n", device_xname(sc->sc_dev), n);
		p += n; 
		n = (buffer + fwsize - p);
	}
	delay(100000);
	/* TODO: more code here */
	rc = 0;
	usbd_free_buffer(fwxfer);

	giveup5: usbd_free_xfer(fwxfer);	
	giveup4: usbd_close_pipe(fwpipe);
	giveup3: firmware_free(buffer, fwsize);
	giveup2: firmware_close(fh);

	return rc;
		
}
示例#28
0
Static int
url_openpipes(struct url_softc *sc)
{
	struct url_chain *c;
	usbd_status err;
	int i;
	int error = 0;

	if (sc->sc_dying)
		return (EIO);

	sc->sc_refcnt++;

	/* Open RX pipe */
	err = usbd_open_pipe(sc->sc_ctl_iface, sc->sc_bulkin_no,
			     USBD_EXCLUSIVE_USE, &sc->sc_pipe_rx);
	if (err) {
		printf("%s: open rx pipe failed: %s\n",
		       USBDEVNAME(sc->sc_dev), usbd_errstr(err));
		error = EIO;
		goto done;
	}

	/* Open TX pipe */
	err = usbd_open_pipe(sc->sc_ctl_iface, sc->sc_bulkout_no,
			     USBD_EXCLUSIVE_USE, &sc->sc_pipe_tx);
	if (err) {
		printf("%s: open tx pipe failed: %s\n",
		       USBDEVNAME(sc->sc_dev), usbd_errstr(err));
		error = EIO;
		goto done;
	}

#if 0
	/* XXX: interrupt endpoint is not yet supported */
	/* Open Interrupt pipe */
	err = usbd_open_pipe_intr(sc->sc_ctl_iface, sc->sc_intrin_no,
				  USBD_EXCLUSIVE_USE, &sc->sc_pipe_intr, sc,
				  &sc->sc_cdata.url_ibuf, URL_INTR_PKGLEN,
				  url_intr, URL_INTR_INTERVAL);
	if (err) {
		printf("%s: open intr pipe failed: %s\n",
		       USBDEVNAME(sc->sc_dev), usbd_errstr(err));
		error = EIO;
		goto done;
	}
#endif


	/* Start up the receive pipe. */
	for (i = 0; i < URL_RX_LIST_CNT; i++) {
		c = &sc->sc_cdata.url_rx_chain[i];
		usbd_setup_xfer(c->url_xfer, sc->sc_pipe_rx,
				c, c->url_buf, URL_BUFSZ,
				USBD_SHORT_XFER_OK | USBD_NO_COPY,
				USBD_NO_TIMEOUT, url_rxeof);
		(void)usbd_transfer(c->url_xfer);
		DPRINTF(("%s: %s: start read\n", USBDEVNAME(sc->sc_dev),
			 __func__));
	}

 done:
	if (--sc->sc_refcnt < 0)
		usb_detach_wakeup(USBDEV(sc->sc_dev));

	return (error);
}
int
uscanneropen(dev_t dev, int flag, int mode,
    struct lwp *l)
{
	struct uscanner_softc *sc;
	int unit = USCANNERUNIT(dev);
	usbd_status err;

	sc = device_lookup_private(&uscanner_cd, unit);
	if (sc == NULL)
		return ENXIO;

 	DPRINTFN(5, ("uscanneropen: flag=%d, mode=%d, unit=%d\n",
		     flag, mode, unit));

	if (sc->sc_dying)
		return (ENXIO);

	if (sc->sc_state & USCANNER_OPEN)
		return (EBUSY);

	sc->sc_state |= USCANNER_OPEN;

	sc->sc_bulkin_buffer = malloc(USCANNER_BUFFERSIZE, M_USBDEV, M_WAITOK);
	sc->sc_bulkout_buffer = malloc(USCANNER_BUFFERSIZE, M_USBDEV, M_WAITOK);
	/* No need to check buffers for NULL since we have WAITOK */

	sc->sc_bulkin_bufferlen = USCANNER_BUFFERSIZE;
	sc->sc_bulkout_bufferlen = USCANNER_BUFFERSIZE;

	/* We have decided on which endpoints to use, now open the pipes */
	if (sc->sc_bulkin_pipe == NULL) {
		err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkin,
				     USBD_EXCLUSIVE_USE, &sc->sc_bulkin_pipe);
		if (err) {
			printf("%s: cannot open bulk-in pipe (addr %d)\n",
			       device_xname(sc->sc_dev), sc->sc_bulkin);
			uscanner_do_close(sc);
			return (EIO);
		}
	}
	if (sc->sc_bulkout_pipe == NULL) {
		err = usbd_open_pipe(sc->sc_iface, sc->sc_bulkout,
				     USBD_EXCLUSIVE_USE, &sc->sc_bulkout_pipe);
		if (err) {
			printf("%s: cannot open bulk-out pipe (addr %d)\n",
			       device_xname(sc->sc_dev), sc->sc_bulkout);
			uscanner_do_close(sc);
			return (EIO);
		}
	}

	sc->sc_bulkin_xfer = usbd_alloc_xfer(sc->sc_udev);
	if (sc->sc_bulkin_xfer == NULL) {
		uscanner_do_close(sc);
		return (ENOMEM);
	}
	sc->sc_bulkout_xfer = usbd_alloc_xfer(sc->sc_udev);
	if (sc->sc_bulkout_xfer == NULL) {
		uscanner_do_close(sc);
		return (ENOMEM);
	}

	return (0);	/* success */
}
示例#30
0
usbd_status
umsm_umass_changemode(struct umsm_softc *sc)
{
#define UMASS_CMD_REZERO_UNIT		0x01
#define UMASS_CMD_START_STOP		0x1b
#define UMASS_CMDPARAM_EJECT		0x02
#define UMASS_SERVICE_ACTION_OUT	0x9f
	usb_interface_descriptor_t *id;
	usb_endpoint_descriptor_t *ed;
	struct usbd_xfer *xfer;
	struct usbd_pipe *cmdpipe;
	usbd_status err;
	u_int32_t n;
	void *bufp;
	int target_ep, i;

	struct umass_bbb_cbw cbw;
	static int dCBWTag = 0x12345678;

	USETDW(cbw.dCBWSignature, CBWSIGNATURE);
	USETDW(cbw.dCBWTag, dCBWTag);
	cbw.bCBWLUN   = 0;
	cbw.bCDBLength= 6;
	bzero(cbw.CBWCDB, sizeof(cbw.CBWCDB));

	switch (sc->sc_flag) {
	case DEV_UMASS1:
		USETDW(cbw.dCBWDataTransferLength, 0x0);
		cbw.bCBWFlags = CBWFLAGS_OUT;
		cbw.CBWCDB[0] = UMASS_CMD_REZERO_UNIT;
		cbw.CBWCDB[1] = 0x0;	/* target LUN: 0 */
		break;
	case DEV_UMASS2:
		USETDW(cbw.dCBWDataTransferLength, 0x1);
		cbw.bCBWFlags = CBWFLAGS_IN;
		cbw.CBWCDB[0] = UMASS_CMD_REZERO_UNIT;
		cbw.CBWCDB[1] = 0x0;	/* target LUN: 0 */
		break;
	case DEV_UMASS3: /* longcheer */
		USETDW(cbw.dCBWDataTransferLength, 0x80);
		cbw.bCBWFlags = CBWFLAGS_IN;
		cbw.CBWCDB[0] = 0x06;
		cbw.CBWCDB[1] = 0xf5;
		cbw.CBWCDB[2] = 0x04;
		cbw.CBWCDB[3] = 0x02;
		cbw.CBWCDB[4] = 0x52;
		cbw.CBWCDB[5] = 0x70;
		break;
	case DEV_UMASS4:
		USETDW(cbw.dCBWDataTransferLength, 0x0);
		cbw.bCBWFlags = CBWFLAGS_OUT;
		cbw.CBWCDB[0] = UMASS_CMD_START_STOP;
		cbw.CBWCDB[1] = 0x00;	/* target LUN: 0 */
		cbw.CBWCDB[4] = UMASS_CMDPARAM_EJECT;
		break;
	case DEV_UMASS5:
		cbw.bCBWFlags = CBWFLAGS_OUT;
		cbw.CBWCDB[0] = 0x11;
		cbw.CBWCDB[1] = 0x06;
		break;
	case DEV_UMASS6:	/* ZTE */
		USETDW(cbw.dCBWDataTransferLength, 0x20);
		cbw.bCBWFlags = CBWFLAGS_IN;
		cbw.bCDBLength= 12;
		cbw.CBWCDB[0] = 0x85;
		cbw.CBWCDB[1] = 0x01;
		cbw.CBWCDB[2] = 0x01;
		cbw.CBWCDB[3] = 0x01;
		cbw.CBWCDB[4] = 0x18;
		cbw.CBWCDB[5] = 0x01;
		cbw.CBWCDB[6] = 0x01;
		cbw.CBWCDB[7] = 0x01;
		cbw.CBWCDB[8] = 0x01;
		cbw.CBWCDB[9] = 0x01;
		break;
	case DEV_UMASS7:	/* ZTE */
		USETDW(cbw.dCBWDataTransferLength, 0xc0);
		cbw.bCBWFlags = CBWFLAGS_IN;
		cbw.CBWCDB[0] = UMASS_SERVICE_ACTION_OUT;
		cbw.CBWCDB[1] = 0x03;
		break;
	case DEV_UMASS8:
		USETDW(cbw.dCBWDataTransferLength, 0x0);
		cbw.bCBWFlags = CBWFLAGS_OUT;
		cbw.CBWCDB[0] = 0xf0;
		cbw.CBWCDB[1] = 0x01;
		cbw.CBWCDB[2] = 0x03;
		break;
	default:
		DPRINTF(("%s: unknown device type.\n", sc->sc_dev.dv_xname));
		break;
	}

	/* get command endpoint address */
	id = usbd_get_interface_descriptor(sc->sc_iface);
	for (i = 0; i < id->bNumEndpoints; i++) {
		ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i);
		if (ed == NULL) {
			return (USBD_IOERROR);
		}

		if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
		    UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK)
			target_ep = ed->bEndpointAddress;
	}

	/* open command endppoint */
	err = usbd_open_pipe(sc->sc_iface, target_ep,
		USBD_EXCLUSIVE_USE, &cmdpipe);
	if (err) {
		DPRINTF(("%s: open pipe for modem change cmd failed: %s\n",
		    sc->sc_dev.dv_xname, usbd_errstr(err)));
		return (err);
	}

	xfer = usbd_alloc_xfer(sc->sc_udev);
	if (xfer == NULL) {
		usbd_close_pipe(cmdpipe);
		return (USBD_NOMEM);
	} else {
		bufp = usbd_alloc_buffer(xfer, UMASS_BBB_CBW_SIZE);
		if (bufp == NULL)
			err = USBD_NOMEM;
		else {
			n = UMASS_BBB_CBW_SIZE;
			memcpy(bufp, &cbw, UMASS_BBB_CBW_SIZE);
			usbd_setup_xfer(xfer, cmdpipe, 0, bufp, n,
			    USBD_NO_COPY | USBD_SYNCHRONOUS, 0, NULL);
			err = usbd_transfer(xfer);
			if (err) {
				usbd_clear_endpoint_stall(cmdpipe);
				DPRINTF(("%s: send error:%s", __func__,
				    usbd_errstr(err)));
			}
		}
		usbd_close_pipe(cmdpipe);
		usbd_free_buffer(xfer);
		usbd_free_xfer(xfer);
	}

	return (err);
}