/** * This function perform the reset sequence to the given usbps interface by * configuring the appropriate control bits in the usbps specifc registers. * the usbps reset sequence involves the below steps * Disbale the interrupts * Clear the status registers * Apply the reset command and wait for reset complete status * Update the relevant control registers with reset values * @param BaseAddress of the interface * * @return N/A. * * @note None. * ******************************************************************************/ void XUsbPs_ResetHw(u32 BaseAddress) { u32 RegVal; u32 Timeout = 0; /* Host and device mode */ /* Disable the interrupts */ XUsbPs_WriteReg(BaseAddress,XUSBPS_IER_OFFSET,0x0); /* Clear the interuupt status */ RegVal = XUsbPs_ReadReg(BaseAddress,XUSBPS_ISR_OFFSET); XUsbPs_WriteReg(BaseAddress,XUSBPS_ISR_OFFSET,RegVal); /* Perform the reset operation using USB CMD register */ RegVal = XUsbPs_ReadReg(BaseAddress,XUSBPS_CMD_OFFSET); RegVal = RegVal | XUSBPS_CMD_RST_MASK; XUsbPs_WriteReg(BaseAddress,XUSBPS_CMD_OFFSET,RegVal); RegVal = XUsbPs_ReadReg(BaseAddress,XUSBPS_CMD_OFFSET); /* Wait till the reset operation returns success */ /* * FIX ME: right now no indication to the caller or user about * timeout overflow */ while ((RegVal & XUSBPS_CMD_RST_MASK) && (Timeout < XUSBPS_RESET_TIMEOUT)) { RegVal = XUsbPs_ReadReg(BaseAddress,XUSBPS_CMD_OFFSET); Timeout++; } /* Update periodic list base address register with reset value */ XUsbPs_WriteReg(BaseAddress,XUSBPS_LISTBASE_OFFSET,0x0); /* Update async/endpoint list base address register with reset value */ XUsbPs_WriteReg(BaseAddress,XUSBPS_ASYNCLISTADDR_OFFSET,0x0); }
/** * * This function performs device reset, device is stopped at the end. * * @param InstancePtr is a pointer to XUsbPs instance of the controller. * * @return None. * * @note None. * ******************************************************************************/ void XUsbPs_DeviceReset(XUsbPs *InstancePtr) { int Timeout; /* Clear all setup token semaphores by reading the * XUSBPS_EPSTAT_OFFSET register and writing its value back to * itself. */ XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, XUSBPS_EPSTAT_OFFSET, XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_EPSTAT_OFFSET)); /* Clear all the endpoint complete status bits by reading the * XUSBPS_EPCOMPL_OFFSET register and writings its value back * to itself. */ XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, XUSBPS_EPCOMPL_OFFSET, XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_EPCOMPL_OFFSET)); /* Cancel all endpoint prime status by waiting until all bits * in XUSBPS_EPPRIME_OFFSET are 0 and then writing 0xFFFFFFFF * to XUSBPS_EPFLUSH_OFFSET. * * Avoid hanging here by using a Timeout counter... */ Timeout = XUSBPS_TIMEOUT_COUNTER; while ((XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_EPPRIME_OFFSET) & XUSBPS_EP_ALL_MASK) && --Timeout) { /* NOP */ } XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, XUSBPS_EPFLUSH_OFFSET, 0xFFFFFFFF); XUsbPs_Stop(InstancePtr); /* Write to CR register for controller reset */ XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, XUSBPS_CMD_OFFSET, XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_CMD_OFFSET) | XUSBPS_CMD_RST_MASK); /* Wait for reset to finish, hardware clears the reset bit once done */ Timeout = 1000000; while((XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_CMD_OFFSET) & XUSBPS_CMD_RST_MASK) && --Timeout) { /* NOP */ } }
/** * * This function resets the USB device. All the configuration registers are * reset to their default values. The function waits until the reset operation * is complete or for a certain duration within which the reset operation is * expected to be completed. * * @param InstancePtr is a pointer to XUsbPs instance of the controller. * * @return * - XST_SUCCESS Reset operation completed successfully. * - XST_FAILURE Reset operation timed out. * * @note None. * ******************************************************************************/ int XUsbPs_Reset(XUsbPs *InstancePtr) { int Timeout; Xil_AssertNonvoid(InstancePtr != NULL); /* Write a 1 to the RESET bit. The RESET bit is cleared by HW once the * RESET is complete. * * We are going to wait for the RESET bit to clear before we return * from this function. Unfortunately we do not have timers available at * this point to determine when we should report a Timeout. * * However, by using a large number for the poll loop we can assume * that the polling operation will take longer than the expected time * the HW needs to RESET. If the poll loop expires we can assume a * Timeout. The drawback is that on a slow system (and even on a fast * system) this can lead to _very_ long Timeout periods. */ XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, XUSBPS_CMD_OFFSET, XUSBPS_CMD_RST_MASK); /* Wait for the RESET bit to be cleared by HW. */ Timeout = XUSBPS_TIMEOUT_COUNTER; while ((XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_CMD_OFFSET) & XUSBPS_CMD_RST_MASK) && --Timeout) { /* NOP */ } if (0 == Timeout) { return XST_FAILURE; } return XST_SUCCESS; }
/** * This function is the first-level interrupt handler for the USB core. All USB * interrupts will be handled here. Depending on the type of the interrupt, * second level interrupt handler may be called. Second level interrupt * handlers will be registered by the user using the: * XUsbPs_IntrSetHandler() * and/or * XUsbPs_EpSetHandler() * functions. * * * @param HandlerRef is a Reference passed to the interrupt register * function. In our case this will be a pointer to the XUsbPs * instance. * * @return None * * @note None * ******************************************************************************/ void XUsbPs_IntrHandler(void *HandlerRef) { XUsbPs *InstancePtr; u32 IrqSts; Xil_AssertVoid(HandlerRef != NULL); InstancePtr = (XUsbPs *) HandlerRef; /* Handle controller (non-endpoint) related interrupts. */ IrqSts = XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_ISR_OFFSET); /* Clear the interrupt status register. */ XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, XUSBPS_ISR_OFFSET, IrqSts); /* Nak interrupt, used to respond to host's IN request */ if(IrqSts & XUSBPS_IXR_NAK_MASK) { /* Ack the hardware */ XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, XUSBPS_EPNAKISR_OFFSET, XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_EPNAKISR_OFFSET)); } /*************************************************************** * * Handle general interrupts. Endpoint interrupts will be handler * later. * */ /* RESET interrupt.*/ if (IrqSts & XUSBPS_IXR_UR_MASK) { XUsbPs_IntrHandleReset(InstancePtr, IrqSts); return; } /* Check if we have a user handler that needs to be called. Note that * this is the handler for general interrupts. Endpoint interrupts will * be handled below. */ if ((IrqSts & InstancePtr->HandlerMask) && InstancePtr->HandlerFunc) { (InstancePtr->HandlerFunc)(InstancePtr->HandlerRef, IrqSts); } /*************************************************************** * * Handle Endpoint interrupts. * */ if (IrqSts & XUSBPS_IXR_UI_MASK) { u32 EpStat; u32 EpCompl; /* ENDPOINT 0 SETUP PACKET HANDLING * * Check if we got a setup packet on endpoint 0. Currently we * only check for setup packets on endpoint 0 as we would not * expect setup packets on any other endpoint (even though it * is possible to send setup packets on other endpoints). */ EpStat = XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_EPSTAT_OFFSET); if (EpStat & 0x0001) { /* Handle the setup packet */ XUsbPs_IntrHandleEp0Setup(InstancePtr); /* Re-Prime the endpoint. * Endpoint is de-primed if a setup packet comes in. */ XUsbPs_EpPrime(InstancePtr, 0, XUSBPS_EP_DIRECTION_OUT); } /* Check for RX and TX complete interrupts. */ EpCompl = XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_EPCOMPL_OFFSET); /* ACK the complete interrupts. */ XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, XUSBPS_EPCOMPL_OFFSET, EpCompl); /* Check OUT (RX) endpoints. */ if (EpCompl & XUSBPS_EP_OUT_MASK) { XUsbPs_IntrHandleRX(InstancePtr, EpCompl); } /* Check IN (TX) endpoints. */ if (EpCompl & XUSBPS_EP_IN_MASK) { XUsbPs_IntrHandleTX(InstancePtr, EpCompl); } } }
/** * This function handles a RESET interrupt. It will notify the interrupt * handler callback of the RESET condition. * * @param InstancePtr is pointer to the XUsbPs instance of the controller * @param IrqSts is the Interrupt status register content. * To be passed on to the user. * * @return None * * @Note None. * ******************************************************************************/ static void XUsbPs_IntrHandleReset(XUsbPs *InstancePtr, u32 IrqSts) { int Timeout; /* Clear all setup token semaphores by reading the * XUSBPS_EPSTAT_OFFSET register and writing its value back to * itself. */ XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, XUSBPS_EPSTAT_OFFSET, XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_EPSTAT_OFFSET)); /* Clear all the endpoint complete status bits by reading the * XUSBPS_EPCOMPL_OFFSET register and writings its value back * to itself. */ XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, XUSBPS_EPCOMPL_OFFSET, XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_EPCOMPL_OFFSET)); /* Cancel all endpoint prime status by waiting until all bits * in XUSBPS_EPPRIME_OFFSET are 0 and then writing 0xFFFFFFFF * to XUSBPS_EPFLUSH_OFFSET. * * Avoid hanging here by using a Timeout counter... */ Timeout = XUSBPS_TIMEOUT_COUNTER; while ((XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_EPPRIME_OFFSET) & XUSBPS_EP_ALL_MASK) && --Timeout) { /* NOP */ } XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, XUSBPS_EPFLUSH_OFFSET, 0xFFFFFFFF); /* Make sure that the reset bit in XUSBPS_PORTSCR1_OFFSET is * still set at this point. If the code gets to this point and * the reset bit has already been cleared we are in trouble and * hardware reset is necessary. */ if (!(XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_PORTSCR1_OFFSET) & XUSBPS_PORTSCR_PR_MASK)) { /* Send a notification to the user that a hardware * RESET is required. At this point we can only hope * that the user registered an interrupt handler and * will issue a hardware RESET. */ if (InstancePtr->HandlerFunc) { (InstancePtr->HandlerFunc)(InstancePtr->HandlerRef, IrqSts); } else { for (;;); } /* If we get here there is nothing more to do. The user * should have reset the core. */ return; } /* Check if we have a user handler that needs to be called. */ if (InstancePtr->HandlerFunc) { (InstancePtr->HandlerFunc)(InstancePtr->HandlerRef, IrqSts); } /* We are done. After RESET we don't proceed in the interrupt * handler. */ }
/** * This function extracts the Setup Data from a given endpoint. * * @param InstancePtr is a pointer to the XUsbPs instance of the * controller. * @param EpNum is the number of the endpoint to receive data from. * @param SetupDataPtr is a pointer to the setup data structure to be * filled. * * @return * - XST_SUCCESS: The operation completed successfully. * - XST_FAILURE: An error occured. * * @note None. ******************************************************************************/ int XUsbPs_EpGetSetupData(XUsbPs *InstancePtr, int EpNum, XUsbPs_SetupData *SetupDataPtr) { XUsbPs_EpOut *Ep; u32 Data[2]; u8 *p; int Timeout; Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(SetupDataPtr != NULL); Xil_AssertNonvoid(EpNum < InstancePtr->DeviceConfig.NumEndpoints); Ep = &InstancePtr->DeviceConfig.Ep[EpNum].Out; /* Get the data from the Queue Heads Setup buffer into local variables * so we can extract the setup data values. */ do { /* Arm the tripwire. The tripwire will tell us if a new setup * packet arrived (in which case the tripwire bit will be * cleared) while we were reading the buffer. If a new setup * packet arrived the buffer is corrupted and we continue * reading. */ XUsbPs_SetTripwire(InstancePtr); XUsbPs_dQHInvalidateCache(Ep->dQH); Data[0] = XUsbPs_ReaddQH(Ep->dQH, XUSBPS_dQHSUB0); Data[1] = XUsbPs_ReaddQH(Ep->dQH, XUSBPS_dQHSUB1); } while (FALSE == XUsbPs_TripwireIsSet(InstancePtr)); /* Clear the pending endpoint setup stat bit. */ XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, XUSBPS_EPSTAT_OFFSET, 1 << EpNum); /* Clear the Tripwire bit and continue. */ XUsbPs_ClrTripwire(InstancePtr); /* Data in the setup buffer is being converted by the core to big * endian format. We have to take care of proper byte swapping when * reading the setup data values. * * Need to check if there is a smarter way to do this and take the * processor/memory-controller endianess into account? */ p = (u8 *) Data; SetupDataPtr->bmRequestType = p[0]; SetupDataPtr->bRequest = p[1]; SetupDataPtr->wValue = (p[3] << 8) | p[2]; SetupDataPtr->wIndex = (p[5] << 8) | p[4]; SetupDataPtr->wLength = (p[7] << 8) | p[6]; /* Before we leave we need to make sure that the endpoint setup bit has * cleared. It needs to be 0 before the endpoint can be re-primed. * * Note: According to the documentation this endpoint setup bit should * clear within 1-2us after it has been written above. This means that * we should never catch it being 1 here. However, we still need to * poll it to make sure. Just in case, we use a counter 'Timeout' so we * won't hang here if the bit is stuck for some reason. */ Timeout = XUSBPS_TIMEOUT_COUNTER; while ((XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_EPSTAT_OFFSET) & (1 << EpNum)) && --Timeout) { /* NOP */ } if (0 == Timeout) { return XST_FAILURE; } return XST_SUCCESS; }
/** * This function sends a given data buffer. * * @param InstancePtr is a pointer to XUsbPs instance of the controller. * @param EpNum is the number of the endpoint to receive data from. * @param BufferPtr is a pointer to the buffer to send. * @param BufferLen is the Buffer length. * * @return * - XST_SUCCESS: The operation completed successfully. * - XST_FAILURE: An error occured. * - XST_USB_BUF_TOO_BIG: Provided buffer is too big (>16kB). * - XST_USB_NO_DESC_AVAILABLE: No TX descriptor is available. * ******************************************************************************/ int XUsbPs_EpBufferSend(XUsbPs *InstancePtr, u8 EpNum, const u8 *BufferPtr, u32 BufferLen) { int Status; u32 Token; XUsbPs_EpIn *Ep; XUsbPs_dTD *DescPtr; u32 Length; u32 PipeEmpty = 1; u32 Mask = 0x00010000; u32 BitMask = Mask << EpNum; u32 RegValue; u32 Temp; Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(EpNum < InstancePtr->DeviceConfig.NumEndpoints); /* Locate the next available buffer in the ring. A buffer is available * if its descriptor is not active. */ Ep = &InstancePtr->DeviceConfig.Ep[EpNum].In; Xil_DCacheFlushRange((unsigned int)BufferPtr, BufferLen); if(Ep->dTDTail != Ep->dTDHead) { PipeEmpty = 0; } XUsbPs_dTDInvalidateCache(Ep->dTDHead); /* Tell the caller if we do not have any descriptors available. */ if (XUsbPs_dTDIsActive(Ep->dTDHead)) { return XST_USB_NO_DESC_AVAILABLE; } /* Remember the current head. */ DescPtr = Ep->dTDHead; do { Length = (BufferLen > XUSBPS_dTD_BUF_MAX_SIZE) ? XUSBPS_dTD_BUF_MAX_SIZE : BufferLen; /* Attach the provided buffer to the current descriptor.*/ Status = XUsbPs_dTDAttachBuffer(Ep->dTDHead, BufferPtr, Length); if (XST_SUCCESS != Status) { return XST_FAILURE; } BufferLen -= Length; BufferPtr += Length; XUsbPs_dTDSetActive(Ep->dTDHead); if(BufferLen == 0) XUsbPs_dTDSetIOC(Ep->dTDHead); XUsbPs_dTDClrTerminate(Ep->dTDHead); XUsbPs_dTDFlushCache(Ep->dTDHead); /* Advance the head descriptor pointer to the next descriptor. */ Ep->dTDHead = XUsbPs_dTDGetNLP(Ep->dTDHead); /* Terminate the next descriptor and flush the cache.*/ XUsbPs_dTDInvalidateCache(Ep->dTDHead); /* Tell the caller if we do not have any descriptors available. */ if (XUsbPs_dTDIsActive(Ep->dTDHead)) { return XST_USB_NO_DESC_AVAILABLE; } } while(BufferLen); XUsbPs_dTDSetTerminate(Ep->dTDHead); XUsbPs_dTDFlushCache(Ep->dTDHead); if(!PipeEmpty) { /* Read the endpoint prime register. */ RegValue = XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_EPPRIME_OFFSET); if(RegValue & BitMask) { return XST_SUCCESS; } do { RegValue = XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_CMD_OFFSET); XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, XUSBPS_CMD_OFFSET, RegValue | XUSBPS_CMD_ATDTW_MASK); Temp = XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_EPRDY_OFFSET) & BitMask; } while(!(XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_CMD_OFFSET) & XUSBPS_CMD_ATDTW_MASK)); RegValue = XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_CMD_OFFSET); XUsbPs_WriteReg(InstancePtr->Config.BaseAddress, XUSBPS_CMD_OFFSET, RegValue & ~XUSBPS_CMD_ATDTW_MASK); if(Temp) { return XST_SUCCESS; } } /* Check, if the DMA engine is still running. If it is running, we do * not clear Queue Head fields. * * Same cache rule as for the Transfer Descriptor applies for the Queue * Head. */ XUsbPs_dQHInvalidateCache(Ep->dQH); /* Add the dTD to the dQH */ XUsbPs_WritedQH(Ep->dQH, XUSBPS_dQHdTDNLP, DescPtr); Token = XUsbPs_ReaddQH(Ep->dQH, XUSBPS_dQHdTDTOKEN); Token &= ~(XUSBPS_dTDTOKEN_ACTIVE_MASK | XUSBPS_dTDTOKEN_HALT_MASK); XUsbPs_WritedQH(Ep->dQH, XUSBPS_dQHdTDTOKEN, Token); XUsbPs_dQHFlushCache(Ep->dQH); Status = XUsbPs_EpPrime(InstancePtr, EpNum, XUSBPS_EP_DIRECTION_IN); return Status; }
/** * This function handles a standard device request. * * @param InstancePtr is a pointer to XUsbPs instance of the controller. * @param SetupData is a pointer to the data structure containing the * setup request. * * @return None. * * @note None. * ******************************************************************************/ static void XUsbPs_StdDevReq(XUsbPs *InstancePtr, XUsbPs_SetupData *SetupData) { int Status; int Error = 0; XUsbPs_Local *UsbLocalPtr; int ReplyLen; #ifdef __ICCARM__ #pragma data_alignment = 32 static u8 Reply[XUSBPS_REQ_REPLY_LEN]; #pragma data_alignment = 4 #else static u8 Reply[XUSBPS_REQ_REPLY_LEN] ALIGNMENT_CACHELINE; #endif /* Check that the requested reply length is not bigger than our reply * buffer. This should never happen... */ if (SetupData->wLength > XUSBPS_REQ_REPLY_LEN) { return; } UsbLocalPtr = (XUsbPs_Local *) InstancePtr->UserDataPtr; #ifdef CH9_DEBUG printf("std dev req %d\n", SetupData->bRequest); #endif switch (SetupData->bRequest) { case XUSBPS_REQ_GET_STATUS: switch(SetupData->bmRequestType & XUSBPS_STATUS_MASK) { case XUSBPS_STATUS_DEVICE: /* It seems we do not have to worry about zeroing out the rest * of the reply buffer even though we are only using the first * two bytes. */ *((u16 *) &Reply[0]) = 0x0100; /* Self powered */ break; case XUSBPS_STATUS_INTERFACE: *((u16 *) &Reply[0]) = 0x0; break; case XUSBPS_STATUS_ENDPOINT: { u32 Status; int EpNum = SetupData->wIndex; Status = XUsbPs_ReadReg(InstancePtr->Config.BaseAddress, XUSBPS_EPCRn_OFFSET(EpNum & 0xF)); if(EpNum & 0x80) { /* In EP */ if(Status & XUSBPS_EPCR_TXS_MASK) { *((u16 *) &Reply[0]) = 0x0100; }else { *((u16 *) &Reply[0]) = 0x0000; } } else { /* Out EP */ if(Status & XUSBPS_EPCR_RXS_MASK) { *((u16 *) &Reply[0]) = 0x0100; }else { *((u16 *) &Reply[0]) = 0x0000; } } break; } default: ; #ifdef CH9_DEBUG printf("unknown request for status %x\n", SetupData->bmRequestType); #endif } XUsbPs_EpBufferSend(InstancePtr, 0, Reply, SetupData->wLength); break; case XUSBPS_REQ_SET_ADDRESS: /* With bit 24 set the address value is held in a shadow * register until the status phase is acked. At which point it * address value is written into the address register. */ XUsbPs_SetDeviceAddress(InstancePtr, SetupData->wValue); #ifdef CH9_DEBUG printf("Set address %d\n", SetupData->wValue); #endif /* There is no data phase so ack the transaction by sending a * zero length packet. */ XUsbPs_EpBufferSend(InstancePtr, 0, NULL, 0); break; case XUSBPS_REQ_GET_INTERFACE: #ifdef CH9_DEBUG printf("Get interface %d/%d/%d\n", SetupData->wIndex, SetupData->wLength, InstancePtr->CurrentAltSetting); #endif Response = (u8)InstancePtr->CurrentAltSetting; /* Ack the host */ XUsbPs_EpBufferSend(InstancePtr, 0, &Response, 1); break; case XUSBPS_REQ_GET_DESCRIPTOR: #ifdef CH9_DEBUG printf("Get desc %x/%d\n", (SetupData->wValue >> 8) & 0xff, SetupData->wLength); #endif /* Get descriptor type. */ switch ((SetupData->wValue >> 8) & 0xff) { case XUSBPS_TYPE_DEVICE_DESC: case XUSBPS_TYPE_DEVICE_QUALIFIER: /* Set up the reply buffer with the device descriptor * data. */ ReplyLen = XUsbPs_Ch9SetupDevDescReply( Reply, XUSBPS_REQ_REPLY_LEN); ReplyLen = ReplyLen > SetupData->wLength ? SetupData->wLength : ReplyLen; if(((SetupData->wValue >> 8) & 0xff) == XUSBPS_TYPE_DEVICE_QUALIFIER) { Reply[0] = (u8)ReplyLen; Reply[1] = (u8)0x6; Reply[2] = (u8)0x0; Reply[3] = (u8)0x2; Reply[4] = (u8)0xFF; Reply[5] = (u8)0x00; Reply[6] = (u8)0x0; Reply[7] = (u8)0x10; Reply[8] = (u8)0; Reply[9] = (u8)0x0; } Status = XUsbPs_EpBufferSend(InstancePtr, 0, Reply, ReplyLen); if (XST_SUCCESS != Status) { /* Failure case needs to be handled */ for (;;); } break; case XUSBPS_TYPE_CONFIG_DESC: /* Set up the reply buffer with the configuration * descriptor data. */ ReplyLen = XUsbPs_Ch9SetupCfgDescReply( Reply, XUSBPS_REQ_REPLY_LEN); #ifdef CH9_DEBUG printf("get config %d/%d\n", ReplyLen, SetupData->wLength); #endif ReplyLen = ReplyLen > SetupData->wLength ? SetupData->wLength : ReplyLen; Status = XUsbPs_EpBufferSend(InstancePtr, 0, Reply, ReplyLen); if (XST_SUCCESS != Status) { /* Failure case needs to be handled */ for (;;); } break; case XUSBPS_TYPE_STRING_DESC: /* Set up the reply buffer with the string descriptor * data. */ ReplyLen = XUsbPs_Ch9SetupStrDescReply( Reply, XUSBPS_REQ_REPLY_LEN, SetupData->wValue & 0xFF); ReplyLen = ReplyLen > SetupData->wLength ? SetupData->wLength : ReplyLen; Status = XUsbPs_EpBufferSend(InstancePtr, 0, Reply, ReplyLen); if (XST_SUCCESS != Status) { /* Failure case needs to be handled */ for (;;); } break; #ifdef MOUSE_SIMULATION case XUSBPS_TYPE_HID_DESC: /* Set up the reply buffer with the HID descriptor * data. */ ReplyLen = XUsbPs_Ch9SetupHidDescReply( Reply, XUSBPS_REQ_REPLY_LEN); ReplyLen = ReplyLen > SetupData->wLength ? SetupData->wLength : ReplyLen; Status = XUsbPs_EpBufferSend(InstancePtr, 0, Reply, ReplyLen); if (XST_SUCCESS != Status) { /* Failure case needs to be handled */ for (;;); } break; case XUSBPS_TYPE_REPORT_DESC: /* Set up the reply buffer with the report descriptor * data. */ ReplyLen = XUsbPs_Ch9SetupReportDescReply( Reply, XUSBPS_REQ_REPLY_LEN); #ifdef CH9_DEBUG printf("report desc len %d\n", ReplyLen); #endif ReplyLen = ReplyLen > SetupData->wLength ? SetupData->wLength : ReplyLen; Status = XUsbPs_EpBufferSend(InstancePtr, 0, Reply, ReplyLen); if (XST_SUCCESS != Status) { /* Failure case needs to be handled */ for (;;); } break; #endif /* MOUSE_SIMULATION */ default: Error = 1; break; } break; case XUSBPS_REQ_SET_CONFIGURATION: /* * Only allow configuration index 1 as this is the only one we * have. */ if ((SetupData->wValue & 0xff) != 1) { Error = 1; break; } UsbLocalPtr->CurrentConfig = SetupData->wValue & 0xff; /* Call the application specific configuration function to * apply the configuration with the given configuration index. */ XUsbPs_SetConfiguration(InstancePtr, UsbLocalPtr->CurrentConfig); /* There is no data phase so ack the transaction by sending a * zero length packet. */ XUsbPs_EpBufferSend(InstancePtr, 0, NULL, 0); break; case XUSBPS_REQ_GET_CONFIGURATION: Response = (u8)InstancePtr->CurrentAltSetting; XUsbPs_EpBufferSend(InstancePtr, 0, &Response, 1); break; case XUSBPS_REQ_CLEAR_FEATURE: switch(SetupData->bmRequestType & XUSBPS_STATUS_MASK) { case XUSBPS_STATUS_ENDPOINT: if(SetupData->wValue == XUSBPS_ENDPOINT_HALT) { int EpNum = SetupData->wIndex; if(EpNum & 0x80) { /* In ep */ XUsbPs_ClrBits(InstancePtr, XUSBPS_EPCRn_OFFSET(EpNum & 0xF), XUSBPS_EPCR_TXS_MASK); }else { /* Out ep */ XUsbPs_ClrBits(InstancePtr, XUSBPS_EPCRn_OFFSET(EpNum), XUSBPS_EPCR_RXS_MASK); } } /* Ack the host ? */ XUsbPs_EpBufferSend(InstancePtr, 0, NULL, 0); break; default: Error = 1; break; } break; case XUSBPS_REQ_SET_FEATURE: switch(SetupData->bmRequestType & XUSBPS_STATUS_MASK) { case XUSBPS_STATUS_ENDPOINT: if(SetupData->wValue == XUSBPS_ENDPOINT_HALT) { int EpNum = SetupData->wIndex; if(EpNum & 0x80) { /* In ep */ XUsbPs_SetBits(InstancePtr, XUSBPS_EPCRn_OFFSET(EpNum & 0xF), XUSBPS_EPCR_TXS_MASK); }else { /* Out ep */ XUsbPs_SetBits(InstancePtr, XUSBPS_EPCRn_OFFSET(EpNum), XUSBPS_EPCR_RXS_MASK); } } /* Ack the host ? */ XUsbPs_EpBufferSend(InstancePtr, 0, NULL, 0); break; case XUSBPS_STATUS_DEVICE: if (SetupData->wValue == XUSBPS_TEST_MODE) { int TestSel = (SetupData->wIndex >> 8) & 0xFF; /* Ack the host, the transition must happen after status stage and < 3ms */ XUsbPs_EpBufferSend(InstancePtr, 0, NULL, 0); usleep(1000); switch (TestSel) { case XUSBPS_TEST_J: case XUSBPS_TEST_K: case XUSBPS_TEST_SE0_NAK: case XUSBPS_TEST_PACKET: case XUSBPS_TEST_FORCE_ENABLE: XUsbPs_SetBits(InstancePtr, \ XUSBPS_PORTSCR1_OFFSET, \ TestSel << 16); break; default: /* Unsupported test selector */ break; } break; } default: Error = 1; break; } break; /* For set interface, check the alt setting host wants */ case XUSBPS_REQ_SET_INTERFACE: #ifdef CH9_DEBUG printf("set interface %d/%d\n", SetupData->wValue, SetupData->wIndex); #endif /* Not supported */ /* XUsbPs_SetInterface(InstancePtr, SetupData->wValue, SetupData->wIndex); */ /* Ack the host after device finishes the operation */ Error = XUsbPs_EpBufferSend(InstancePtr, 0, NULL, 0); if(Error) { #ifdef CH9_DEBUG printf("EpBufferSend failed %d\n", Error); #endif } break; default: Error = 1; break; }