// --------------------------------------------------------------------------- BOOL CPU_USB_StartOutput(USB_CONTROLLER_STATE* State, int epNum) { if (State == NULL || epNum >= State->EndpointCount) return FALSE; GLOBAL_LOCK(irq); // Exit if endpoint has no output queue if (State->Queues[epNum] == NULL || !State->IsTxQueue[epNum]) return FALSE; // If endpoint status is halt, clear all queues if (State->EndpointStatus[epNum] & USB_STATUS_ENDPOINT_HALT) { while (USB_TxDequeue(State, epNum, TRUE) != NULL); // Clear TX queue return TRUE; } USBD_HANDLE_T hUsb = (State == USB_STATE(0)) ? USB_HANDLE(0) : USB_HANDLE(1); int core = USB_CORE(hUsb); USB_PACKET64* Packet64; UINT8* dst = ep_in_data[core]; UINT32 cnt = 0; // Hold if buffer pending if (ep_in_count[core] != 0) return FALSE; // If payload missing, hold until flush to avoid host timeout at HS Packet64 = USB_TxDequeue(State, epNum, FALSE); if (Packet64->Size == sizeof(WP_Packet) && ((memcmp(Packet64->Buffer, MARKER_DEBUGGER_V1, 7) == 0) || (memcmp(Packet64->Buffer, MARKER_PACKET_V1, 7) == 0))) { memcpy(dst, Packet64->Buffer, Packet64->Size); int missing = ((WP_Packet*)dst)->m_size + sizeof(WP_Packet); for (int i = 0; i < State->Queues[epNum]->NumberOfElements(); i++) { missing -= (*State->Queues[epNum])[i]->Size; } if (missing != 0) return FALSE; } // Copy packets to endpoint buffer cnt = 0; while ((Packet64 = USB_TxDequeue(State, epNum, FALSE)) != NULL) // Peek { if ((cnt + Packet64->Size) > EP_MEM_SIZE) break; Packet64 = USB_TxDequeue(State, epNum, TRUE); // Pop memcpy(dst, Packet64->Buffer, Packet64->Size); dst += Packet64->Size; cnt += Packet64->Size; } ep_in_count[core] = cnt; // Transmit buffer USB_EP_In_Handler(hUsb, (void*) epNum, USB_EVT_IN); return TRUE; }
void AT91_USBHS_Driver::TxPacket( USB_CONTROLLER_STATE* State, int endpoint ) { ASSERT( endpoint < c_Used_Endpoints ); ASSERT( State ); struct AT91_UDPHS *pUdp = (struct AT91_UDPHS *) (AT91C_BASE_UDP) ; UINT8 * pDest = (UINT8*) ((((struct AT91_UDPHS_EPTFIFO *)AT91C_BASE_UDP_DMA)->UDPHS_READEPT0) + 16384 * endpoint); GLOBAL_LOCK(irq); // transmit a packet on UsbPortNum, if there are no more packets to transmit, then die USB_PACKET64* Packet64; Packet64 = USB_TxDequeue( State, endpoint, TRUE ); if(Packet64 != NULL && Packet64->Size == 0) { g_AT91_USBHS_Driver.TxNeedZLPS[endpoint] = TRUE; Packet64 = NULL; } while (pUdp->UDPHS_EPT[endpoint].UDPHS_EPTSTA & AT91C_UDPHS_TX_PK_RDY); if(Packet64) { int i; // We should absolutely have an empty buffer to use // ASSERT(pEp->UDP_CSR[endpoint] & AT91C_UDP_TXPKTRDY); // fill fifo for(i = 0; i < Packet64->Size; i++) { *pDest++ = Packet64->Buffer[i]; } g_AT91_USBHS_Driver.TxNeedZLPS[endpoint] = (Packet64->Size == 64); } else { // send the zero leght packet since we landed on the FIFO boundary before // (and we queued a zero length packet to transmit) if(g_AT91_USBHS_Driver.TxNeedZLPS[endpoint]) { g_AT91_USBHS_Driver.TxNeedZLPS[endpoint] = FALSE; } // no more data g_AT91_USBHS_Driver.TxRunning[endpoint] = FALSE; pUdp->UDPHS_EPT[endpoint].UDPHS_EPTCTLDIS = AT91C_UDPHS_TX_PK_RDY; } pUdp->UDPHS_EPT[endpoint].UDPHS_EPTSETSTA = AT91C_UDPHS_TX_PK_RDY; }
// // Data In (Tx) Endpoint Interrupt Handler // void STM32_USB_Driver_EP_In_Int(UINT32 , USB_CONTROLLER_STATE* State, int endpoint) { ASSERT_IRQ_MUST_BE_OFF(); // If this is not a legal transmit endpoint, there is nothing more to do if((State->Queues[endpoint] != NULL) && State->IsTxQueue[endpoint]) { USB_PACKET64* Packet64 = USB_TxDequeue(State, endpoint, TRUE); if(Packet64) { // More data to send // copy buffer // FIXME: Optimize, both buffers are always 64 bytes long int count = Packet64->Size; for(int i = 0; i < count; i++) { APP_Rx_Buffer[i] = Packet64->Buffer[i]; } STM32_USB_EndpointTransmit(NETMF_IN_EP, (UINT8*)APP_Rx_Buffer, count); } } }