Exemple #1
0
/**
* 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);		
	
}
Exemple #2
0
/**
*
* 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 */
	}
}
Exemple #3
0
/**
*
* 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;
}
Exemple #8
0
/**
* 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;
	}