Ejemplo n.º 1
0
usbd_status
uhidev_write(struct uhidev_softc *sc, void *data, int len)
{

	DPRINTF(("uhidev_write: data=%p, len=%d\n", data, len));

	if (sc->sc_opipe == NULL)
		return USBD_INVAL;

#ifdef UHIDEV_DEBUG
	if (uhidevdebug > 50) {

		u_int32_t i;
		u_int8_t *d = data;

		DPRINTF(("uhidev_write: data ="));
		for (i = 0; i < len; i++)
			DPRINTF((" %02x", d[i]));
		DPRINTF(("\n"));
	}
#endif
	return usbd_intr_transfer(sc->sc_owxfer, sc->sc_opipe, 0,
	    USBD_NO_TIMEOUT, data, &len, "uhidevwi");
}
Ejemplo n.º 2
0
/* ARGSUSED */
static int
udsir_write(void *h, struct uio *uio, int flag)
{
	struct udsir_softc *sc = h;
	usbd_status err;
	uint32_t wrlen;
	int error, sirlength;
	uint8_t *wrbuf;
	int s;

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

	if (sc->sc_dying)
		return EIO;

#ifdef DIAGNOSTIC
	if (sc->sc_wr_buf == NULL)
		return EINVAL;
#endif

	wrlen = uio->uio_resid;
	if (wrlen > sc->sc_wr_maxpsz)
		return EINVAL;

	sc->sc_refcnt++;

	if (!UDSIR_BLOCK_RX_DATA(sc)) {
		/*
		 * If reads are not blocked, determine what action we
		 * should potentially take...
		 */
		if (sc->sc_direction == udir_output) {
			/*
			 * If the last operation was an output, wait for the
			 * polling thread to check for incoming data.
			 */
			sc->sc_wr_stalewrite = 1;
			wakeup(&sc->sc_thread);
		} else if (!sc->sc_rd_readinprogress &&
			   (sc->sc_direction == udir_idle ||
			    sc->sc_direction == udir_input)) {
			/* If idle, check for input before outputting */
			udsir_start_read(sc);
		}
	}

	s = splusb();
	while (sc->sc_wr_stalewrite ||
	       (sc->sc_direction != udir_output &&
		sc->sc_direction != udir_idle)) {
		DPRINTFN(5, ("%s: sc=%p stalewrite=%d direction=%d, "
			     "calling tsleep()\n",
			     __func__, sc, sc->sc_wr_stalewrite,
			     sc->sc_direction));
		error = tsleep(&sc->sc_wr_buf, PZERO | PCATCH, "usirwr", 0);
		if (sc->sc_dying)
			error = EIO;
		if (error) {
			splx(s);
			DPRINTFN(0, ("%s: tsleep() = %d\n", __func__, error));
			goto ret;
		}
	}
	splx(s);

	wrbuf = sc->sc_wr_buf;

	sirlength = irda_sir_frame(wrbuf, MAX_UDSIR_OUTPUT_FRAME,
	    uio, sc->sc_params.ebofs);
	if (sirlength < 0)
		error = -sirlength;
	else {
		uint32_t btlen;

		DPRINTFN(1, ("%s: transfer %u bytes\n",
			     __func__, (unsigned int)wrlen));

		btlen = sirlength;

		sc->sc_direction = udir_output;

#ifdef UDSIR_DEBUG
		if (udsirdebug >= 20)
			udsir_dumpdata(wrbuf, btlen, __func__);
#endif

		err = usbd_intr_transfer(sc->sc_wr_xfer, sc->sc_wr_pipe,
		     USBD_FORCE_SHORT_XFER, UDSIR_WR_TIMEOUT,
		     wrbuf, &btlen);
		DPRINTFN(2, ("%s: err=%d\n", __func__, err));
		if (err != USBD_NORMAL_COMPLETION) {
			if (err == USBD_INTERRUPTED)
				error = EINTR;
			else if (err == USBD_TIMEOUT)
				error = ETIMEDOUT;
			else
				error = EIO;
		} else
			error = 0;
	}

 ret:
	if (--sc->sc_refcnt < 0)
		usb_detach_wakeupold(sc->sc_dev);

	DPRINTFN(1, ("%s: sc=%p done\n", __func__, sc));
	return error;
}
Ejemplo n.º 3
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\n", scd->sc_state));

	mutex_enter(&sc->sc_lock);
	if (scd->sc_state & UHIDEV_OPEN) {
		mutex_exit(&sc->sc_lock);
		return EBUSY;
	}
	scd->sc_state |= UHIDEV_OPEN;
	if (sc->sc_refcnt++) {
		mutex_exit(&sc->sc_lock);
		return 0;
	}
	mutex_exit(&sc->sc_lock);

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

	sc->sc_ibuf = kmem_alloc(sc->sc_isize, KM_SLEEP);

	/* 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;
	}

	/*
	 * 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));

		error = usbd_create_xfer(sc->sc_opipe, UHIDEV_OSIZE, 0, 0,
		    &sc->sc_oxfer);
		if (error) {
			DPRINTF(("uhidev_open: couldn't allocate an xfer\n"));
			goto out3;
		}

		if (sc->sc_flags & UHIDEV_F_XB1) {
			uint8_t init_data[] = { 0x05, 0x20 };
			int init_data_len = sizeof(init_data);
			err = usbd_intr_transfer(sc->sc_oxfer, sc->sc_opipe, 0,
			    USBD_NO_TIMEOUT, init_data, &init_data_len);
			if (err != USBD_NORMAL_COMPLETION) {
				DPRINTF(("uhidev_open: xb1 init failed, "
				    "error=%d\n", err));
				error = EIO;
				goto out4;
			}
		}
	}

	return 0;
out4:
	/* Free output xfer */
	if (sc->sc_oxfer != NULL)
		usbd_destroy_xfer(sc->sc_oxfer);
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"));
	kmem_free(sc->sc_ibuf, sc->sc_isize);
	mutex_enter(&sc->sc_lock);
	scd->sc_state &= ~UHIDEV_OPEN;
	sc->sc_refcnt = 0;
	sc->sc_ibuf = NULL;
	sc->sc_ipipe = NULL;
	sc->sc_opipe = NULL;
	sc->sc_oxfer = NULL;
	mutex_exit(&sc->sc_lock);
	return error;
}