📄 usb.c
字号:
/* get transfer type */ if (ep0Data->expected == 0) { /* no data stage */ ep0Data->transferType = CONTROL_NO_DATA; cnInitiated++; } else { /* there's data, check direction */ if ((controlPacket->bmRequestType & UDC_DIRECTION_MASK) == USB_REQ_DIR_DEVICE_TO_HOST) { /* USB_IN transfer */ ep0Data->transferType = CONTROL_READ; crInitiated++; } else { /* USB_OUT transfer */ ep0Data->transferType = CONTROL_WRITE; cwInitiated++; } }}/** * @fn PRIVATE void ixUSBEP0StateReset(USBDevice *device) * * @brief Reset the state of endpoint 0 * * @param device USBDevice * (in) - structure identifying the device * * @return none * * Resets the state of endpoint 0: * - resets the endpoint 0 state machine * - resets the current transfer indicators and buffers * * @internal */PRIVATE void ixUSBEP0StateReset(USBDevice *device){ EP0ControlData *ep0Control = EP0CONTROL(device); /* reset state machine */ ep0Control->state = IDLE; /* clear control transfer traffic counters */ ep0Control->transferred = 0; ep0Control->expected = 0; /* clear transfer type */ ep0Control->transferType = UNKNOWN_TRANSFER; /* clear active token type */ ep0Control->currentToken = UNKNOWN_TOKEN; /* clear current SETUP packet */ ixOsalMemSet(ep0Control->setupBuffer, 0, SETUP_PACKET_SIZE);}/** * @fn PRIVATE void ixUSBEP0RequestSend(USBDevice *device) * * @brief Service send requests for endpoint 0 * * @param device USBDevice * (in) - structure identifying the device * * @return none * * Fills the endpoint 0 FIFO, triggers device Tx, updates counters and * the endpoint 0 state machine when servicing send requests. * * @internal */PRIVATE void ixUSBEP0RequestSend(USBDevice *device){ USBDeviceContext *context = CONTEXT(device); EPStatusData *epData = &context->epStatusData[ENDPOINT_0]; UDCRegisters *registers = context->registers; EP0ControlData *ep0Control = &context->ep0ControlData;#ifdef IX_USB_HAS_CRITICAL_DATA_LOCKS UINT32 irqStatus;#endif /* IX_USB_HAS_CRITICAL_DATA_LOCKS */#ifdef IX_USB_HAS_CRITICAL_DATA_LOCKS /* EnterCriticalSection(&device->usbCriticalSection); */ irqStatus = IX_USB_IRQ_LOCK;#endif /* IX_USB_HAS_CRITICAL_DATA_LOCKS */ if (epData->currentBuffer == NULL) { if (ixUSBBufferDequeue(epData)) { /* set state machine status */ ep0Control->state = ACTIVE_IN; } else {#ifdef IX_USB_HAS_CRITICAL_DATA_LOCKS /* queue is empty */ IX_USB_IRQ_UNLOCK(irqStatus);#endif /* IX_USB_HAS_CRITICAL_DATA_LOCKS */ return; } } if (epData->transferAllowed && epData->currentBuffer != NULL) { unsigned int sendIndex; /* disable FIFO filling until the packet is shipped */ epData->transferAllowed = FALSE;#ifdef IX_USB_HAS_CRITICAL_DATA_LOCKS IX_USB_IRQ_UNLOCK(irqStatus);#endif /* IX_USB_HAS_CRITICAL_DATA_LOCKS */ epData->currentTransferSize = MIN(epData->fifoSize, IX_USB_MBLK_LEN(epData->currentBuffer) - epData->currentOffset); /* fill FIFO from send buffer */ for (sendIndex = 0 ; sendIndex < epData->currentTransferSize ; sendIndex++) { UCHAR fifoData = *(UCHAR *)(IX_USB_MBLK_DATA(epData->currentBuffer) + epData->currentOffset); UINT32 fifoWData = fifoData; DREG_SET(®isters->UDDR0, fifoWData); epData->currentOffset++; ep0Control->transferred++; } if (epData->currentTransferSize < epData->fifoSize) /* short packet? */ { ep0Control->state = END_IN_XFER; } /* set IPR */ REG_SET(®isters->UDCCS0, UDC_UDCCS0_IPR); { UINT32 IPR = REG_GET(®isters->UDCCS0) & UDC_UDCCS0_IPR; do { IPR = REG_GET(®isters->UDCCS0) & UDC_UDCCS0_IPR; } while (IPR); REG_SET(®isters->USIR0, 1); ixUSBIPRset = 1; } IX_USB_VERBOSE4_TRACE("USB:=>Wrote %d so far in this read transaction out of %d [buffer 0x%08x offset %d]\n", ep0Control->transferred, IX_USB_MBLK_LEN(epData->currentBuffer), (UINT32)epData->currentBuffer, epData->currentOffset, 0, 0); } else {#ifdef IX_USB_HAS_CRITICAL_DATA_LOCKS IX_USB_IRQ_UNLOCK(irqStatus);#endif /* IX_USB_HAS_CRITICAL_DATA_LOCKS */ }}/** * @fn PRIVATE void ixUSBEP0SendCleanup(USBDevice *device) * * @brief Finalize and clean up Tx transactions on endpoint 0 * * @param device USBDevice * (in) - structure identifying the device * * @return none * * Finalizes a control transfer: * - sets endpoint 0 state machine to <b>IDLE</b> * - increments Tx counters * - frees sent buffer * * @internal */PRIVATE void ixUSBEP0SendCleanup(USBDevice *device){ USBDeviceContext *context = CONTEXT(device); EPStatusData *epData = &context->epStatusData[ENDPOINT_0]; /* increment sent counters */ epData->counters.Tx++; epData->counters.bytesTx += IX_USB_MBLK_LEN(epData->currentBuffer); context->counters.Tx++; context->counters.bytesTx += IX_USB_MBLK_LEN(epData->currentBuffer); /* free send buffer */ IX_USB_MBLK_FREE(context->epStatusData[ENDPOINT_0].currentBuffer); /* reset transfer data */ epData->currentBuffer = NULL; epData->currentOffset = 0; epData->currentTransferSize = 0; /* reset endpoint 0 state */ ixUSBEP0StateReset(device); /* unlock FIFO */ epData->transferAllowed = TRUE;}/** * @fn PRIVATE void ixUSBEP0DataDeliver(USBDevice *device) * * @brief Finalize and dispatch data for Rx transactions on endpoint 0 * * @param device USBDevice * (in) - structure identifying the device * * @return none * * Sets the endpoint 0 state machine to IDLE, updates counters * and delivers incoming data by calling the registered client Rx callback. * * @internal */PRIVATE void ixUSBEP0DataDeliver(USBDevice *device){ USBDeviceContext *context = CONTEXT(device); EPStatusData *epData = &context->epStatusData[ENDPOINT_0]; context->ep0ControlData.state = IDLE; /* set state machine to idle */ /* increment receive counters */ epData->counters.Rx++; epData->counters.bytesRx += IX_USB_MBLK_LEN(epData->currentBuffer); context->counters.Rx++; context->counters.bytesRx += IX_USB_MBLK_LEN(epData->currentBuffer); if (IX_USB_MBLK_LEN(epData->currentBuffer)) { /* dispatch data - client is required to free buffer */ IX_USB_VERBOSE4_TRACE("USB: Build 1003: Callback on EP0, %d bytes\n", IX_USB_MBLK_LEN(epData->currentBuffer), 0, 0, 0, 0, 0); context->eventProcessor.receiveCallback(device, ENDPOINT_0, epData->currentBuffer); } else { IX_USB_VERBOSE4_TRACE("USB: Build 1003: Ignoring 0 bytes payload\n", 0, 0, 0, 0, 0, 0); IX_USB_MBLK_FREE(epData->currentBuffer); } /* reset transfer data */ epData->currentBuffer = NULL; epData->currentOffset = 0; epData->currentTransferSize = 0;}/** * @fn PRIVATE void ixUSBQueueDiscard(EPStatusData *epData) * * @brief Discard and free the data queue of an endpoint * * @param epData EPStatusData * (in) - structure identifying the endpoint * * @return none * * Frees the endpoint data queue (used only for Tx) and updates the * endpoint counters. * * @internal */PRIVATE voidixUSBQueueDiscard(EPStatusData *epData){ USBDataQueue *queue = &(epData->queue); UINT32 local_index;#ifdef IX_USB_HAS_CRITICAL_DATA_LOCKS UINT32 irqStatus; /* USBDevice *device = epData->device; */ irqStatus = IX_USB_LOCK;#endif /* IX_USB_HAS_CRITICAL_DATA_LOCKS */ for (local_index = 0 ; local_index < queue->len ; local_index++) { UINT32 offset = QUEUE_WRAP(queue->head + local_index); IX_USB_MBLK_FREE(queue->base[offset]); queue->base[offset] = NULL; } /* update counters - queues are actually used only for Tx */ epData->counters.DTx += epData->queue.len; COUNTERS(epData->device)->DTx += epData->queue.len; queue->head = 0; queue->len = 0;#ifdef IX_USB_HAS_CRITICAL_DATA_LOCKS IX_USB_UNLOCK(irqStatus);#endif /* IX_USB_HAS_CRITICAL_DATA_LOCKS */}/** * @fn PRIVATE void ixUSBQueueInit(EPStatusData *epData) * * @brief Initialize the data queue of an endpoint * * @param epData EPStatusData * (in) - structure identifying the endpoint * * @return none * * @internal */PRIVATE voidixUSBQueueInit(EPStatusData *epData){ epData->queue.head = 0; epData->queue.len = 0; ixOsalMemSet(epData->queue.base, 0, MAX_QUEUE_SIZE * sizeof (IX_USB_MBLK *));}/** * @fn PRIVATE BOOL ixUSBBufferEnqueue(EPStatusData *epData, IX_USB_MBLK *buf) * * @brief Add a buffer to an endpoint data queue * * @param epData EPStatusData * (in) - structure identifying the endpoint * @param buf IX_USB_MBLK * (in) - buffer to enqueue * * @return <b>TRUE</b> if the buffer was successfully queued and * <b>FALSE</b> otherwise (if the queue is full) * * @internal */PRIVATE BOOL ixUSBBufferEnqueue(EPStatusData *epData, IX_USB_MBLK *buf){ USBDataQueue *queue = &(epData->queue); BOOL result;#ifdef IX_USB_HAS_CRITICAL_DATA_LOCKS /* lock section */ /* USBDevice *device = epData->device; */ UINT32 irqStatus = IX_USB_LOCK;#endif /* IX_USB_HAS_CRITICAL_DATA_LOCKS */ if (queue->len < MAX_QUEUE_SIZE) { UINT32 tail = QUEUE_WRAP(queue->head + queue->len); queue->base[tail] = buf; queue->len++; result = TRUE; } else { result = FALSE; /* queue is full */ }#ifdef IX_USB_HAS_CRITICAL_DATA_LOCKS IX_USB_UNLOCK(irqStatus);#endif /* IX_USB_HAS_CRITICAL_DATA_LOCKS */ return result;}/** * @fn PRIVATE BOOL ixUSBBufferDequeue(EPStatusData *epData) * * @brief Moves the top buffer from the endpoint queue into the * current transaction slot * * @param epData EPStatusData * (in) - structure identifying the endpoint * * @return <b>TRUE</b> if the dequeueing was completed successfully and * <b>FALSE</b> otherwise (if the queue is empty) * * @internal */PRIVATE BOOL ixUSBBufferDequeue(EPStatusData *epData){ USBDataQueue *queue = &(epData->queue); UINT32 lock; lock = IX_USB_LOCK; /* NULL buffer pointers can exist in the queue if buffers are cancelled */ /* retry until a non-NULL buffer pointer is extracted or queue becomes empty */ while (TRUE) { if (queue->len > 0) { epData->currentBuffer = queue->base[queue->head]; /* remove entry from queue */ queue->base[queue->head] = NULL; queue->len--; queue->head = QUEUE_WRAP(queue->head + 1); if (epData->currentBuffer != NULL) { epData->currentOffset = 0; IX_USB_UNLOCK(lock); return TRUE; } } else { IX_USB_UNLOCK(lock); return FALSE; /* queue is empty */ } } IX_USB_UNLOCK(lock);}/** * @fn PRIVATE void ixUSBRequestSend(EPStatusData *epData) * * @brief Service send requests for USB_IN endpoints * * @param epData EPStatusData * (in) - structure identifying the endpoint * * @return none * * Fills the endpoint FIFO and triggers UDC send.<br> * If transactioning is enabled it also automatically sends * end-of-transfer short packets.<br> * Checks transaction timeouts if compiled with <b>IX_USB_HAS_TIMESTAMP_CHECKS</b>. * * @internal
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -