Ejemplo n.º 1
0
static int
atausb_bbb_start(struct ata_request *request)
{
    struct atausb_softc *sc = 
	device_get_softc(device_get_parent(request->parent));
    struct ata_channel *ch = device_get_softc(request->parent);

    sc->timeout = (request->timeout * 1000) + 5000;
    USETDW(sc->cbw.signature, CBWSIGNATURE);
    USETDW(sc->cbw.tag, UGETDW(sc->cbw.tag) + 1);
    USETDW(sc->cbw.transfer_length, request->bytecount);
    sc->cbw.flags = (request->flags & ATA_R_READ) ? CBWFLAGS_IN : CBWFLAGS_OUT;
    sc->cbw.lun = ch->unit;
    sc->cbw.length = 16;
    bzero(sc->cbw.cdb, 16);
    bcopy(request->u.atapi.ccb, sc->cbw.cdb, 12); /* XXX SOS */
    sc->state = ATAUSB_S_BBB_COMMAND;
    if (atausb_start(sc, sc->bulkout_pipe, &sc->cbw, sizeof(struct bbb_cbw),
		     0, sc->transfer[ATAUSB_T_BBB_CBW])) {
	request->result = EIO;
        if (atausbdebug)
	    device_printf(request->dev, "cannot setup USB transfer\n");
        atausb_bbb_reset(sc);
	return ATA_OP_FINISHED;
    }
    return ATA_OP_CONTINUES;
}
Ejemplo n.º 2
0
void
umct_set_baudrate(struct umct_softc *sc, u_int rate, int cts)
{
        usb_device_request_t req;
	uDWord arate;
	u_int val;

	if (sc->sc_product == USB_PRODUCT_MCT_SITECOM_USB232 ||
	    sc->sc_product == USB_PRODUCT_BELKIN_F5U109) {
		switch (rate) {
		case    300: val = 0x01; break;
		case    600: val = 0x02; break;
		case   1200: val = 0x03; break;
		case   2400: val = 0x04; break;
		case   4800: val = 0x06; break;
		case   9600: val = 0x08; break;
		case  19200: val = 0x09; break;
		case  38400: val = 0x0a; break;
		case  57600: val = 0x0b; break;
		case 115200: val = 0x0c; break;
		default:     val = -1; break;
		}
	} else {
		val = UMCT_BAUD_RATE(rate);
	}
	USETDW(arate, val);

        req.bmRequestType = UMCT_SET_REQUEST;
        req.bRequest = REQ_SET_BAUD_RATE;
        USETW(req.wValue, 0);
        USETW(req.wIndex, sc->sc_iface_number);
        USETW(req.wLength, LENGTH_BAUD_RATE);

	/* XXX should check */
        (void)usbd_do_request(sc->sc_udev, &req, arate);

	/* unknown request, required after setting baud rate */
	USETDW(arate, 0);
	req.bmRequestType = UMCT_SET_REQUEST;
	req.bRequest = REQ_UNKNOWN1;
	USETW(req.wValue, 0);
	USETW(req.wIndex, sc->sc_iface_number);
	USETW(req.wLength, LENGTH_UNKNOWN1);
	(void)usbd_do_request(sc->sc_udev, &req, arate);

	/* update CTS, also required after setting baud rate */
	USETDW(arate, cts);
	req.bmRequestType = UMCT_SET_REQUEST;
	req.bRequest = REQ_SET_CTS;
	USETW(req.wValue, 0);
	USETW(req.wIndex, sc->sc_iface_number);
	USETW(req.wLength, LENGTH_SET_CTS);
	(void)usbd_do_request(sc->sc_udev, &req, arate);
}
Ejemplo n.º 3
0
static int
uplcom_param(void *addr, int portno, struct termios *t)
{
	struct uplcom_softc *sc = addr;
	usbd_status err;
	usb_cdc_line_state_t ls;
	int i;

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

	/* Check requested baud rate */
	for (i = 0; i < N_UPLCOM_RATES; i++)
		if (uplcom_rates[i] == t->c_ospeed)
			break;
	if (i == N_UPLCOM_RATES) {
		DPRINTF(("uplcom_param: bad baud rate (%d)\n", t->c_ospeed));
		return (EIO);
	}

	USETDW(ls.dwDTERate, t->c_ospeed);
	if (ISSET(t->c_cflag, CSTOPB))
		ls.bCharFormat = UCDC_STOP_BIT_2;
	else
		ls.bCharFormat = UCDC_STOP_BIT_1;
	if (ISSET(t->c_cflag, PARENB)) {
		if (ISSET(t->c_cflag, PARODD))
			ls.bParityType = UCDC_PARITY_ODD;
		else
			ls.bParityType = UCDC_PARITY_EVEN;
	} else
		ls.bParityType = UCDC_PARITY_NONE;
	switch (ISSET(t->c_cflag, CSIZE)) {
	case CS5:
		ls.bDataBits = 5;
		break;
	case CS6:
		ls.bDataBits = 6;
		break;
	case CS7:
		ls.bDataBits = 7;
		break;
	case CS8:
		ls.bDataBits = 8;
		break;
	}

	err = uplcom_set_line_coding(sc, &ls);
	if (err)
		return (EIO);

	if (ISSET(t->c_cflag, CRTSCTS)) {
		err = uplcom_set_crtscts(sc);
		if (err)
			return (EIO);
	}

	return (0);
}
Ejemplo n.º 4
0
int
uplcom_param(void *addr, int portno, struct termios *t)
{
	struct uplcom_softc *sc = addr;
	usbd_status err;
	usb_cdc_line_state_t ls;

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

	USETDW(ls.dwDTERate, t->c_ospeed);
	if (ISSET(t->c_cflag, CSTOPB))
		ls.bCharFormat = UCDC_STOP_BIT_2;
	else
		ls.bCharFormat = UCDC_STOP_BIT_1;
	if (ISSET(t->c_cflag, PARENB)) {
		if (ISSET(t->c_cflag, PARODD))
			ls.bParityType = UCDC_PARITY_ODD;
		else
			ls.bParityType = UCDC_PARITY_EVEN;
	} else
		ls.bParityType = UCDC_PARITY_NONE;
	switch (ISSET(t->c_cflag, CSIZE)) {
	case CS5:
		ls.bDataBits = 5;
		break;
	case CS6:
		ls.bDataBits = 6;
		break;
	case CS7:
		ls.bDataBits = 7;
		break;
	case CS8:
		ls.bDataBits = 8;
		break;
	}

	err = uplcom_set_line_coding(sc, &ls);
	if (err) {
		DPRINTF(("uplcom_param: err=%s\n", usbd_errstr(err)));
		return (EIO);
	}

	if (ISSET(t->c_cflag, CRTSCTS))
		uplcom_set_crtscts(sc);

	if (sc->sc_rts == -1 || sc->sc_dtr == -1)
		uplcom_set_line_state(sc);

	if (err) {
		DPRINTF(("uplcom_param: err=%s\n", usbd_errstr(err)));
		return (EIO);
	}

	return (0);
}
Ejemplo n.º 5
0
int
ugl_send(struct ugl_softc *sc, struct mbuf *m, int idx)
{
	int			total_len;
	struct ugl_chain	*c;
	usbd_status		err;

	c = &sc->sc_cdata.ugl_tx_chain[idx];

	/*
	 * Copy the mbuf data into a contiguous buffer, leaving two
	 * bytes at the beginning to hold the frame length.
	 */
	USETDW(c->ugl_buf->pkt_count, UGL_TX_FRAMES);
	USETDW(c->ugl_buf->pkt_length, m->m_pkthdr.len);
	m_copydata(m, 0, m->m_pkthdr.len, c->ugl_buf->pkt_data);
	c->ugl_mbuf = m;

	total_len = offsetof(struct ugl_packet, pkt_data[m->m_pkthdr.len]);

	DPRINTFN(10,("%s: %s: total_len=%d\n",
		     sc->sc_dev.dv_xname, __func__, total_len));

	usbd_setup_xfer(c->ugl_xfer, sc->sc_ep[UGL_ENDPT_TX],
	    c, c->ugl_buf, total_len, USBD_FORCE_SHORT_XFER | USBD_NO_COPY,
	    USBD_DEFAULT_TIMEOUT, ugl_txeof);

	/* Transmit */
	err = usbd_transfer(c->ugl_xfer);
	if (err != USBD_IN_PROGRESS) {
		printf("%s: ugl_send error=%s\n", sc->sc_dev.dv_xname,
		       usbd_errstr(err));
		ugl_stop(sc);
		return (EIO);
	}

	sc->sc_cdata.ugl_tx_cnt++;

	return (0);
}
Ejemplo n.º 6
0
/* write 4bytes to register */
Static int
url_csr_write_4(struct url_softc *sc, int reg, int aval)
{
	uDWord val;

	DPRINTFN(0x100,
		 ("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __func__));

	USETDW(val, aval);

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

	return (url_mem(sc, URL_CMD_WRITEMEM, reg, &val, 4) ? -1 : 0);
}
Ejemplo n.º 7
0
Static int
umct_request(struct umct_softc *sc, uint8_t request, int len, uint32_t value)
{
	usb_device_request_t req;
	usbd_status err;
	uint8_t oval[4];

	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
	req.bRequest = request;
	USETW(req.wValue, 0);
	USETW(req.wIndex, sc->sc_iface_number);
	USETW(req.wLength, len);
	USETDW(oval, value);

	err = usbd_do_request(sc->sc_ucom.sc_udev, &req, oval);
	if (err)
		printf("%s: ubsa_request: %s\n",
		    USBDEVNAME(sc->sc_ucom.sc_dev), usbd_errstr(err));
	return (err);
}
Ejemplo n.º 8
0
int
ueagle_cr(struct ueagle_softc *sc, uint32_t address, uint16_t offset,
    uint32_t *data)
{
	struct ueagle_cmv cmv;
	usbd_status error;
	int s;

	USETW(cmv.wPreamble, UEAGLE_CMV_PREAMBLE);
	cmv.bDst = UEAGLE_MODEM;
	cmv.bFunction = UEAGLE_CR;
	USETW(cmv.wIndex, sc->index);
	USETW(cmv.wOffsetAddress, offset);
	USETDW(cmv.dwSymbolicAddress, address);
	USETDATA(cmv.dwData, 0);

#ifdef USB_DEBUG
	if (ueagledebug >= 15) {
		printf("%s: reading CMV\n", sc->sc_dev.dv_xname);
		ueagle_dump_cmv(sc, &cmv);
	}
#endif

	s = splusb();

	ueagle_request(sc, UEAGLE_SETBLOCK, UEAGLE_MPTXSTART, &cmv, sizeof cmv);

	/* wait at most 2 seconds for an answer */
	error = tsleep(UEAGLE_COND_CMV(sc), PZERO, "cmv", 2 * hz);
	if (error != 0) {
		printf("%s: timeout waiting for CMV ack\n",
		    sc->sc_dev.dv_xname);
		splx(s);
		return error;
	}

	*data = sc->data;
	splx(s);

	return 0;
}
Ejemplo n.º 9
0
static void
usb_modem_control_ep_test(struct modem *p, uint32_t duration, uint8_t flag)
{
	struct timeval sub_tv;
	struct timeval ref_tv;
	struct timeval res_tv;
	struct LIBUSB20_CONTROL_SETUP_DECODED setup;
	struct usb_cdc_abstract_state ast;
	struct usb_cdc_line_state ls;
	uint16_t feature = UCDC_ABSTRACT_STATE;
	uint16_t state = UCDC_DATA_MULTIPLEXED;
	uint8_t iface_no;
	uint8_t buf[4];
	int id = 0;
	int iter = 0;

	time_t last_sec;

	iface_no = p->usb_iface - 1;

	gettimeofday(&ref_tv, 0);

	last_sec = ref_tv.tv_sec;

	printf("\nTest=%d\n", (int)flag);

	while (1) {

		gettimeofday(&sub_tv, 0);

		if (last_sec != sub_tv.tv_sec) {

			printf("STATUS: ID=%u, COUNT=%u tests/sec ERR=%u\n",
			    (int)id,
			    (int)iter,
			    (int)p->errors);

			fflush(stdout);

			last_sec = sub_tv.tv_sec;

			id++;

			iter = 0;
		}
		timersub(&sub_tv, &ref_tv, &res_tv);

		if ((res_tv.tv_sec < 0) || (res_tv.tv_sec >= (int)duration))
			break;

		LIBUSB20_INIT(LIBUSB20_CONTROL_SETUP, &setup);

		if (flag & 1) {
			setup.bmRequestType = UT_READ_CLASS_INTERFACE;
			setup.bRequest = 0x03;
			setup.wValue = 0x0001;
			setup.wIndex = iface_no;
			setup.wLength = 0x0002;

			if (libusb20_dev_request_sync(p->usb_dev, &setup, buf, NULL, 250, 0)) {
				p->errors++;
			}
		}
		if (flag & 2) {
			setup.bmRequestType = UT_WRITE_CLASS_INTERFACE;
			setup.bRequest = UCDC_SET_COMM_FEATURE;
			setup.wValue = feature;
			setup.wIndex = iface_no;
			setup.wLength = UCDC_ABSTRACT_STATE_LENGTH;
			USETW(ast.wState, state);

			if (libusb20_dev_request_sync(p->usb_dev, &setup, &ast, NULL, 250, 0)) {
				p->errors++;
			}
		}
		if (flag & 4) {
			USETDW(ls.dwDTERate, 115200);
			ls.bCharFormat = UCDC_STOP_BIT_1;
			ls.bParityType = UCDC_PARITY_NONE;
			ls.bDataBits = 8;

			setup.bmRequestType = UT_WRITE_CLASS_INTERFACE;
			setup.bRequest = UCDC_SET_LINE_CODING;
			setup.wValue = 0;
			setup.wIndex = iface_no;
			setup.wLength = sizeof(ls);

			if (libusb20_dev_request_sync(p->usb_dev, &setup, &ls, NULL, 250, 0)) {
				p->errors++;
			}
		}
		iter++;
	}

	printf("\nModem control endpoint test done!\n");
}
Ejemplo n.º 10
0
/*------------------------------------------------------------------------*
 *	cdce_ncm_init
 *
 * Return values:
 * 0: Success
 * Else: Failure
 *------------------------------------------------------------------------*/
static uint8_t
cdce_ncm_init(struct cdce_softc *sc)
{
	struct usb_ncm_parameters temp;
	struct usb_device_request req;
	struct usb_ncm_func_descriptor *ufd;
	uint8_t value[8];
	int err;

	ufd = usbd_find_descriptor(sc->sc_ue.ue_udev, NULL,
	    sc->sc_ifaces_index[1], UDESC_CS_INTERFACE, 0 - 1,
	    UCDC_NCM_FUNC_DESC_SUBTYPE, 0 - 1);

	/* verify length of NCM functional descriptor */
	if (ufd != NULL) {
		if (ufd->bLength < sizeof(*ufd))
			ufd = NULL;
		else
			DPRINTFN(1, "Found NCM functional descriptor.\n");
	}

	req.bmRequestType = UT_READ_CLASS_INTERFACE;
	req.bRequest = UCDC_NCM_GET_NTB_PARAMETERS;
	USETW(req.wValue, 0);
	req.wIndex[0] = sc->sc_ifaces_index[1];
	req.wIndex[1] = 0;
	USETW(req.wLength, sizeof(temp));

	err = usbd_do_request_flags(sc->sc_ue.ue_udev, NULL, &req,
	    &temp, 0, NULL, 1000 /* ms */);
	if (err)
		return (1);

	/* Read correct set of parameters according to device mode */

	if (usbd_get_mode(sc->sc_ue.ue_udev) == USB_MODE_HOST) {
		sc->sc_ncm.rx_max = UGETDW(temp.dwNtbInMaxSize);
		sc->sc_ncm.tx_max = UGETDW(temp.dwNtbOutMaxSize);
		sc->sc_ncm.tx_remainder = UGETW(temp.wNdpOutPayloadRemainder);
		sc->sc_ncm.tx_modulus = UGETW(temp.wNdpOutDivisor);
		sc->sc_ncm.tx_struct_align = UGETW(temp.wNdpOutAlignment);
		sc->sc_ncm.tx_nframe = UGETW(temp.wNtbOutMaxDatagrams);
	} else {
		sc->sc_ncm.rx_max = UGETDW(temp.dwNtbOutMaxSize);
		sc->sc_ncm.tx_max = UGETDW(temp.dwNtbInMaxSize);
		sc->sc_ncm.tx_remainder = UGETW(temp.wNdpInPayloadRemainder);
		sc->sc_ncm.tx_modulus = UGETW(temp.wNdpInDivisor);
		sc->sc_ncm.tx_struct_align = UGETW(temp.wNdpInAlignment);
		sc->sc_ncm.tx_nframe = UGETW(temp.wNtbOutMaxDatagrams);
	}

	/* Verify maximum receive length */

	if ((sc->sc_ncm.rx_max < 32) || 
	    (sc->sc_ncm.rx_max > CDCE_NCM_RX_MAXLEN)) {
		DPRINTFN(1, "Using default maximum receive length\n");
		sc->sc_ncm.rx_max = CDCE_NCM_RX_MAXLEN;
	}

	/* Verify maximum transmit length */

	if ((sc->sc_ncm.tx_max < 32) ||
	    (sc->sc_ncm.tx_max > CDCE_NCM_TX_MAXLEN)) {
		DPRINTFN(1, "Using default maximum transmit length\n");
		sc->sc_ncm.tx_max = CDCE_NCM_TX_MAXLEN;
	}

	/* 
	 * Verify that the structure alignment is:
	 * - power of two
	 * - not greater than the maximum transmit length
	 * - not less than four bytes
	 */
	if ((sc->sc_ncm.tx_struct_align < 4) ||
	    (sc->sc_ncm.tx_struct_align != 
	     ((-sc->sc_ncm.tx_struct_align) & sc->sc_ncm.tx_struct_align)) ||
	    (sc->sc_ncm.tx_struct_align >= sc->sc_ncm.tx_max)) {
		DPRINTFN(1, "Using default other alignment: 4 bytes\n");
		sc->sc_ncm.tx_struct_align = 4;
	}

	/* 
	 * Verify that the payload alignment is:
	 * - power of two
	 * - not greater than the maximum transmit length
	 * - not less than four bytes
	 */
	if ((sc->sc_ncm.tx_modulus < 4) ||
	    (sc->sc_ncm.tx_modulus !=
	     ((-sc->sc_ncm.tx_modulus) & sc->sc_ncm.tx_modulus)) ||
	    (sc->sc_ncm.tx_modulus >= sc->sc_ncm.tx_max)) {
		DPRINTFN(1, "Using default transmit modulus: 4 bytes\n");
		sc->sc_ncm.tx_modulus = 4;
	}

	/* Verify that the payload remainder */

	if ((sc->sc_ncm.tx_remainder >= sc->sc_ncm.tx_modulus)) {
		DPRINTFN(1, "Using default transmit remainder: 0 bytes\n");
		sc->sc_ncm.tx_remainder = 0;
	}

	/*
	 * Offset the TX remainder so that IP packet payload starts at
	 * the tx_modulus. This is not too clear in the specification.
	 */

	sc->sc_ncm.tx_remainder = 
	    (sc->sc_ncm.tx_remainder - ETHER_HDR_LEN) &
	    (sc->sc_ncm.tx_modulus - 1);

	/* Verify max datagrams */

	if (sc->sc_ncm.tx_nframe == 0 ||
	    sc->sc_ncm.tx_nframe > (CDCE_NCM_SUBFRAMES_MAX - 1)) {
		DPRINTFN(1, "Using default max "
		    "subframes: %u units\n", CDCE_NCM_SUBFRAMES_MAX - 1);
		/* need to reserve one entry for zero padding */
		sc->sc_ncm.tx_nframe = (CDCE_NCM_SUBFRAMES_MAX - 1);
	}

	/* Additional configuration, will fail in device side mode, which is OK. */

	req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
	req.bRequest = UCDC_NCM_SET_NTB_INPUT_SIZE;
	USETW(req.wValue, 0);
	req.wIndex[0] = sc->sc_ifaces_index[1];
	req.wIndex[1] = 0;

	if (ufd != NULL &&
	    (ufd->bmNetworkCapabilities & UCDC_NCM_CAP_MAX_DGRAM)) {
		USETW(req.wLength, 8);
		USETDW(value, sc->sc_ncm.rx_max);
		USETW(value + 4, (CDCE_NCM_SUBFRAMES_MAX - 1));
		USETW(value + 6, 0);
	} else {
		USETW(req.wLength, 4);
		USETDW(value, sc->sc_ncm.rx_max);
 	}

	err = usbd_do_request_flags(sc->sc_ue.ue_udev, NULL, &req,
	    &value, 0, NULL, 1000 /* ms */);
	if (err) {
		DPRINTFN(1, "Setting input size "
		    "to %u failed.\n", sc->sc_ncm.rx_max);
	}

	req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
	req.bRequest = UCDC_NCM_SET_CRC_MODE;
	USETW(req.wValue, 0);	/* no CRC */
	req.wIndex[0] = sc->sc_ifaces_index[1];
	req.wIndex[1] = 0;
	USETW(req.wLength, 0);

	err = usbd_do_request_flags(sc->sc_ue.ue_udev, NULL, &req,
	    NULL, 0, NULL, 1000 /* ms */);
	if (err) {
		DPRINTFN(1, "Setting CRC mode to off failed.\n");
	}

	req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
	req.bRequest = UCDC_NCM_SET_NTB_FORMAT;
	USETW(req.wValue, 0);	/* NTB-16 */
	req.wIndex[0] = sc->sc_ifaces_index[1];
	req.wIndex[1] = 0;
	USETW(req.wLength, 0);

	err = usbd_do_request_flags(sc->sc_ue.ue_udev, NULL, &req,
	    NULL, 0, NULL, 1000 /* ms */);
	if (err) {
		DPRINTFN(1, "Setting NTB format to 16-bit failed.\n");
	}

	return (0);		/* success */
}
Ejemplo n.º 11
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);
}
Ejemplo n.º 12
0
static uint8_t
do_msc_cmd(uint8_t *pcmd, uint8_t cmdlen, void *pdata, uint32_t datalen,
    uint8_t isread, uint8_t isshort, uint8_t lun, uint8_t flags)
{
	umass_bbb_cbw_t cbw;
	umass_bbb_csw_t csw;
	struct libusb20_transfer *xfer_io;
	uint32_t actlen;
	uint32_t timeout;
	int error;

	memset(&cbw, 0, sizeof(cbw));

	USETDW(cbw.dCBWSignature, xfer_wrapper_sig);
	USETDW(cbw.dCBWTag, xfer_current_id);
	xfer_current_id++;
	USETDW(cbw.dCBWDataTransferLength, datalen);
	cbw.bCBWFlags = (isread ? CBWFLAGS_IN : CBWFLAGS_OUT);
	cbw.bCBWLUN = lun;
	cbw.bCDBLength = cmdlen;
	bcopy(pcmd, cbw.CBWCDB, cmdlen);

	actlen = 0;

	timeout = ((datalen + 299999) / 300000) * 1000;
	timeout += 5000;

	if ((error = libusb20_tr_bulk_intr_sync(xfer_out,
	    &cbw, sizeof(cbw), &actlen, TIMEOUT_FILTER(1000)))) {
		printf("ERROR: CBW reception: %d\n", error);
		do_msc_reset(lun);
		return (1);
	}
	if (actlen != sizeof(cbw)) {
		printf("ERROR: CBW length: %d != %d\n",
		    actlen, (int)sizeof(cbw));
		do_msc_reset(lun);
		return (1);
	}
	if (flags & 1)
		datalen /= 2;

	if (datalen != 0) {
		xfer_io = isread ? xfer_in : xfer_out;

		if ((error = libusb20_tr_bulk_intr_sync(xfer_io,
		    pdata, datalen, &actlen, TIMEOUT_FILTER(timeout)))) {
			printf("ERROR: Data transfer: %d\n", error);
			do_msc_reset(lun);
			return (1);
		}
		if ((actlen != datalen) && (!isshort)) {
			printf("ERROR: Short data: %d of %d bytes\n",
			    actlen, datalen);
			do_msc_reset(lun);
			return (1);
		}
	}
	actlen = 0;
	timeout = 8;

	do {
		error = libusb20_tr_bulk_intr_sync(xfer_in, &csw,
		    sizeof(csw), &actlen, TIMEOUT_FILTER(1000));
		if (error) {
			if (error == LIBUSB20_TRANSFER_TIMED_OUT) {
				printf("TIMEOUT: Trying to get CSW again. "
				    "%d tries left.\n", timeout);
			} else {
				break;
			}
		} else {
			break;
		}
	} while (--timeout);

	if (error) {
		libusb20_tr_clear_stall_sync(xfer_in);
		error = libusb20_tr_bulk_intr_sync(xfer_in, &csw,
		    sizeof(csw), &actlen, TIMEOUT_FILTER(1000));
		if (error) {
			libusb20_tr_clear_stall_sync(xfer_in);
			printf("ERROR: Could not read CSW: Stalled or "
			    "timeout (%d).\n", error);
			do_msc_reset(lun);
			return (1);
		}
	}
	if (UGETDW(csw.dCSWSignature) != CSWSIGNATURE) {
		printf("ERROR: Wrong CSW signature\n");
		do_msc_reset(lun);
		return (1);
	}
	if (actlen != sizeof(csw)) {
		printf("ERROR: Wrong CSW length: %d != %d\n",
		    actlen, (int)sizeof(csw));
		do_msc_reset(lun);
		return (1);
	}
	if (csw.bCSWStatus != 0) {
		printf("ERROR: CSW status: %d\n", (int)csw.bCSWStatus);
		return (1);
	} else {
		stats.xfer_success++;
		return (0);
	}
}
Ejemplo n.º 13
0
static void
cdce_intr_write_callback(struct usb_xfer *xfer, usb_error_t error)
{
	struct cdce_softc *sc = usbd_xfer_softc(xfer);
	struct usb_cdc_notification req;
	struct usb_page_cache *pc;
	uint32_t speed;
	int actlen;

	usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);

	switch (USB_GET_STATE(xfer)) {
	case USB_ST_TRANSFERRED:

		DPRINTF("Transferred %d bytes\n", actlen);

		switch (sc->sc_notify_state) {
		case CDCE_NOTIFY_NETWORK_CONNECTION:
			sc->sc_notify_state = CDCE_NOTIFY_SPEED_CHANGE;
			break;
		case CDCE_NOTIFY_SPEED_CHANGE:
			sc->sc_notify_state = CDCE_NOTIFY_DONE;
			break;
		default:
			break;
		}

		/* FALLTHROUGH */
	case USB_ST_SETUP:
tr_setup:
		/*
		 * Inform host about connection. Required according to USB CDC
		 * specification and communicating to Mac OS X USB host stack.
		 * Some of the values seems ignored by Mac OS X though.
		 */
		if (sc->sc_notify_state == CDCE_NOTIFY_NETWORK_CONNECTION) {
			req.bmRequestType = UCDC_NOTIFICATION;
			req.bNotification = UCDC_N_NETWORK_CONNECTION;
			req.wIndex[0] = sc->sc_ifaces_index[1];
			req.wIndex[1] = 0;
			USETW(req.wValue, 1); /* Connected */
			USETW(req.wLength, 0);

			pc = usbd_xfer_get_frame(xfer, 0);
			usbd_copy_in(pc, 0, &req, sizeof(req));
			usbd_xfer_set_frame_len(xfer, 0, sizeof(req));
			usbd_xfer_set_frames(xfer, 1);
			usbd_transfer_submit(xfer); 

		} else if (sc->sc_notify_state == CDCE_NOTIFY_SPEED_CHANGE) {
			req.bmRequestType = UCDC_NOTIFICATION;
			req.bNotification = UCDC_N_CONNECTION_SPEED_CHANGE;
			req.wIndex[0] = sc->sc_ifaces_index[1];
			req.wIndex[1] = 0;
			USETW(req.wValue, 0);
			USETW(req.wLength, 8);

			/* Peak theoretical bulk trasfer rate in bits/s */
			if (usbd_get_speed(sc->sc_ue.ue_udev) != USB_SPEED_FULL)
				speed = (13 * 512 * 8 * 1000 * 8);
			else
				speed = (19 * 64 * 1 * 1000 * 8);

			USETDW(req.data + 0, speed); /* Upstream bit rate */
			USETDW(req.data + 4, speed); /* Downstream bit rate */
 
			pc = usbd_xfer_get_frame(xfer, 0);
			usbd_copy_in(pc, 0, &req, sizeof(req));
			usbd_xfer_set_frame_len(xfer, 0, sizeof(req));
			usbd_xfer_set_frames(xfer, 1);
			usbd_transfer_submit(xfer); 
		}
		break;

	default:			/* Error */
		if (error != USB_ERR_CANCELLED) {
			if (usbd_get_mode(sc->sc_ue.ue_udev) == USB_MODE_HOST) {
				/* start clear stall */
				usbd_xfer_set_stall(xfer);
			}
			goto tr_setup;
		}
		break;
	}
}