
Added initial support Xilinx Embedded Software. Signed-off-by: Jagannadha Sutradharudu Teki <jaganna@xilinx.com>
1261 lines
32 KiB
C
Executable file
1261 lines
32 KiB
C
Executable file
/******************************************************************************
|
|
*
|
|
* Copyright (C) 2006 Vreelin Engineering, Inc. All Rights Reserved.
|
|
* (c) Copyright 2007-2013 Xilinx, Inc. All rights reserved.
|
|
*
|
|
* This file contains confidential and proprietary information of Xilinx, Inc.
|
|
* and is protected under U.S. and international copyright and other
|
|
* intellectual property laws.
|
|
*
|
|
* DISCLAIMER
|
|
* This disclaimer is not a license and does not grant any rights to the
|
|
* materials distributed herewith. Except as otherwise provided in a valid
|
|
* license issued to you by Xilinx, and to the maximum extent permitted by
|
|
* applicable law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND WITH ALL
|
|
* FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS,
|
|
* IMPLIED, OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
|
|
* MERCHANTABILITY, NON-INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE;
|
|
* and (2) Xilinx shall not be liable (whether in contract or tort, including
|
|
* negligence, or under any other theory of liability) for any loss or damage
|
|
* of any kind or nature related to, arising under or in connection with these
|
|
* materials, including for any direct, or any indirect, special, incidental,
|
|
* or consequential loss or damage (including loss of data, profits, goodwill,
|
|
* or any type of loss or damage suffered as a result of any action brought by
|
|
* a third party) even if such damage or loss was reasonably foreseeable or
|
|
* Xilinx had been advised of the possibility of the same.
|
|
*
|
|
* CRITICAL APPLICATIONS
|
|
* Xilinx products are not designed or intended to be fail-safe, or for use in
|
|
* any application requiring fail-safe performance, such as life-support or
|
|
* safety devices or systems, Class III medical devices, nuclear facilities,
|
|
* applications related to the deployment of airbags, or any other applications
|
|
* that could lead to death, personal injury, or severe property or
|
|
* environmental damage (individually and collectively, "Critical
|
|
* Applications"). Customer assumes the sole risk and liability of any use of
|
|
* Xilinx products in Critical Applications, subject only to applicable laws
|
|
* and regulations governing limitations on product liability.
|
|
*
|
|
* THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS PART OF THIS FILE
|
|
* AT ALL TIMES.
|
|
*
|
|
******************************************************************************/
|
|
/*****************************************************************************/
|
|
/**
|
|
* @file xusb_cp9.c
|
|
*
|
|
* This file contains the USB Chapter 9 related functions.
|
|
*
|
|
* @note None.
|
|
*
|
|
* <pre>
|
|
* MODIFICATION HISTORY:
|
|
*
|
|
* Ver Who Date Changes
|
|
* ----- ---- -----------------------------------------------------------------
|
|
* 1.00a hvm 2/22/07 First release
|
|
* 1.01a hvm 5/30/07 Moved the USB class specific command processing to
|
|
* application files.
|
|
* 3.00a hvm 11/18/09 Updated to use HAL processor APIs.
|
|
* XUsb_mReadReg is renamed to XUsb_ReadReg and
|
|
* XUsb_mWriteReg is renamed to XUsb_WriteReg.
|
|
* 3.02a hvm 08/16/10 Updated with the little endian support changes.
|
|
* 4.00a hvm 12/20/10 Updated SetInterface function with microphone case
|
|
* support.
|
|
*
|
|
* </pre>
|
|
*****************************************************************************/
|
|
/***************************** Include Files *********************************/
|
|
|
|
#include "xusb_cp9.h"
|
|
#include <xparameters.h>
|
|
|
|
#undef XUSB_CH9_DEBUG
|
|
|
|
#ifdef XUSB_CH9_DEBUG
|
|
#include "stdio.h"
|
|
#endif
|
|
|
|
/************************** Constant Definitions ******************************/
|
|
|
|
/************************** Variable Definitions ******************************/
|
|
|
|
IntChar UsbMemData; /* Dual Port memory */
|
|
|
|
/*
|
|
* Instance of the Chapter 9 command buffer.
|
|
*/
|
|
USB_CMD_BUF Ch9_CmdBuf;
|
|
|
|
/*
|
|
* Maximum control pkt size.
|
|
*/
|
|
u16 MaxControlSize = 8;
|
|
|
|
/*
|
|
* Standard USB structure instances.
|
|
*/
|
|
extern USB_STD_DEV_DESC DeviceDescriptor;
|
|
extern USB_STD_QUAL_DESC QualifierDescriptor;
|
|
extern FPGA1_CONFIGURATION HsUsbConfig;
|
|
extern FPGA1_CONFIGURATION FsUsbConfig;
|
|
extern USB_STD_STRING_DESC LangId;
|
|
extern USB_STD_STRING_MAN_DESC Manufacturer;
|
|
extern USB_STD_STRING_PS_DESC ProductString;
|
|
extern USB_STD_STRING_SN_DESC SerialNumber;
|
|
|
|
#ifdef HID_DEVICES
|
|
extern USB_STD_HID_DESC HidDescriptor;
|
|
#endif
|
|
|
|
#ifdef USB_KEYBOARD
|
|
const unsigned char ReportDesc[0x2b] = // Report descriptor
|
|
{
|
|
0x05,0x01, /* Usage Page (generic desktop) */
|
|
0x09,0x06, /* Usage (keyboard) */
|
|
0xA1,0x01, /* Collection */
|
|
0x05,0x07, /* Usage Page 7 (keyboard/keypad) */
|
|
0x19,0xE0, /* Usage Minimum = 224 */
|
|
0x29,0xE7, /* Usage Maximum = 231 */
|
|
0x15,0x00, /* Logical Minimum = 0 */
|
|
0x25,0x01, /* Logical Maximum = 1 */
|
|
0x75,0x01, /* Report Size = 1 */
|
|
0x95,0x08, /* Report Count = 8 */
|
|
0x81,0x02, /* Input(Data,Variable,Absolute) */
|
|
0x95,0x01, /* Report Count = 1 */
|
|
0x75,0x08, /* Report Size = 8 */
|
|
0x81,0x01, /* Input(Constant) */
|
|
0x19,0x00, /* Usage Minimum = 0 */
|
|
0x29,0x65, /* Usage Maximum = 101 */
|
|
0x15,0x00, /* Logical Minimum = 0 */
|
|
0x25,0x65, /* Logical Maximum = 101 */
|
|
0x75,0x08, /* Report Size = 8 */
|
|
0x95,0x01, /* Report Count = 1 */
|
|
0x81,0x00, /* Input(Data,Variable,Array) */
|
|
0xC0}; /* End Collection */
|
|
#endif
|
|
|
|
#ifdef USB_MOUSE
|
|
const unsigned char ReportDesc[0x34] = // Report descriptor
|
|
{
|
|
0x05,0x01, /* Usage Page (generic desktop) */
|
|
0x09,0x02, /* Usage (mouse) */
|
|
0xA1,0x01, /* Collection */
|
|
0x09,0x01, /* Usage Page 7 () */
|
|
0xA1,0x00, /* Usage Minimum = 224 */
|
|
0x05,0x09, /* Usage Maximum = 231 */
|
|
0x19,0x01, /* Logical Minimum = 0 */
|
|
0x29,0x03, /* Logical Maximum = 1 */
|
|
0x15,0x00, /* Report Size = 1 */
|
|
0x25,0x01, /* Report Count = 8 */
|
|
0x95,0x03, /* Input(Data,Variable,Absolute) */
|
|
0x75,0x01, /* Report Count = 1 */
|
|
0x81,0x02, /* Report Size = 8 */
|
|
0x95,0x01, /* Input(Constant) */
|
|
0x75,0x05, /* Usage Minimum = 0 */
|
|
0x81,0x01, /* Usage Maximum = 101 */
|
|
0x05,0x01, /* Logical Minimum = 0 */
|
|
0x09,0x30, /* Logical Maximum = 101 */
|
|
0x09,0x31, /* Report Size = 8 */
|
|
0x09,0x38,
|
|
0x15,0x81, /* Report Count = 1 */
|
|
0x25,0x7F, /* Input(Data,Variable,Array) */
|
|
0x75,0x08,
|
|
0x95,0x03,
|
|
0x81,0x06,
|
|
0xC0,
|
|
0xC0}; /* End Collection */
|
|
#endif
|
|
|
|
/************************** Function Prototypes *******************************/
|
|
|
|
/******************************************************************************/
|
|
/**
|
|
* This routine is called when an OUT transaction for Endpoint Zero is received.
|
|
*
|
|
* @param InstancePtr is a pointer to the XUsb instance of the controller.
|
|
*
|
|
* @return None.
|
|
*
|
|
* @note None.
|
|
*
|
|
******************************************************************************/
|
|
void EP0ProcessOutToken(XUsb * InstancePtr)
|
|
{
|
|
u8 Count;
|
|
u8 *RamBase;
|
|
u16 Index;
|
|
|
|
switch (Ch9_CmdBuf.SetupSeqRX) {
|
|
case STATUS_PHASE:
|
|
/*
|
|
* This resets both state machines for the next
|
|
* Setup packet.
|
|
*/
|
|
Ch9_CmdBuf.SetupSeqRX = SETUP_PHASE;
|
|
Ch9_CmdBuf.SetupSeqTX = SETUP_PHASE;
|
|
break;
|
|
|
|
case DATA_PHASE:
|
|
|
|
Count = XUsb_ReadReg(InstancePtr->Config.BaseAddress,
|
|
XUSB_EP_BUF0COUNT_OFFSET);
|
|
/*
|
|
* Copy the data to be received from the DPRAM.
|
|
*/
|
|
RamBase = (u8 *) (InstancePtr->Config.BaseAddress +
|
|
((InstancePtr->DeviceConfig.Ep[0].
|
|
RamBase) << 2));
|
|
|
|
for (Index = 0; Index < Count; Index++) {
|
|
|
|
*Ch9_CmdBuf.ContReadPtr++ = *RamBase++;
|
|
}
|
|
|
|
Ch9_CmdBuf.ContReadCount += Count;
|
|
|
|
if (Ch9_CmdBuf.Word3.wLength == Ch9_CmdBuf.ContReadCount) {
|
|
Ch9_CmdBuf.SetupSeqRX = STATUS_PHASE;
|
|
ExecuteCommand(InstancePtr);
|
|
} else {
|
|
/*
|
|
* Set the Tx packet size and the Tx enable bit.
|
|
*/
|
|
XUsb_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XUSB_EP_BUF0COUNT_OFFSET, Count);
|
|
|
|
XUsb_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XUSB_BUFFREADY_OFFSET, 1);
|
|
|
|
InstancePtr->DeviceConfig.Ep[0].Buffer0Ready = 1;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/**
|
|
* This routine is called when IN transaction for Endpoint Zero is received.
|
|
*
|
|
* @param InstancePtr is a pointer to the XUsb instance of the controller.
|
|
*
|
|
* @return None.
|
|
*
|
|
* @note None.
|
|
*
|
|
******************************************************************************/
|
|
void EP0ProcessInToken(XUsb * InstancePtr)
|
|
{
|
|
u32 EpCfgReg;
|
|
|
|
switch (Ch9_CmdBuf.SetupSeqTX) {
|
|
case STATUS_PHASE:
|
|
if (Ch9_CmdBuf.Byte1.bRequest == SET_ADDRESS) {
|
|
/*
|
|
* Set the address of the device.
|
|
*/
|
|
XUsb_SetDeviceAddress(InstancePtr,
|
|
Ch9_CmdBuf.Word1.Byte23.
|
|
bDescriptorIndex);
|
|
}
|
|
else if (Ch9_CmdBuf.Byte1.bRequest == SET_FEATURE) {
|
|
if (Ch9_CmdBuf.Byte0.bmRequestType ==
|
|
STANDARD_OUT_DEVICE) {
|
|
#ifdef __LITTLE_ENDIAN__
|
|
Ch9_CmdBuf.Word1.wValue =
|
|
((u16)(Ch9_CmdBuf.Word1.Byte23.bDescriptorIndex) |
|
|
(u16)(Ch9_CmdBuf.Word1.Byte23.bDescriptorType << 8));
|
|
#endif
|
|
|
|
if (Ch9_CmdBuf.Word1.wValue == TEST_MODE) {
|
|
XUsb_SetTestMode(InstancePtr, TEST_J,
|
|
NULL);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case DATA_PHASE:
|
|
if (Ch9_CmdBuf.ContWriteCount == 0) {
|
|
/*
|
|
* We're done with data transfer, next
|
|
* will be zero length OUT with data toggle of
|
|
* 1. Setup data_toggle.
|
|
*/
|
|
EpCfgReg = XUsb_ReadReg(InstancePtr->Config.
|
|
BaseAddress,
|
|
InstancePtr->
|
|
EndPointOffset[0]);
|
|
EpCfgReg |= XUSB_EP_CFG_DATA_TOGGLE_MASK;
|
|
XUsb_WriteReg(InstancePtr->Config.BaseAddress,
|
|
InstancePtr->EndPointOffset[0],
|
|
EpCfgReg);
|
|
XUsb_WriteReg(InstancePtr->Config.BaseAddress,
|
|
(InstancePtr->EndPointOffset[0] +
|
|
XUSB_EP_BUF0COUNT_OFFSET), 0);
|
|
XUsb_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XUSB_BUFFREADY_OFFSET, 1);
|
|
InstancePtr->DeviceConfig.Ep[0].Buffer0Ready = 1;
|
|
|
|
Ch9_CmdBuf.SetupSeqTX = STATUS_PHASE;
|
|
|
|
}
|
|
else {
|
|
LoadEP0(InstancePtr);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/**
|
|
* This routine is called when a chapter 9 command is received.
|
|
*
|
|
* @param InstancePtr is a pointer to the XUsb instance of the controller.
|
|
*
|
|
* @return The setup request value to be processed by the upper layer.
|
|
*
|
|
* @note None.
|
|
*
|
|
******************************************************************************/
|
|
int Chapter9(XUsb * InstancePtr)
|
|
{
|
|
volatile unsigned int *RamBase;
|
|
|
|
/*
|
|
* Load up the chapter 9 command buffer.
|
|
*/
|
|
RamBase = (unsigned int *) (InstancePtr->Config.BaseAddress +
|
|
XUSB_SETUP_PKT_ADDR_OFFSET);
|
|
/*
|
|
* Get the first 4 bytes of the setup packet.
|
|
*/
|
|
UsbMemData.Word = *RamBase;
|
|
Ch9_CmdBuf.Byte0.bmRequestType = UsbMemData.Byte.Zero;
|
|
Ch9_CmdBuf.Byte1.bRequest = UsbMemData.Byte.One;
|
|
Ch9_CmdBuf.Word1.Byte23.bDescriptorIndex = UsbMemData.Byte.Two;
|
|
Ch9_CmdBuf.Word1.Byte23.bDescriptorType = UsbMemData.Byte.Three;
|
|
|
|
/*
|
|
* Get the last 4 bytes of the setup packet.
|
|
*/
|
|
RamBase += 1;
|
|
UsbMemData.Word = *RamBase;
|
|
|
|
/*
|
|
* Byte swapping for next 4 bytes for BE machines is defined in
|
|
* the different layout of BECB verses LECB.
|
|
*/
|
|
#ifdef __LITTLE_ENDIAN__
|
|
Ch9_CmdBuf.Word2.Byte45.Byteh = UsbMemData.Byte.Zero;
|
|
Ch9_CmdBuf.Word2.Byte45.Bytel = UsbMemData.Byte.One;
|
|
Ch9_CmdBuf.Word3.Byte67.Byteh = UsbMemData.Byte.Two;
|
|
Ch9_CmdBuf.Word3.Byte67.Bytel = UsbMemData.Byte.Three;
|
|
#else
|
|
Ch9_CmdBuf.Word2.Byte45.Bytel = UsbMemData.Byte.Zero;
|
|
Ch9_CmdBuf.Word2.Byte45.Byteh = UsbMemData.Byte.One;
|
|
Ch9_CmdBuf.Word3.Byte67.Bytel = UsbMemData.Byte.Two;
|
|
Ch9_CmdBuf.Word3.Byte67.Byteh = UsbMemData.Byte.Three;
|
|
#endif
|
|
/*
|
|
* Restore ReadPtr to data buffer.
|
|
*/
|
|
Ch9_CmdBuf.ContReadPtr = &Ch9_CmdBuf.ContReadDataBuffer[0];
|
|
|
|
if (Ch9_CmdBuf.Byte0.bmRequestType & DIR_DEVICE_TO_HOST) {
|
|
/*
|
|
* Execute the get command.
|
|
*/
|
|
Ch9_CmdBuf.SetupSeqRX = STATUS_PHASE;
|
|
Ch9_CmdBuf.SetupSeqTX = DATA_PHASE;
|
|
return (ExecuteCommand(InstancePtr));
|
|
}
|
|
else {
|
|
/*
|
|
* Execute the put command.
|
|
*/
|
|
Ch9_CmdBuf.SetupSeqRX = DATA_PHASE;
|
|
Ch9_CmdBuf.SetupSeqTX = STATUS_PHASE;
|
|
if (Ch9_CmdBuf.Word3.wLength == 0) {
|
|
return (ExecuteCommand(InstancePtr));
|
|
}
|
|
}
|
|
/*
|
|
* Control should never reach here
|
|
*/
|
|
return XST_FAILURE;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/**
|
|
* This function executes the chapter 9 command processing
|
|
*
|
|
* @param InstancePtr is a pointer to the XUsb instance of the controller.
|
|
*
|
|
* @return The request value to be processed by the upper layer if the
|
|
* request is not handled.
|
|
* XST_SUCCESS if the request is successfully processed.
|
|
*
|
|
* @note None.
|
|
*
|
|
******************************************************************************/
|
|
int ExecuteCommand(XUsb * InstancePtr)
|
|
{
|
|
|
|
if ((Ch9_CmdBuf.Byte0.bmRequestType & TYPE_MASK) == TYPE_STANDARD) {
|
|
/*
|
|
* Process the chapter 9 command.
|
|
*/
|
|
switch (Ch9_CmdBuf.Byte1.bRequest) {
|
|
case GET_STATUS:
|
|
#ifdef XUSB_CH9_DEBUG
|
|
xil_printf("Get Status \r\n");
|
|
#endif
|
|
GetStatus(InstancePtr);
|
|
break;
|
|
|
|
case CLEAR_FEATURE:
|
|
#ifdef XUSB_CH9_DEBUG
|
|
xil_printf("Clear Feature \r\n");
|
|
#endif
|
|
SetClearFeature(InstancePtr, FALSE);
|
|
break;
|
|
|
|
case SET_FEATURE:
|
|
#ifdef XUSB_CH9_DEBUG
|
|
xil_printf("Set Feature \r\n");
|
|
#endif
|
|
SetClearFeature(InstancePtr, TRUE);
|
|
break;
|
|
|
|
case SET_ADDRESS:
|
|
#ifdef XUSB_CH9_DEBUG
|
|
xil_printf("Set address \r\n");
|
|
#endif
|
|
SetupControlWriteStatusStage(InstancePtr);
|
|
break;
|
|
|
|
case GET_DESCRIPTOR:
|
|
GetDescriptor(InstancePtr);
|
|
break;
|
|
|
|
case SET_DESCRIPTOR:
|
|
#ifdef XUSB_CH9_DEBUG
|
|
xil_printf("Set Descriptor \r\n");
|
|
#endif
|
|
SetDescriptor(InstancePtr);
|
|
break;
|
|
|
|
case GET_CONFIGURATION:
|
|
#ifdef XUSB_CH9_DEBUG
|
|
xil_printf("Get Configuration \r\n");
|
|
#endif
|
|
GetConfiguration(InstancePtr);
|
|
break;
|
|
|
|
case SET_CONFIGURATION:
|
|
#ifdef XUSB_CH9_DEBUG
|
|
xil_printf("Set Configuration \r\n");
|
|
#endif
|
|
SetConfiguration(InstancePtr);
|
|
break;
|
|
|
|
case GET_INTERFACE:
|
|
#ifdef XUSB_CH9_DEBUG
|
|
xil_printf("Get Interface \r\n");
|
|
#endif
|
|
GetInterface(InstancePtr);
|
|
break;
|
|
|
|
case SET_INTERFACE:
|
|
#ifdef XUSB_CH9_DEBUG
|
|
xil_printf("Set Interface \r\n");
|
|
#endif
|
|
SetInterface(InstancePtr);
|
|
break;
|
|
|
|
case SYCH_FRAME:
|
|
break;
|
|
|
|
default:
|
|
/*
|
|
* The default is to stall the end point zero.
|
|
*/
|
|
XUsb_EpStall(InstancePtr, 0);
|
|
break;
|
|
}
|
|
|
|
}
|
|
else if ((Ch9_CmdBuf.Byte0.bmRequestType & TYPE_MASK) == TYPE_CLASS) {
|
|
#ifdef XUSB_CH9_DEBUG
|
|
xil_printf("Sub class code %d \r\n", Ch9_CmdBuf.Byte1.bRequest);
|
|
#endif
|
|
return (Ch9_CmdBuf.Byte1.bRequest);
|
|
}
|
|
else {
|
|
/*
|
|
* Unsupported command. Stall the end point.
|
|
*/
|
|
XUsb_EpStall(InstancePtr, 0);
|
|
}
|
|
return XST_SUCCESS;
|
|
}
|
|
|
|
/******************************************************************************
|
|
Start of Chapter 9 Commands
|
|
******************************************************************************/
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* This function responds to the GET_INTERFACE command.
|
|
*
|
|
* @param InstancePtr is a pointer to the XUsb instance of the controller.
|
|
*
|
|
* @return None.
|
|
*
|
|
* @note None.
|
|
*
|
|
******************************************************************************/
|
|
void GetInterface(XUsb * InstancePtr)
|
|
{
|
|
u32 *RamBase;
|
|
|
|
#ifdef __LITTLE_ENDIAN__
|
|
Ch9_CmdBuf.Word1.wValue =
|
|
((u16)(Ch9_CmdBuf.Word1.Byte23.bDescriptorIndex) |
|
|
(u16)(Ch9_CmdBuf.Word1.Byte23.bDescriptorType << 8));
|
|
#endif
|
|
|
|
if (Ch9_CmdBuf.Word1.wValue == 0) {
|
|
RamBase = (u32 *) (InstancePtr->Config.BaseAddress +
|
|
((InstancePtr->DeviceConfig.Ep[0].
|
|
RamBase) << 2));
|
|
UsbMemData.Word = 0x0;
|
|
*RamBase = UsbMemData.Word;
|
|
InstancePtr->DeviceConfig.Ep[0].Buffer0Ready = 1;
|
|
|
|
XUsb_WriteReg(InstancePtr->Config.BaseAddress,
|
|
(InstancePtr->EndPointOffset[0] +
|
|
XUSB_EP_BUF0COUNT_OFFSET), 1);
|
|
XUsb_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XUSB_BUFFREADY_OFFSET, 1);
|
|
|
|
}
|
|
else {
|
|
XUsb_EpStall(InstancePtr, 0);
|
|
}
|
|
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/**
|
|
* This function responds to the SET_INTERFACE command.
|
|
*
|
|
* @param InstancePtr is a pointer to the XUsb instance of the controller.
|
|
*
|
|
* @return None.
|
|
*
|
|
* @note None.
|
|
*
|
|
******************************************************************************/
|
|
void SetInterface(XUsb * InstancePtr)
|
|
{
|
|
if ((Ch9_CmdBuf.Word1.wValue == 0) && (Ch9_CmdBuf.Word2.wIndex == 0)) {
|
|
SetupControlWriteStatusStage(InstancePtr);
|
|
}
|
|
else {
|
|
#ifdef MICROPHONE
|
|
SetupControlWriteStatusStage(InstancePtr);
|
|
#else
|
|
XUsb_EpStall(InstancePtr, 0);
|
|
#endif
|
|
}
|
|
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/**
|
|
* This function sets the basic Control status words.
|
|
*
|
|
* @param InstancePtr is a pointer to the XUsb instance of the controller.
|
|
*
|
|
* @return None.
|
|
*
|
|
* @note None.
|
|
*
|
|
******************************************************************************/
|
|
void SetupControlWriteStatusStage(XUsb * InstancePtr)
|
|
{
|
|
u32 EpCfgReg;
|
|
|
|
EpCfgReg = XUsb_ReadReg(InstancePtr->Config.BaseAddress,
|
|
InstancePtr->EndPointOffset[0]);
|
|
EpCfgReg |= XUSB_EP_CFG_DATA_TOGGLE_MASK;
|
|
|
|
XUsb_WriteReg(InstancePtr->Config.BaseAddress,
|
|
InstancePtr->EndPointOffset[0], EpCfgReg);
|
|
InstancePtr->DeviceConfig.Ep[0].Buffer0Count = 0;
|
|
XUsb_WriteReg(InstancePtr->Config.BaseAddress,
|
|
(InstancePtr->EndPointOffset[0] +
|
|
XUSB_EP_BUF0COUNT_OFFSET), 0);
|
|
XUsb_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XUSB_BUFFREADY_OFFSET, 1);
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/**
|
|
* This routine is called when a GET_STATUS command is received.
|
|
*
|
|
* @param InstancePtr is a pointer to the XUsb instance of the controller.
|
|
*
|
|
* @return None.
|
|
*
|
|
* @note None.
|
|
*
|
|
******************************************************************************/
|
|
void GetStatus(XUsb * InstancePtr)
|
|
{
|
|
u32 *RamBase;
|
|
u8 EndPoint;
|
|
|
|
UsbMemData.Word = 0x0;
|
|
RamBase = (u32 *) (InstancePtr->Config.BaseAddress +
|
|
((InstancePtr->DeviceConfig.Ep[0].RamBase) << 2));
|
|
|
|
switch (Ch9_CmdBuf.Byte0.bmRequestType) {
|
|
case STANDARD_IN_DEVICE:
|
|
UsbMemData.Byte.Zero = 0x01;
|
|
UsbMemData.Byte.One = 0x00;
|
|
|
|
*RamBase = UsbMemData.Word;
|
|
|
|
InstancePtr->DeviceConfig.Ep[0].Buffer0Ready = 1;
|
|
XUsb_WriteReg(InstancePtr->Config.BaseAddress,
|
|
(InstancePtr->EndPointOffset[0] +
|
|
XUSB_EP_BUF0COUNT_OFFSET), 2);
|
|
XUsb_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XUSB_BUFFREADY_OFFSET, 1);
|
|
break;
|
|
|
|
case STANDARD_IN_INTERFACE:
|
|
if ((Ch9_CmdBuf.Word2.wIndex > 0) &&
|
|
(Ch9_CmdBuf.Word2.wIndex <= MAX_INTERFACES)) {
|
|
UsbMemData.Byte.Zero = 0;
|
|
UsbMemData.Byte.One = 0;
|
|
*RamBase = UsbMemData.Word;
|
|
InstancePtr->DeviceConfig.Ep[0].Buffer0Ready = 1;
|
|
XUsb_WriteReg(InstancePtr->Config.
|
|
BaseAddress, (InstancePtr->EndPointOffset
|
|
[0] + XUSB_EP_BUF0COUNT_OFFSET),
|
|
2);
|
|
XUsb_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XUSB_BUFFREADY_OFFSET, 1);
|
|
}
|
|
else {
|
|
XUsb_EpStall(InstancePtr, 0);
|
|
}
|
|
break;
|
|
|
|
case STANDARD_IN_ENDPOINT:
|
|
EndPoint = (unsigned int) (Ch9_CmdBuf.Word2.wIndex & 0x07);
|
|
UsbMemData.Byte.Zero =
|
|
(u8) (((XUsb_ReadReg(InstancePtr->Config.BaseAddress,
|
|
InstancePtr->
|
|
EndPointOffset[EndPoint]))
|
|
& XUSB_EP_CFG_STALL_MASK) >>
|
|
XUSB_EP_CFG_STALL_SHIFT);
|
|
UsbMemData.Byte.One = 0;
|
|
|
|
*RamBase = UsbMemData.Word;
|
|
|
|
InstancePtr->DeviceConfig.Ep[0].Buffer0Ready = 1;
|
|
XUsb_WriteReg(InstancePtr->Config.BaseAddress,
|
|
(InstancePtr->EndPointOffset[0] +
|
|
XUSB_EP_BUF0COUNT_OFFSET), 2);
|
|
XUsb_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XUSB_BUFFREADY_OFFSET, 1);
|
|
break;
|
|
|
|
default:
|
|
/*
|
|
* The default is to stall the end point.
|
|
*/
|
|
XUsb_EpStall(InstancePtr, 0);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/**
|
|
* This routine is called when a GET_DESCRIPTOR command is received.
|
|
*
|
|
* @param InstancePtr is a pointer to the XUsb instance of the controller.
|
|
*
|
|
* @return None.
|
|
*
|
|
* @note None.
|
|
*
|
|
******************************************************************************/
|
|
void GetDescriptor(XUsb * InstancePtr)
|
|
{
|
|
switch (Ch9_CmdBuf.Word1.Byte23.bDescriptorType) {
|
|
case DEVICE_DESCR:
|
|
#ifdef XUSB_CH9_DEBUG
|
|
xil_printf("Get Dev Decriptor \r\n");
|
|
#endif
|
|
if (InstancePtr->DeviceConfig.CurrentSpeed ==
|
|
XUSB_EP_HIGH_SPEED) {
|
|
Ch9_CmdBuf.ContWritePtr =
|
|
(unsigned char *) &DeviceDescriptor;
|
|
}
|
|
else {
|
|
Ch9_CmdBuf.ContWritePtr = (u8 *) &DeviceDescriptor;
|
|
}
|
|
Ch9_CmdBuf.ContWriteCount = sizeof(USB_STD_DEV_DESC);
|
|
if (Ch9_CmdBuf.ContWriteCount > Ch9_CmdBuf.Word3.wLength) {
|
|
Ch9_CmdBuf.ContWriteCount = Ch9_CmdBuf.Word3.wLength;
|
|
}
|
|
break;
|
|
|
|
case QUALIFIER_DESCR:
|
|
#ifdef XUSB_CH9_DEBUG
|
|
xil_printf("Get Qua Decriptor \r\n");
|
|
#endif
|
|
Ch9_CmdBuf.ContWritePtr =
|
|
(unsigned char *) &QualifierDescriptor;
|
|
Ch9_CmdBuf.ContWriteCount = sizeof(USB_STD_QUAL_DESC);
|
|
if (Ch9_CmdBuf.ContWriteCount > Ch9_CmdBuf.Word3.wLength) {
|
|
Ch9_CmdBuf.ContWriteCount = Ch9_CmdBuf.Word3.wLength;
|
|
}
|
|
break;
|
|
|
|
case CONFIG_DESCR:
|
|
#ifdef XUSB_CH9_DEBUG
|
|
xil_printf("Get Config Decriptor \r\n");
|
|
#endif
|
|
if (Ch9_CmdBuf.Word1.Byte23.bDescriptorIndex <=
|
|
DeviceDescriptor.bNumConfigurations) {
|
|
switch (Ch9_CmdBuf.Word1.Byte23.bDescriptorIndex) {
|
|
case 0:
|
|
/*
|
|
* Duplicate this for each configuration
|
|
* supported.
|
|
*/
|
|
if (InstancePtr->DeviceConfig.
|
|
CurrentSpeed == XUSB_EP_HIGH_SPEED) {
|
|
#ifdef XUSB_CH9_DEBUG
|
|
xil_printf("High Speed \r\n");
|
|
#endif
|
|
HsUsbConfig.stdCfg.bType = CONFIG_DESCR;
|
|
Ch9_CmdBuf.ContWritePtr =
|
|
(u8 *) &HsUsbConfig;
|
|
Ch9_CmdBuf.ContWriteCount =
|
|
HsUsbConfig.stdCfg.bTotalLength;
|
|
}
|
|
else {
|
|
FsUsbConfig.stdCfg.bType = CONFIG_DESCR;
|
|
Ch9_CmdBuf.ContWritePtr =
|
|
(u8 *) &FsUsbConfig;
|
|
Ch9_CmdBuf.ContWriteCount =
|
|
FsUsbConfig.stdCfg.bTotalLength;
|
|
}
|
|
if (Ch9_CmdBuf.ContWriteCount >
|
|
Ch9_CmdBuf.Word3.wLength) {
|
|
Ch9_CmdBuf.ContWriteCount =
|
|
Ch9_CmdBuf.Word3.wLength;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
XUsb_EpStall(InstancePtr, 0);
|
|
goto Func_Exit7;
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
XUsb_EpStall(InstancePtr, 0);
|
|
goto Func_Exit7;
|
|
}
|
|
break;
|
|
|
|
case OSD_CONFIG_DESCR:
|
|
#ifdef XUSB_CH9_DEBUG
|
|
xil_printf("Get OSD Config Decriptor \r\n");
|
|
#endif
|
|
if (Ch9_CmdBuf.Word1.Byte23.bDescriptorIndex <=
|
|
DeviceDescriptor.bNumConfigurations) {
|
|
switch (Ch9_CmdBuf.Word1.Byte23.bDescriptorIndex) {
|
|
case 0:
|
|
/*
|
|
* Duplicate this for each
|
|
* configuration supported.
|
|
*/
|
|
if (InstancePtr->DeviceConfig.
|
|
CurrentSpeed == XUSB_EP_HIGH_SPEED) {
|
|
FsUsbConfig.stdCfg.bType =
|
|
OSD_CONFIG_DESCR;
|
|
Ch9_CmdBuf.ContWritePtr =
|
|
(u8 *) &FsUsbConfig;
|
|
Ch9_CmdBuf.ContWriteCount =
|
|
FsUsbConfig.stdCfg.bTotalLength;
|
|
}
|
|
else {
|
|
HsUsbConfig.stdCfg.bType =
|
|
OSD_CONFIG_DESCR;
|
|
Ch9_CmdBuf.ContWritePtr =
|
|
(u8 *) &HsUsbConfig;
|
|
Ch9_CmdBuf.ContWriteCount =
|
|
HsUsbConfig.stdCfg.bTotalLength;
|
|
}
|
|
if (Ch9_CmdBuf.ContWriteCount >
|
|
Ch9_CmdBuf.Word3.wLength) {
|
|
Ch9_CmdBuf.ContWriteCount =
|
|
Ch9_CmdBuf.Word3.wLength;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
XUsb_EpStall(InstancePtr, 0);
|
|
goto Func_Exit7;
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
XUsb_EpStall(InstancePtr, 0);
|
|
goto Func_Exit7;
|
|
}
|
|
break;
|
|
|
|
case STRING_DESCR:
|
|
if (Ch9_CmdBuf.Word1.Byte23.bDescriptorIndex <= 3) {
|
|
switch (Ch9_CmdBuf.Word1.Byte23.bDescriptorIndex) {
|
|
case 0:
|
|
/*
|
|
* Set the language ID's.
|
|
*/
|
|
#ifdef XUSB_CH9_DEBUG
|
|
xil_printf("Get LangId \r\n");
|
|
#endif
|
|
Ch9_CmdBuf.ContWritePtr =
|
|
(unsigned char *) &LangId;
|
|
Ch9_CmdBuf.ContWriteCount = LangId.bLength;
|
|
if (Ch9_CmdBuf.ContWriteCount >
|
|
Ch9_CmdBuf.Word3.wLength) {
|
|
Ch9_CmdBuf.ContWriteCount =
|
|
Ch9_CmdBuf.Word3.wLength;
|
|
}
|
|
break;
|
|
|
|
case 1:
|
|
/*
|
|
* Set the Manufacturer's String.
|
|
*/
|
|
#ifdef XUSB_CH9_DEBUG
|
|
xil_printf("Get Manuferer \r\n");
|
|
#endif
|
|
Ch9_CmdBuf.ContWritePtr =
|
|
(unsigned char *) &Manufacturer;
|
|
Ch9_CmdBuf.ContWriteCount =
|
|
Manufacturer.bLength;
|
|
if (Ch9_CmdBuf.ContWriteCount >
|
|
Ch9_CmdBuf.Word3.wLength) {
|
|
Ch9_CmdBuf.ContWriteCount =
|
|
Ch9_CmdBuf.Word3.wLength;
|
|
}
|
|
break;
|
|
|
|
case 2:
|
|
/*
|
|
* Set the Product String.
|
|
*/
|
|
#ifdef XUSB_CH9_DEBUG
|
|
xil_printf("Get Product Id \r\n");
|
|
#endif
|
|
Ch9_CmdBuf.ContWritePtr =
|
|
(unsigned char *) &ProductString;
|
|
Ch9_CmdBuf.ContWriteCount =
|
|
ProductString.bLength;
|
|
if (Ch9_CmdBuf.ContWriteCount >
|
|
Ch9_CmdBuf.Word3.wLength) {
|
|
Ch9_CmdBuf.ContWriteCount =
|
|
Ch9_CmdBuf.Word3.wLength;
|
|
}
|
|
break;
|
|
|
|
case 3:
|
|
/*
|
|
* Set the Serial Number String.
|
|
*/
|
|
#ifdef XUSB_CH9_DEBUG
|
|
xil_printf("Get Serial No \r\n");
|
|
#endif
|
|
Ch9_CmdBuf.ContWritePtr =
|
|
(unsigned char *) &SerialNumber;
|
|
Ch9_CmdBuf.ContWriteCount =
|
|
SerialNumber.bLength;
|
|
if (Ch9_CmdBuf.ContWriteCount >
|
|
Ch9_CmdBuf.Word3.wLength) {
|
|
Ch9_CmdBuf.ContWriteCount =
|
|
Ch9_CmdBuf.Word3.wLength;
|
|
}
|
|
break;
|
|
default:
|
|
XUsb_EpStall(InstancePtr, 0);
|
|
goto Func_Exit7;
|
|
break;
|
|
}
|
|
}
|
|
else {
|
|
XUsb_EpStall(InstancePtr, 0);
|
|
goto Func_Exit7;
|
|
}
|
|
break;
|
|
|
|
#ifdef HID_DEVICES
|
|
case HID_DESC:
|
|
#ifdef XUSB_CH9_DEBUG
|
|
xil_printf("Get HID descriptor \r\n");
|
|
#endif
|
|
Ch9_CmdBuf.ContWritePtr = (unsigned char *)&HidDescriptor;
|
|
Ch9_CmdBuf.ContWriteCount =
|
|
HidDescriptor.bLength;
|
|
if (Ch9_CmdBuf.ContWriteCount >
|
|
Ch9_CmdBuf.Word3.wLength) {
|
|
Ch9_CmdBuf.ContWriteCount =
|
|
Ch9_CmdBuf.Word3.wLength;
|
|
}
|
|
break;
|
|
case REPORT_DESC:
|
|
#ifdef XUSB_CH9_DEBUG
|
|
xil_printf(" Get Report descriptor \r\n");
|
|
#endif
|
|
Ch9_CmdBuf.ContWritePtr = (unsigned char *) &ReportDesc[0];
|
|
Ch9_CmdBuf.ContWriteCount = sizeof (ReportDesc);
|
|
if (Ch9_CmdBuf.ContWriteCount >
|
|
Ch9_CmdBuf.Word3.wLength) {
|
|
Ch9_CmdBuf.ContWriteCount =
|
|
Ch9_CmdBuf.Word3.wLength;
|
|
}
|
|
break;
|
|
#endif
|
|
default:
|
|
/*
|
|
* The default is to stall the end point zero.
|
|
*/
|
|
XUsb_EpStall(InstancePtr, 0);
|
|
goto Func_Exit7;
|
|
break;
|
|
|
|
}
|
|
LoadEP0(InstancePtr);
|
|
|
|
Func_Exit7:
|
|
return;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/**
|
|
* This routine is called when a SET_DESCRIPTOR command is received.
|
|
*
|
|
* @param InstancePtr is a pointer to the XUsb instance of the controller.
|
|
*
|
|
* @return None.
|
|
*
|
|
* @note None.
|
|
*
|
|
******************************************************************************/
|
|
void SetDescriptor(XUsb * InstancePtr)
|
|
{
|
|
/*
|
|
* Command not supported.
|
|
*/
|
|
XUsb_EpStall(InstancePtr, 0);
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/**
|
|
* This routine is called when a GET_CONFIGURATION command is received.
|
|
*
|
|
* @param InstancePtr is a pointer to the XUsb instance of the controller.
|
|
*
|
|
* @return None.
|
|
*
|
|
* @note None.
|
|
*
|
|
******************************************************************************/
|
|
void GetConfiguration(XUsb * InstancePtr)
|
|
{
|
|
u32 *RamBase;
|
|
|
|
UsbMemData.Word = 0x00;
|
|
RamBase = (u32 *) (InstancePtr->Config.BaseAddress +
|
|
((InstancePtr->DeviceConfig.Ep[0].RamBase) << 2));
|
|
UsbMemData.Byte.Zero = InstancePtr->DeviceConfig.CurrentConfiguration;
|
|
UsbMemData.Byte.One = 0;
|
|
UsbMemData.Byte.Two = 0;
|
|
UsbMemData.Byte.Three = 0;
|
|
|
|
*RamBase = UsbMemData.Word;
|
|
|
|
InstancePtr->DeviceConfig.Ep[0].Buffer0Ready = 1;
|
|
XUsb_WriteReg(InstancePtr->Config.BaseAddress,
|
|
(InstancePtr->EndPointOffset[0] +
|
|
XUSB_EP_BUF0COUNT_OFFSET), 1);
|
|
XUsb_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XUSB_BUFFREADY_OFFSET, 1);
|
|
Ch9_CmdBuf.ContWriteCount = 0;
|
|
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/**
|
|
* This routine is called when a SET_CONFIGURATION command is received.
|
|
*
|
|
* @param InstancePtr is a pointer to the XUsb instance of the controller.
|
|
*
|
|
* @return None.
|
|
*
|
|
* @note None.
|
|
*
|
|
******************************************************************************/
|
|
void SetConfiguration(XUsb * InstancePtr)
|
|
{
|
|
u8 Index;
|
|
|
|
#ifdef __LITTLE_ENDIAN__
|
|
Ch9_CmdBuf.Word1.wValue =
|
|
((u16)(Ch9_CmdBuf.Word1.Byte23.bDescriptorIndex) |
|
|
(u16)(Ch9_CmdBuf.Word1.Byte23.bDescriptorType << 8));
|
|
#endif
|
|
|
|
switch (Ch9_CmdBuf.Word1.wValue) {
|
|
case 0:
|
|
/*
|
|
* This configuration value resets the device to the
|
|
* un configured state like power up.
|
|
*/
|
|
#ifdef XUSB_CH9_DEBUG
|
|
xil_printf("Reset Configuration \r\n");
|
|
#endif
|
|
InstancePtr->DeviceConfig.CurrentConfiguration = 0;
|
|
InitUsbInterface(InstancePtr);
|
|
/*
|
|
* Cause a valid status phase to be issued.
|
|
*/
|
|
SetupControlWriteStatusStage(InstancePtr);
|
|
break;
|
|
|
|
case CONFIGURATION_ONE:
|
|
#ifdef XUSB_CH9_DEBUG
|
|
xil_printf("USB enumerated \r\n");
|
|
#endif
|
|
InstancePtr->DeviceConfig.CurrentConfiguration = 1;
|
|
|
|
|
|
SetupControlWriteStatusStage(InstancePtr);
|
|
|
|
for (Index = 0; Index < InstancePtr->DeviceConfig.NumEndpoints;
|
|
Index++){
|
|
|
|
if (Index != 0){
|
|
if (InstancePtr->DeviceConfig.Ep[Index].OutIn ==
|
|
XUSB_EP_DIRECTION_OUT) {
|
|
XUsb_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XUSB_BUFFREADY_OFFSET, 1 << Index);
|
|
|
|
InstancePtr->DeviceConfig.Ep[Index].Buffer0Ready = 1;
|
|
|
|
XUsb_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XUSB_BUFFREADY_OFFSET, (1 <<
|
|
(Index +
|
|
XUSB_STATUS_EP_BUFF2_SHIFT)));
|
|
InstancePtr->DeviceConfig.Ep[Index].Buffer1Ready = 1;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
/*
|
|
* Additional configurations can be added here.
|
|
*/
|
|
default:
|
|
/*
|
|
* stall the end point.
|
|
*/
|
|
XUsb_EpStall(InstancePtr, 0);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/**
|
|
* This routine is called when a SET_FEATURE or a CLEAR_FEATURE command is
|
|
* received.
|
|
*
|
|
* @param InstancePtr is a pointer to the XUsb instance of the controller.
|
|
* @param flag specifies whether it is a SET_FEATURE (TRUE)or a
|
|
* CLEAR_FEATURE (FALSE) command.
|
|
*
|
|
* @return None.
|
|
*
|
|
* @note None.
|
|
*
|
|
******************************************************************************/
|
|
void SetClearFeature(XUsb * InstancePtr, int flag)
|
|
{
|
|
u8 EndPoint;
|
|
u8 OutInbit;
|
|
u32 EpCfgReg;
|
|
|
|
#ifdef __LITTLE_ENDIAN__
|
|
Ch9_CmdBuf.Word1.wValue =
|
|
((u16)(Ch9_CmdBuf.Word1.Byte23.bDescriptorIndex) |
|
|
(u16)(Ch9_CmdBuf.Word1.Byte23.bDescriptorType << 8));
|
|
#endif
|
|
|
|
switch (Ch9_CmdBuf.Byte0.bmRequestType) {
|
|
case STANDARD_OUT_DEVICE:
|
|
switch (Ch9_CmdBuf.Word1.wValue) {
|
|
case DEVICE_REMOTE_WAKEUP:
|
|
/*
|
|
* User needs to add code here.
|
|
*/
|
|
break;
|
|
|
|
case TEST_MODE:
|
|
/*
|
|
* The Test Mode will be executed
|
|
* after the status phase.
|
|
*/
|
|
break;
|
|
|
|
default:
|
|
XUsb_EpStall(InstancePtr, 0);
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case STANDARD_OUT_ENDPOINT:
|
|
if (Ch9_CmdBuf.Word1.wValue == 0) {
|
|
EndPoint = Ch9_CmdBuf.Word2.wIndex & 0xf;
|
|
OutInbit = Ch9_CmdBuf.Word2.wIndex & 0x80;
|
|
OutInbit = OutInbit >> 7;
|
|
|
|
/*
|
|
* Make sure direction matches.
|
|
*/
|
|
if (OutInbit !=
|
|
InstancePtr->DeviceConfig.Ep[EndPoint].OutIn) {
|
|
XUsb_EpStall(InstancePtr, 0);
|
|
goto Func_Exit10;
|
|
}
|
|
|
|
if (EndPoint == 0) {
|
|
/*
|
|
* Clear the stall.
|
|
*/
|
|
XUsb_EpUnstall(InstancePtr, 0);
|
|
|
|
break;
|
|
}
|
|
else {
|
|
if (flag == TRUE) {
|
|
XUsb_EpStall(InstancePtr, EndPoint);
|
|
}
|
|
else {
|
|
XUsb_EpUnstall(InstancePtr, EndPoint);
|
|
|
|
/*
|
|
* Clear the data toggle.
|
|
*/
|
|
EpCfgReg =
|
|
XUsb_ReadReg(InstancePtr->
|
|
Config.
|
|
BaseAddress,
|
|
InstancePtr->
|
|
EndPointOffset
|
|
[EndPoint]);
|
|
EpCfgReg &=
|
|
~XUSB_EP_CFG_DATA_TOGGLE_MASK;
|
|
XUsb_WriteReg(InstancePtr->Config.
|
|
BaseAddress,
|
|
InstancePtr->
|
|
EndPointOffset[EndPoint],
|
|
EpCfgReg);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
/*
|
|
* Add more here as needed.
|
|
*/
|
|
default:
|
|
XUsb_EpStall(InstancePtr, 0);
|
|
goto Func_Exit10;
|
|
break;
|
|
}
|
|
|
|
/*
|
|
* Cause and valid status phase to be issued.
|
|
*/
|
|
SetupControlWriteStatusStage(InstancePtr);
|
|
|
|
Func_Exit10:
|
|
return;
|
|
}
|
|
|
|
/******************************************************************************/
|
|
/**
|
|
* This routine copies the EP0 related data to the DPRAM.
|
|
*
|
|
* @param InstancePtr is a pointer to the XUsb instance of the controller.
|
|
*
|
|
* @return None.
|
|
*
|
|
* @note None.
|
|
*
|
|
******************************************************************************/
|
|
void LoadEP0(XUsb * InstancePtr)
|
|
{
|
|
u16 Count;
|
|
u8 *RamBase;
|
|
u16 Index;
|
|
|
|
if (MaxControlSize >= Ch9_CmdBuf.ContWriteCount) {
|
|
Count = Ch9_CmdBuf.ContWriteCount;
|
|
}
|
|
else {
|
|
Count = MaxControlSize;
|
|
}
|
|
|
|
/*
|
|
* Copy the data to be transmitted into the DPRAM.
|
|
*/
|
|
RamBase = (u8 *) (InstancePtr->Config.BaseAddress +
|
|
((InstancePtr->DeviceConfig.Ep[0].RamBase) << 2));
|
|
for (Index = 0; Index < Count; Index++) {
|
|
|
|
*RamBase++ = *Ch9_CmdBuf.ContWritePtr++;
|
|
}
|
|
|
|
/*
|
|
* Set the Tx packet size and enable the Transmission.
|
|
*/
|
|
XUsb_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XUSB_EP_BUF0COUNT_OFFSET, Count);
|
|
|
|
XUsb_WriteReg(InstancePtr->Config.BaseAddress,
|
|
XUSB_BUFFREADY_OFFSET, 1);
|
|
|
|
InstancePtr->DeviceConfig.Ep[0].Buffer0Ready = 1;
|
|
|
|
Ch9_CmdBuf.ContWriteCount -= Count;
|
|
}
|
|
|