Пример #1
0
void
uftdi_read(void *vsc, int portno, u_char **ptr, u_int32_t *count)
{
	struct uftdi_softc *sc = vsc;
	u_char msr, lsr;

	DPRINTFN(15,("uftdi_read: sc=%p, port=%d count=%d\n", sc, portno,
		     *count));

	msr = FTDI_GET_MSR(*ptr);
	lsr = FTDI_GET_LSR(*ptr);

#ifdef UFTDI_DEBUG
	if (*count != 2)
		DPRINTFN(10,("uftdi_read: sc=%p, port=%d count=%d data[0]="
			    "0x%02x\n", sc, portno, *count, (*ptr)[2]));
#endif

	if (sc->sc_msr != msr ||
	    (sc->sc_lsr & FTDI_LSR_MASK) != (lsr & FTDI_LSR_MASK)) {
		DPRINTF(("uftdi_read: status change msr=0x%02x(0x%02x) "
			 "lsr=0x%02x(0x%02x)\n", msr, sc->sc_msr,
			 lsr, sc->sc_lsr));
		sc->sc_msr = msr;
		sc->sc_lsr = lsr;
		ucom_status_change((struct ucom_softc *)sc->sc_subdev);
	}

	/* Pick up status and adjust data part. */
	*ptr += 2;
	*count -= 2;
}
Пример #2
0
Static void
uftdi_read(void *vsc, int portno, u_char **ptr, u_int32_t *count)
{
	struct uftdi_softc *sc = vsc;
	u_char msr, lsr;

	DPRINTFN(15,("uftdi_read: sc=%p, port=%d count=%d\n", sc, portno,
		     *count));

	msr = FTDI_GET_MSR(*ptr);
	lsr = FTDI_GET_LSR(*ptr);

#ifdef UFTDI_DEBUG
	if (*count != 2)
		DPRINTFN(10,("uftdi_read: sc=%p, port=%d count=%d data[0]="
			    "0x%02x\n", sc, portno, *count, (*ptr)[2]));
#endif

	if (sc->sc_msr != msr ||
	    (sc->sc_lsr & FTDI_LSR_MASK) != (lsr & FTDI_LSR_MASK)) {
		DPRINTF(("uftdi_read: status change msr=0x%02x(0x%02x) "
			 "lsr=0x%02x(0x%02x)\n", msr, sc->sc_msr,
			 lsr, sc->sc_lsr));
		sc->sc_msr = msr;
		sc->sc_lsr = lsr;
		ucom_status_change(device_private(sc->sc_subdev[portno-1]));
	}

	/* Adjust buffer pointer to skip status prefix */
	*ptr += 2;
}
Пример #3
0
void
FTDIDevice::OnRead(char **buffer, size_t *numBytes)
{
	fStatusMSR = FTDI_GET_MSR(*buffer);
	fStatusLSR = FTDI_GET_LSR(*buffer);
	TRACE("FTDIDevice::OnRead(): MSR: 0x%02x LSR: 0x%02x\n", fStatusMSR, fStatusLSR);
	*buffer += 2;
	*numBytes -= 2;
}
Пример #4
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);
}