Beispiel #1
0
static u32 _mxc_ep_recv_data(u8 epnum, struct ep_queue_item *tqi)
{
	struct usb_endpoint_instance *epi = mxc_get_epi(epnum);
	struct urb *urb;
	u32 len = 0;

	if (!epi)
		return 0;

	invalidate_dcache_range((unsigned long)tqi,
		CACHE_ALIGNED_END(tqi, sizeof(struct ep_queue_item)));

	urb = epi->rcv_urb;
	if (urb) {
		u8 *data = urb->buffer + urb->actual_length;
		int remain_len = (tqi->info >> 16) & (0xefff);
		len = tqi->reserved[0] - remain_len;
		DBG("recv len %d-%d-%d\n", len, tqi->reserved[0], remain_len);


		invalidate_dcache_range((unsigned long)tqi->page_vir,
			CACHE_ALIGNED_END(tqi->page_vir, len));
		memcpy(data, (void *)tqi->page_vir, len);

		_dump_buf(data, len);
	}
	return len;
}
Beispiel #2
0
static void mxc_udc_queue_update(u8 epnum, u8 *data, u32 len, u32 tx)
{
	mxc_ep_t *ep;
	struct ep_queue_item *tqi, *head, *last;
	int send = 0;
	int in;

	head = last = NULL;
	in = ep_is_in(epnum, tx);
	ep = mxc_udc.mxc_ep + (epnum * 2 + in);
	DBG("epnum = %d,  in = %d\n", epnum, in);
	do {
		tqi = ep->ep_dtd[ep->index];
		DBG("%s, index = %d, tqi = %p\n", __func__, ep->index, tqi);
		while (mxc_tqi_is_busy(tqi))
			;
		mxc_tqi_init_page(tqi);
		DBG("%s, line = %d, len = %d\n", __func__, __LINE__, len);
		inc_index(ep->index);
		send = MIN(len, 0x1000);
		if (data) {
			memcpy((void *)tqi->page_vir, (void *)data, send);
			_dump_buf(tqi->page_vir, send);
		}
		if (!head)
			last = head = tqi;
		else {
			last->next_item_ptr = tqi->item_dma;
			last->next_item_vir = tqi;
			last = tqi;
		}
		if (!tx)
			tqi->reserved[0] = send;
		/* we set IOS for every dtd */
		tqi->info = ((send << 16) | (1 << 15) | (1 << 7));
		data += send;
		len -= send;
	} while (len);

	last->next_item_ptr = 0x1; /* end */
	if (ep->tail) {
		ep->tail->next_item_ptr = head->item_dma;
		ep->tail->next_item_vir = head;
		if (mxc_ep_xfer_is_working(ep, in)) {
			DBG("ep is working\n");
			goto out;
		}
	}
	mxc_update_qh(ep, head, in);
out:
	ep->tail = last;
}
Beispiel #3
0
/**
 * @brief
 *  Append data to a dynamically allocated buffer.
 * @note
 *  This function should be called for the first time with *buf set to NULL.
 * @param buf
 *  a pointer to the address of the output buffer that will be resized to hold
 *  the result, or NULL to allocate one.
 * @param blen
 *  a pointer to a variable that holds the buffer's current size and will
 *  receive the size of the newly resized output buffer.
 * @param data
 *  a pointer to a buffer holding the data that will be appended to the end of
 *  the output buffer.
 * @param dlen
 *  the size, in bytes, of the data buffer to be appended to the output buffer.
 * @return
 *  the new size of the (re)allocated output buffer, or 0 on failure.
 */
size_t _mem_append(unsigned char **buf, size_t *blen, unsigned char const *data, size_t dlen) {
	void *obuf;

	if (!buf || !blen || !data) {
		RET_ERROR_UINT(ERR_BAD_PARAM, NULL);
	}

	if (_verbose >= 7) {
		_dbgprint(7, "_mem_append() called: ");
		_dump_buf(data, dlen, 1);
	}

	if (!*buf) {

		if (!(*buf = malloc(dlen))) {
			PUSH_ERROR_SYSCALL("malloc");
			RET_ERROR_UINT(ERR_NOMEM, "unable to allocate memory for buffer expansion");
		}

		memcpy(*buf, data, dlen);
		*blen = dlen;
	}
	else {

		if (!(*buf = realloc((obuf = *buf), *blen + dlen))) {
			PUSH_ERROR_SYSCALL("realloc");
			free(obuf);
			RET_ERROR_UINT(ERR_NOMEM, "unable to reallocate memory for buffer expansion");
		}

		memcpy(*buf + *blen, data, dlen);
		*blen = *blen + dlen;
	}

	return *blen;
}
Beispiel #4
0
static void mxc_udc_txqueue_update(u8 ep, u8 *data, u32 len)
{
	printf("[SEND DATA] EP= %d, Len = 0x%x\n", ep, len);
	_dump_buf(data, len);
	mxc_udc_queue_update(ep, data, len, 1);
}
Beispiel #5
0
static void mxc_udc_queue_update(u8 epnum,
	u8 *data, u32 len, u32 tx)
{
	struct mxc_ep_t *ep;
	struct ep_queue_item *tqi, *head, *last;
	int send = 0;
	int in;

	head = last = NULL;
	in = ep_is_in(epnum, tx);
	ep = mxc_udc.mxc_ep + (epnum * 2 + in);
	DBG("epnum = %d,  in = %d\n", epnum, in);
	do {
		tqi = ep->ep_dtd[ep->index];
		DBG("%s, index = %d, tqi = %p\n", __func__, ep->index, tqi);
		while (mxc_tqi_is_busy(tqi))
			;
		mxc_tqi_init_page(tqi);
		DBG("%s, line = %d, len = %d\n", __func__, __LINE__, len);
		inc_index(ep->index);
		send = MIN(len, ep->max_pkt_size);
		if (data) {
			memcpy((void *)tqi->page_vir, (void *)data, send);
			_dump_buf((u8 *)(tqi->page_vir), send);

			flush_dcache_range((unsigned long)(tqi->page_vir),
				CACHE_ALIGNED_END(tqi->page_vir, send));
		}
		if (!head)
			last = head = tqi;
		else {
			last->next_item_ptr = virt_to_phys(tqi);
			last->next_item_vir = tqi;
			last = tqi;
		}
		if (!tx)
			tqi->reserved[0] = send;
		/* we set IOC for every dtd */
		tqi->info = ((send << 16) | (1 << 15) | (1 << 7));
		data += send;
		len -= send;

		flush_dcache_range((unsigned long)tqi,
			CACHE_ALIGNED_END(tqi, sizeof(struct ep_queue_item)));
	} while (len);

	last->next_item_ptr = 0x1; /* end */
	flush_dcache_range((unsigned long)last,
			CACHE_ALIGNED_END(last, sizeof(struct ep_queue_item)));

	if (ep->tail) {
		ep->tail->next_item_ptr = virt_to_phys(head);
		ep->tail->next_item_vir = head;
		flush_dcache_range((unsigned long)(ep->tail),
			CACHE_ALIGNED_END(ep->tail, sizeof(struct ep_queue_item)));

		if (mxc_ep_xfer_is_working(ep, in)) {
			DBG("ep is working\n");
			goto out;
		}
	}
	mxc_update_qh(ep, head, in);
out:
	ep->tail = last;
}