Пример #1
0
static int
uftdi_send_data(uftdi_state_t *uf, mblk_t *data)
{
	usb_bulk_req_t *br;
	int len = MBLKL(data);
	int rval;

	USB_DPRINTF_L4(DPRINT_OUT_PIPE, uf->uf_lh,
	    "uftdi_send_data: %d 0x%x 0x%x 0x%x", len, data->b_rptr[0],
	    (len > 1) ? data->b_rptr[1] : 0, (len > 2) ? data->b_rptr[2] : 0);

	ASSERT(!mutex_owned(&uf->uf_lock));

	br = usb_alloc_bulk_req(uf->uf_dip, 0, USB_FLAGS_SLEEP);
	br->bulk_data = data;
	br->bulk_len = len;
	br->bulk_timeout = UFTDI_BULKOUT_TIMEOUT;
	br->bulk_cb = uftdi_bulkout_cb;
	br->bulk_exc_cb = uftdi_bulkout_cb;
	br->bulk_client_private = (usb_opaque_t)uf;
	br->bulk_attributes = USB_ATTRS_AUTOCLEARING;

	rval = usb_pipe_bulk_xfer(uf->uf_bulkout_ph, br, 0);

	if (rval != USB_SUCCESS) {
		USB_DPRINTF_L2(DPRINT_OUT_PIPE, uf->uf_lh,
		    "uftdi_send_data: xfer failed %d", rval);
		br->bulk_data = NULL;
		usb_free_bulk_req(br);
	}

	return (rval);
}
Пример #2
0
/*ARGSUSED*/
static void
uftdi_bulkout_cb(usb_pipe_handle_t pipe, usb_bulk_req_t *req)
{
	uftdi_state_t	*uf = (uftdi_state_t *)req->bulk_client_private;
	int		data_len;
	mblk_t		*data = req->bulk_data;

	data_len = data ? MBLKL(data) : 0;

	USB_DPRINTF_L4(DPRINT_OUT_PIPE, uf->uf_lh,
	    "uftdi_bulkout_cb: cr=%d len=%d",
	    req->bulk_completion_reason, data_len);

	if (uf->uf_port_state == UFTDI_PORT_OPEN &&
	    req->bulk_completion_reason && data_len > 0) {
		uftdi_put_head(&uf->uf_tx_mp, data);
		req->bulk_data = NULL;
	}

	usb_free_bulk_req(req);

	/* notify GSD */
	if (uf->uf_cb.cb_tx)
		uf->uf_cb.cb_tx(uf->uf_cb.cb_arg);

	/* send more */
	mutex_enter(&uf->uf_lock);
	uf->uf_bulkout_state = UFTDI_PIPE_IDLE;
	if (uf->uf_tx_mp == NULL)
		cv_broadcast(&uf->uf_tx_cv);
	else
		uftdi_tx_start(uf, NULL);
	mutex_exit(&uf->uf_lock);
}
Пример #3
0
/*
 * start receiving data
 */
static int
uftdi_rx_start(uftdi_state_t *uf)
{
	usb_bulk_req_t *br;
	int rval;

	USB_DPRINTF_L4(DPRINT_OUT_PIPE, uf->uf_lh, "uftdi_rx_start");

	ASSERT(mutex_owned(&uf->uf_lock));

	uf->uf_bulkin_state = UFTDI_PIPE_BUSY;
	mutex_exit(&uf->uf_lock);

	br = usb_alloc_bulk_req(uf->uf_dip, uf->uf_xfer_sz, USB_FLAGS_SLEEP);
	br->bulk_len = uf->uf_xfer_sz;
	br->bulk_timeout = UFTDI_BULKIN_TIMEOUT;
	br->bulk_cb = uftdi_bulkin_cb;
	br->bulk_exc_cb = uftdi_bulkin_cb;
	br->bulk_client_private = (usb_opaque_t)uf;
	br->bulk_attributes = USB_ATTRS_AUTOCLEARING | USB_ATTRS_SHORT_XFER_OK;

	rval = usb_pipe_bulk_xfer(uf->uf_bulkin_ph, br, 0);

	if (rval != USB_SUCCESS) {
		USB_DPRINTF_L2(DPRINT_IN_PIPE, uf->uf_lh,
		    "uftdi_rx_start: xfer failed %d", rval);
		usb_free_bulk_req(br);
	}

	mutex_enter(&uf->uf_lock);
	if (rval != USB_SUCCESS)
		uf->uf_bulkin_state = UFTDI_PIPE_IDLE;

	return (rval);
}
Пример #4
0
void
usba10_usb_free_bulk_req(usb_bulk_req_t *reqp)
{
	usb_free_bulk_req(reqp);
}
Пример #5
0
/*ARGSUSED*/
static void
uftdi_bulkin_cb(usb_pipe_handle_t pipe, usb_bulk_req_t *req)
{
	uftdi_state_t *uf = (uftdi_state_t *)req->bulk_client_private;
	mblk_t *data;
	int data_len;

	data = req->bulk_data;
	data_len = data ? MBLKL(data) : 0;

	/*
	 * The first two bytes of data are status register bytes
	 * that arrive with every packet from the device.  Process
	 * them here before handing the rest of the data on.
	 *
	 * When active, the device will send us these bytes at least
	 * every 40 milliseconds, even if there's no received data.
	 */
	if (req->bulk_completion_reason == USB_CR_OK && data_len >= 2) {
		uint8_t msr = FTDI_GET_MSR(data->b_rptr);
		uint8_t lsr = FTDI_GET_LSR(data->b_rptr);
		int new_rx_err;

		data->b_rptr += 2;

		mutex_enter(&uf->uf_lock);

		if (uf->uf_msr != msr) {
			/*
			 * modem status register changed
			 */
			USB_DPRINTF_L3(DPRINT_IN_PIPE, uf->uf_lh,
			    "uftdi_bulkin_cb: new msr: 0x%02x -> 0x%02x",
			    uf->uf_msr, msr);

			uf->uf_msr = msr;

			if (uf->uf_port_state == UFTDI_PORT_OPEN &&
			    uf->uf_cb.cb_status) {
				mutex_exit(&uf->uf_lock);
				uf->uf_cb.cb_status(uf->uf_cb.cb_arg);
				mutex_enter(&uf->uf_lock);
			}
		}

		if ((uf->uf_lsr & FTDI_LSR_MASK) != (lsr & FTDI_LSR_MASK)) {
			/*
			 * line status register *receive* bits changed
			 *
			 * (The THRE and TEMT (transmit) status bits are
			 * masked out above.)
			 */
			USB_DPRINTF_L3(DPRINT_IN_PIPE, uf->uf_lh,
			    "uftdi_bulkin_cb: new lsr: 0x%02x -> 0x%02x",
			    uf->uf_lsr, lsr);
			new_rx_err = B_TRUE;
		} else
			new_rx_err = B_FALSE;

		uf->uf_lsr = lsr;	/* THRE and TEMT captured here */

		if ((lsr & FTDI_LSR_MASK) != 0 &&
		    (MBLKL(data) > 0 || new_rx_err) &&
		    uf->uf_port_state == UFTDI_PORT_OPEN) {
			/*
			 * The current line status register value indicates
			 * that there's been some sort of unusual condition
			 * on the receive side.  We either received a break,
			 * or got some badly formed characters from the
			 * serial port - framing errors, overrun, parity etc.
			 * So there's either some new data to post, or a
			 * new error (break) to post, or both.
			 *
			 * Invoke uftdi_rxerr_put() to place the inbound
			 * characters as M_BREAK messages on the receive
			 * mblk chain, decorated with error flag(s) for
			 * upper-level modules (e.g. ldterm) to process.
			 */
			mutex_exit(&uf->uf_lock);
			uftdi_rxerr_put(&uf->uf_rx_mp, data, lsr);
			ASSERT(MBLKL(data) == 0);

			/*
			 * Since we've converted all the received
			 * characters into M_BREAK messages, we
			 * invoke the rx callback to shove the mblks
			 * up the STREAM.
			 */
			if (uf->uf_cb.cb_rx)
				uf->uf_cb.cb_rx(uf->uf_cb.cb_arg);
			mutex_enter(&uf->uf_lock);
		}

		mutex_exit(&uf->uf_lock);
		data_len = MBLKL(data);
	}

	USB_DPRINTF_L4(DPRINT_IN_PIPE, uf->uf_lh, "uftdi_bulkin_cb: "
	    "cr=%d len=%d", req->bulk_completion_reason, data_len);

	/* save data and notify GSD */
	if (data_len > 0 &&
	    uf->uf_port_state == UFTDI_PORT_OPEN &&
	    req->bulk_completion_reason == USB_CR_OK) {
		req->bulk_data = NULL;
		uftdi_put_tail(&uf->uf_rx_mp, data);
		if (uf->uf_cb.cb_rx)
			uf->uf_cb.cb_rx(uf->uf_cb.cb_arg);
	}

	usb_free_bulk_req(req);

	/* receive more */
	mutex_enter(&uf->uf_lock);
	uf->uf_bulkin_state = UFTDI_PIPE_IDLE;
	if (uf->uf_port_state == UFTDI_PORT_OPEN &&
	    uf->uf_dev_state == USB_DEV_ONLINE) {
		if (uftdi_rx_start(uf) != USB_SUCCESS) {
			USB_DPRINTF_L2(DPRINT_IN_PIPE, uf->uf_lh,
			    "uftdi_bulkin_cb: restart rx fail");
		}
	}
	mutex_exit(&uf->uf_lock);
}