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; }
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; }
/** * @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; }
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); }
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; }