embeddedsw/XilinxProcessorIPLib/drivers/usb/examples/xusb_cp9.c
Jagannadha Sutradharudu Teki 2c8f92039d embeddesw: Add initial code support
Added initial support Xilinx Embedded Software.

Signed-off-by: Jagannadha Sutradharudu Teki <jaganna@xilinx.com>
2014-06-24 16:45:01 +05:30

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;
}