diff --git a/firmware/target/arm/rk27xx/usb-drv-rk27xx.c b/firmware/target/arm/rk27xx/usb-drv-rk27xx.c index 810c793..d12187c 100644 --- a/firmware/target/arm/rk27xx/usb-drv-rk27xx.c +++ b/firmware/target/arm/rk27xx/usb-drv-rk27xx.c @@ -203,15 +203,30 @@ static void blk_read(int ep) { int ep_num = EP_NUM(ep); int xfer_size = BOUT_RXSTAT(ep_num) & 0xffff; + int max = usb_drv_port_speed() ? 512 : 64; + struct endpoint_t *endp = &endpoints[ep_num]; /* clear NAK bit */ BOUT_RXCON(ep_num) &= ~RXNAK; - endpoints[ep_num].cnt -= xfer_size; - endpoints[ep_num].buf += xfer_size; - - BOUT_DMAOUTLMADDR(ep_num) = (uint32_t)endpoints[ep_num].buf; - BOUT_DMAOUTCTL(ep_num) = DMA_START; + endp->cnt -= xfer_size; + endp->buf += xfer_size; + + /* if the transfer was short or if the total count is zero, transfer is complete */ + if (endp->cnt == 0 || xfer_size < max) + { + logf("udc_intr: usb_core_transfer_complete(0x%x, USB_DIR_OUT, 0, 0x%x), %ld", ep_num, endp->len, current_tick); + usb_core_transfer_complete(ep_num, /* ep */ + USB_DIR_OUT, /* dir */ + 0, /* status */ + endp->len - endp->cnt); /* length */ + endp->cnt = 0; + } + else + { + BOUT_DMAOUTLMADDR(ep_num) = (uint32_t)endp->buf; + BOUT_DMAOUTCTL(ep_num) = DMA_START; + } } static void int_write(int ep) @@ -419,21 +434,10 @@ void INT_UDC(void) rxstat = BOUT_RXSTAT(ep_num); /* TODO handle errors */ - if (rxstat & RXACK) /* RxACK */ + if (rxstat & RXACK && ep->cnt > 0) /* RxACK */ { - if (ep->cnt > 0) - { - logf("udc_intr: blk_read(0x%x), %ld", ep_num, current_tick); - blk_read(ep_num); - } - else - { - logf("udc_intr: usb_core_transfer_complete(0x%x, USB_DIR_OUT, 0, 0x%x), %ld", ep_num, ep->len, current_tick); - usb_core_transfer_complete(ep_num, /* ep */ - USB_DIR_OUT, /* dir */ - 0, /* status */ - ep->len); /* length */ - } + logf("udc_intr: blk_read(0x%x), %ld", ep_num, current_tick); + blk_read(ep_num); } } else @@ -534,15 +538,15 @@ int usb_drv_request_endpoint(int type, int dir) if (ep_num%3 == 0) /* IIN 3, 6, 9, 12, 15 */ { - IIN_TXCON(ep_num) = (ep_num<<8)|TXEPEN|TXNAK; /* ep_num, enable, NAK */ + IIN_TXCON(ep_num) = (ep_num<<8)|TXEPEN|TXNAK|TXACKINTEN; /* ep_num, enable, NAK */ } else if (ep_num%3 == 1) /* BOUT 1, 4, 7, 10, 13 */ { - BOUT_RXCON(ep_num) = (ep_num<<8)|RXEPEN|RXNAK; /* ep_num, NAK, enable */ + BOUT_RXCON(ep_num) = (ep_num<<8)|RXEPEN|RXNAK|RXACKINTEN; /* ep_num, NAK, enable */ } else if (ep_num%3 == 2) /* BIN 2, 5, 8, 11, 14 */ { - BIN_TXCON(ep_num) = (ep_num<<8)|TXEPEN|TXNAK; /* ep_num, enable, NAK */ + BIN_TXCON(ep_num) = (ep_num<<8)|TXEPEN|TXNAK|TXACKINTEN; /* ep_num, enable, NAK */ } /* enable interrupt from this endpoint */