Beispiel #1
0
/* Defaults to EP0 for now */
__noinline
static int
usb_tx_next(struct usbd_ep_pipe_state_t *s)
{

	/**
	 * Us being here means the previous transfer just completed
	 * successfully.  That means the host just toggled its data
	 * sync bit, and so do we.
	 */
	s->data01 ^= 1;

	if (s->transfer_size > 0) {
		size_t thislen = s->transfer_size;

		if (thislen > s->ep_maxsize)
			thislen = s->ep_maxsize;
		else if (thislen != s->ep_maxsize)
			s->short_transfer = 0;

		void *addr = s->data_buf + s->pos;

		if (s->copy_source) {
			/* Bounce buffer mode */
			addr = s->data_buf;
			memcpy(addr, s->copy_source + s->pos, thislen);
		}
		s->pos += thislen;
		s->transfer_size -= thislen;

		usb_queue_next(s, addr, thislen);
		s->pingpong ^= 1;

		return (1);
	}

	/**
	 * All data has been shipped.  Do we need to send a short
	 * packet?
	 */
	if (s->short_transfer) {
		s->short_transfer = 0;
		usb_queue_next(s, NULL, 0);
		s->pingpong ^= 1;
		return (1);
	}

	if (s->callback)
		s->callback(s->data_buf, s->pos, s->callback_data);

	return (0);
}
Beispiel #2
0
/**
 * Receive USB data (OUT device transaction)
 *
 * Returns: size to be received, or -1 on error.
 */
int
usb_rx(struct usbd_ep_pipe_state_t *s, void *buf, size_t len, ep_callback_t cb, void *cb_data)
{
	s->data_buf = buf;
	s->transfer_size = len;
	s->pos = 0;
	s->callback = cb;
	s->callback_data = cb_data;

	size_t thislen = s->transfer_size;
	if (thislen > s->ep_maxsize)
		thislen = s->ep_maxsize;

	usb_queue_next(s, s->data_buf, thislen);
	return (len);
}
Beispiel #3
0
/* XXX pass usb_stat to validate pingpong */
__noinline
static int
usb_rx_next(struct usbd_ep_pipe_state_t *s)
{
	/**
	 * Us being here means the previous transfer just completed
	 * successfully.  That means the host just toggled its data
	 * sync bit, and so do we.
	 */
	s->data01 ^= 1;

	size_t thislen = usb_ep_get_transfer_size(s);

	s->transfer_size -= thislen;
	s->pos += thislen;

	/**
	 * We're done with this buffer now.  Switch the pingpong now
	 * before we might have to receive the next piece of data.
	 */
	s->pingpong ^= 1;

	/**
	 * If this is a short transfer, or we received what we
	 * expected, we're done.
	 */
	if (thislen < s->ep_maxsize || s->transfer_size == 0) {
		if (s->callback)
			s->callback(s->data_buf, s->pos, s->callback_data);
		return (0);
	}

	/**
	 * Otherwise we still need to receive more data.
	 */
	size_t nextlen = s->transfer_size;

        if (nextlen > s->ep_maxsize)
                nextlen = s->ep_maxsize;

        void *addr = s->data_buf + s->pos;
	usb_queue_next(s, addr, nextlen);

	return (1);
}