Beispiel #1
0
static int
usb_std_io(usb_dev_handle * dev, int ep, char *bytes, int size,
    int timeout, int is_intr)
{
	struct libusb20_transfer *xfer;
	uint32_t temp;
	uint32_t maxsize;
	uint32_t actlen;
	char *oldbytes;

	xfer = usb_get_transfer_by_ep_no(dev, ep);
	if (xfer == NULL)
		return (-1);

	if (libusb20_tr_pending(xfer)) {
		/* there is already a transfer ongoing */
		return (-1);
	}
	maxsize = libusb20_tr_get_max_total_length(xfer);
	oldbytes = bytes;

	/*
	 * We allow transferring zero bytes which is the same
	 * equivalent to a zero length USB packet.
	 */
	do {

		temp = size;
		if (temp > maxsize) {
			/* find maximum possible length */
			temp = maxsize;
		}
		if (is_intr)
			libusb20_tr_setup_intr(xfer, bytes, temp, timeout);
		else
			libusb20_tr_setup_bulk(xfer, bytes, temp, timeout);

		libusb20_tr_start(xfer);

		while (1) {

			if (libusb20_dev_process((void *)dev) != 0) {
				/* device detached */
				return (-1);
			}
			if (libusb20_tr_pending(xfer) == 0) {
				/* transfer complete */
				break;
			}
			/* wait for USB event from kernel */
			libusb20_dev_wait_process((void *)dev, -1);
		}

		switch (libusb20_tr_get_status(xfer)) {
		case 0:
			/* success */
			break;
		case LIBUSB20_TRANSFER_TIMED_OUT:
			/* transfer timeout */
			return (-ETIMEDOUT);
		default:
			/* other transfer error */
			return (-ENXIO);
		}
		actlen = libusb20_tr_get_actual_length(xfer);

		bytes += actlen;
		size -= actlen;

		if (actlen != temp) {
			/* short transfer */
			break;
		}
	} while (size > 0);

	return (bytes - oldbytes);
}
Beispiel #2
0
static void
usb_modem_data_stress_test(struct modem *p, uint32_t duration)
{
	struct timeval sub_tv;
	struct timeval ref_tv;
	struct timeval res_tv;

	time_t last_sec;

	uint8_t in_pending = 0;
	uint8_t in_ready = 0;
	uint8_t out_pending = 0;

	uint32_t id = 0;

	uint32_t in_max;
	uint32_t out_max;
	uint32_t io_max;

	uint8_t *in_buffer = 0;
	uint8_t *out_buffer = 0;

	gettimeofday(&ref_tv, 0);

	last_sec = ref_tv.tv_sec;

	printf("\n");

	in_max = libusb20_tr_get_max_total_length(p->xfer_in);
	out_max = libusb20_tr_get_max_total_length(p->xfer_out);

	/* get the smallest buffer size and use that */
	io_max = (in_max < out_max) ? in_max : out_max;

	if (in_max != out_max)
		printf("WARNING: Buffer sizes are un-equal: %u vs %u\n", in_max, out_max);

	in_buffer = malloc(io_max);
	if (in_buffer == NULL)
		goto fail;

	out_buffer = malloc(io_max);
	if (out_buffer == NULL)
		goto fail;

	while (1) {

		gettimeofday(&sub_tv, 0);

		if (last_sec != sub_tv.tv_sec) {

			printf("STATUS: ID=%u, RX=%u bytes/sec, TX=%u bytes/sec, ERR=%d\n",
			    (int)id,
			    (int)p->rx_bytes.bytes,
			    (int)p->tx_bytes.bytes,
			    (int)p->errors);

			p->rx_bytes.bytes = 0;
			p->tx_bytes.bytes = 0;

			fflush(stdout);

			last_sec = sub_tv.tv_sec;

			id++;
		}
		timersub(&sub_tv, &ref_tv, &res_tv);

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

		libusb20_dev_process(p->usb_dev);

		if (!libusb20_tr_pending(p->xfer_in)) {
			if (in_pending) {
				if (libusb20_tr_get_status(p->xfer_in) == 0) {
					modem_read(in_buffer, libusb20_tr_get_length(p->xfer_in, 0));
				} else {
					p->errors++;
					usleep(10000);
				}
				in_pending = 0;
				in_ready = 1;
			}
			if (p->loop_data == 0) {
				libusb20_tr_setup_bulk(p->xfer_in, in_buffer, io_max, 0);
				libusb20_tr_start(p->xfer_in);
				in_pending = 1;
				in_ready = 0;
			}
		}
		if (!libusb20_tr_pending(p->xfer_out)) {

			uint32_t len;
			uint32_t dly;

			if (out_pending) {
				if (libusb20_tr_get_status(p->xfer_out) != 0) {
					p->errors++;
					usleep(10000);
				}
			}
			if (p->random_tx_length) {
				len = ((uint32_t)usb_ts_rand_noise()) % ((uint32_t)io_max);
			} else {
				len = io_max;
			}

			if (p->random_tx_delay) {
				dly = ((uint32_t)usb_ts_rand_noise()) % 16000U;
			} else {
				dly = 0;
			}

			if (p->loop_data != 0) {
				if (in_ready != 0) {
					len = libusb20_tr_get_length(p->xfer_in, 0);
					memcpy(out_buffer, in_buffer, len);
					in_ready = 0;
				} else {
					len = io_max + 1;
				}
				if (!libusb20_tr_pending(p->xfer_in)) {
					libusb20_tr_setup_bulk(p->xfer_in, in_buffer, io_max, 0);
					libusb20_tr_start(p->xfer_in);
					in_pending = 1;
				}
			} else {
				modem_write(out_buffer, len);
			}

			if (len <= io_max) {
				libusb20_tr_setup_bulk(p->xfer_out, out_buffer, len, 0);

				if (dly != 0)
					usleep(dly);

				libusb20_tr_start(p->xfer_out);

				out_pending = 1;
			}
		}
		libusb20_dev_wait_process(p->usb_dev, 500);

		if (libusb20_dev_check_connected(p->usb_dev) != 0) {
			printf("Device disconnected\n");
			break;
		}
	}

	libusb20_tr_stop(p->xfer_in);
	libusb20_tr_stop(p->xfer_out);

	printf("\nData stress test done!\n");

fail:
	if (in_buffer)
		free(in_buffer);
	if (out_buffer)
		free(out_buffer);
}
Beispiel #3
0
uint8_t
libusb20_tr_bulk_intr_sync(struct libusb20_transfer *xfer,
    void *pbuf, uint32_t length, uint32_t *pactlen,
    uint32_t timeout)
{
	struct libusb20_device *pdev = xfer->pdev;
	uint32_t transfer_max;
	uint32_t transfer_act;
	uint8_t retval;

	/* set some sensible default value */
	if (pactlen != NULL)
		*pactlen = 0;

	/* check for error condition */
	if (libusb20_tr_pending(xfer))
		return (LIBUSB20_ERROR_OTHER);

	do {
		/* compute maximum transfer length */
		transfer_max = 
		    libusb20_tr_get_max_total_length(xfer);

		if (transfer_max > length)
			transfer_max = length;

		/* setup bulk or interrupt transfer */
		libusb20_tr_setup_bulk(xfer, pbuf, 
		    transfer_max, timeout);

		/* start the transfer */
		libusb20_tr_start(xfer);

		/* wait for transfer completion */
		while (libusb20_dev_process(pdev) == 0) {

			if (libusb20_tr_pending(xfer) == 0)
				break;

			libusb20_dev_wait_process(pdev, -1);
		}

		transfer_act = libusb20_tr_get_actual_length(xfer);

		/* update actual length, if any */
		if (pactlen != NULL)
			pactlen[0] += transfer_act;

		/* check transfer status */
		retval = libusb20_tr_get_status(xfer);
		if (retval)
			break;

		/* check for short transfer */
		if (transfer_act != transfer_max)
			break;

		/* update buffer pointer and length */
		pbuf = ((uint8_t *)pbuf) + transfer_max;
		length = length - transfer_max;

	} while (length != 0);

	return (retval);
}