blob: 106e91ae5dc2bf27384181eafe2d6ffdfc0204d0 [file] [log] [blame]
/******************************************************************************
*
* (C)Copyright 2013 Marvell. All Rights Reserved.
*
* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MARVELL.
* The copyright notice above does not evidence any actual or intended
* publication of such source code.
* This Module contains Proprietary Information of Marvell and should be
* treated as Confidential.
* The information in this file is provided for the exclusive use of the
* licensees of Marvell.
* Such users have the right to use, modify, and incorporate this code into
* products for purposes authorized by the license agreement provided they
* include this notice and the associated copyright notice with any such
* product.
* The information in this file is provided "AS IS" without warranty.
*
******************************************************************************/
#include "Typedef.h"
#include "misc.h"
#include "usb_descriptors.h"
#include "usbdefs.h"
#include "usb2_main.h"
#include "usb2_enumeration.h"
#include "usbapi.h"
#if BOOTROM
#include "Bootrom.h"
#endif
//these are allocated in UsbDescriptors.c
extern OPT_USB_DESCRIPTOR_LOADS USBDescriptors[NUM_USB_DESCRIPTORS];
extern CHAR USB2DevQualDesc[];
extern CHAR USB1ConfigDesc[];
extern UINT_T USBStringIndexTable[MAX_USB_STRINGS];
extern void USB2D_VendorRequest(P_DC_Properties_T pDCProps, P_XLLP_USB_SETUP_DATA_T pSetupPacket);
void USB2D_EnumerationHandler(P_DC_Properties_T pDCProps, P_XLLP_USB_SETUP_DATA_T pSetupPacket)
{
switch (pSetupPacket->bmRequestType & 0x60)
{
case STANDARD_REQ:
switch (pSetupPacket->bRequest)
{
case REQ_GET_STATUS:
USB2D_GetStatus(pDCProps, pSetupPacket);
break;
// case REQ_CLEAR_FEATURE:
// mvUsbCh9ClearFeature(handle, setup, &ci_otg_setupPacket);
// break;
// case REQ_SET_FEATURE:
// mvUsbCh9SetFeature(handle, setup, &ci_otg_setupPacket);
// break;
case REQ_SET_ADDRESS:
USB2D_SetAddress(pDCProps, pSetupPacket);
break;
case REQ_GET_DESCRIPTOR:
USB2D_GetDescriptor(pDCProps, pSetupPacket);
break;
// case REQ_SET_DESCRIPTOR:
// mvUsbCh9SetDescriptior(handle, setup, &ci_otg_setupPacket);
// break;
// case REQ_GET_CONFIGURATION:
// mvUsbCh9GetConfig(handle, setup, &ci_otg_setupPacket);
// break;
case REQ_SET_CONFIGURATION:
USB2D_SetConfig(pDCProps, pSetupPacket);
break;
// case REQ_GET_INTERFACE:
// mvUsbCh9GetInterface(handle, setup, &ci_otg_setupPacket);
// break;
// case REQ_SET_INTERFACE:
// mvUsbCh9SetInterface(handle, setup, &ci_otg_setupPacket);
// break;
default:
//unhandled descriptor. send a STALL PID
pDCProps->pUSBRegs->ENDPTCTRLX[USB_ENDPOINT_0] |= BIT0; //set the RX EP0 STALL bit (RXS)
break;
} // Endswitch
break;
case VENDOR_REQ:
USB2D_VendorRequest(pDCProps, pSetupPacket);
break;
default:
//unhandled descriptor. send a STALL PID
pDCProps->pUSBRegs->ENDPTCTRLX[USB_ENDPOINT_0] |= BIT0; //set the RX EP0 STALL bit (RXS)
break;
} //Endswitch
}
void USB2D_GetDescriptor(P_DC_Properties_T pDCProps, P_XLLP_USB_SETUP_DATA_T pSetupPacket)
{
UINT pktSize, stringLength, stringIndex;
UCHAR *payload = "UNHANDLED";
// Load the appropriate string depending on the descriptor requested
switch (pSetupPacket->wValue >> 8)
{
case DESC_TYPE_DEVICE:
pktSize = USBDescriptors[USB_DEVICE_DESCRIPTOR & 0xFF].DesSize;
payload = (UCHAR*)(USBDescriptors[USB_DEVICE_DESCRIPTOR & 0xFF].pDesPayload);
break;
case DESC_TYPE_CONFIG:
pktSize = USBDescriptors[USB_CONFIG_DESCRIPTOR & 0xFF].DesSize;
payload = (UCHAR*)(USBDescriptors[USB_CONFIG_DESCRIPTOR & 0xFF].pDesPayload);
break;
case DESC_TYPE_STRING:
stringIndex = ((pSetupPacket->wValue) & 0xFF);
// Bounds protection
if (stringIndex >= MAX_USB_STRINGS)
{
stringLength = (pSetupPacket->wLength);
if (stringLength > USBDescriptors[USB_DEFAULT_STRING_DESCRIPTOR & 0xFF].DesSize)
pktSize = USBDescriptors[USB_DEFAULT_STRING_DESCRIPTOR & 0xFF].DesSize;
else
pktSize = stringLength;
payload =(UCHAR*)(USBDescriptors[USB_DEFAULT_STRING_DESCRIPTOR & 0xFF].pDesPayload);
break;
}
switch (USBStringIndexTable[stringIndex])
{
case USB_LANGUAGE_STRING_DESCRIPTOR:
case USB_MANUFACTURER_STRING_DESCRIPTOR:
case USB_PRODUCT_STRING_DESCRIPTOR:
case USB_SERIAL_STRING_DESCRIPTOR:
case USB_INTERFACE_STRING_DESCRIPTOR:
case USB_DEFAULT_STRING_DESCRIPTOR:
stringLength = (pSetupPacket->wLength);
if (stringLength > USBDescriptors[USBStringIndexTable[stringIndex] & 0xFF].DesSize)
pktSize = USBDescriptors[USBStringIndexTable[stringIndex] & 0xFF].DesSize;
else
pktSize = stringLength;
payload = (UCHAR*)(USBDescriptors[USBStringIndexTable[stringIndex] & 0xFF].pDesPayload);
break;
default:
//unhandled descriptor. set length to 0
pktSize = 0;
break;
}
break; // from DESC_TYPE_STRING
case DESC_TYPE_INTERFACE:
pktSize = USBDescriptors[USB_INTERFACE_DESCRIPTOR & 0xFF].DesSize;
payload = (UCHAR*)(USBDescriptors[USB_INTERFACE_DESCRIPTOR & 0xFF].pDesPayload);
break;
case DESC_TYPE_ENDPOINT:
pktSize = USBDescriptors[USB_ENDPOINT_DESCRIPTOR & 0xFF].DesSize;
payload = (UCHAR*)(USBDescriptors[USB_ENDPOINT_DESCRIPTOR & 0xFF].pDesPayload);
break;
case DESC_TYPE_QUALIFIER:
//getting this request means the host wants us to run at FULL speed...
pktSize = USB2DevQualDesc[0]; //bLength field
payload = (UCHAR*) USB2DevQualDesc;
//overwrite the CONFIG descriptor to point to the FULL speed version
USBDescriptors[USB_CONFIG_DESCRIPTOR & 0xFF].DesSize = (USB1ConfigDesc[2]) + (USB1ConfigDesc[3] << 8); //LSB + MSB
USBDescriptors[USB_CONFIG_DESCRIPTOR & 0xFF].pDesPayload = (UINT *)USB1ConfigDesc;
break;
default:
//unhandled descriptor. set length to 0
pktSize = 0;
break;
} // Endswitch
//zero length means a valid descriptor was not found.
if(pktSize == 0)
{ //unhandled descriptor. send a STALL PID
pDCProps->pUSBRegs->ENDPTCTRLX[USB_ENDPOINT_0] |= BIT0; //set the RX EP0 STALL bit (RXS)
return;
}
//add EP0 TX dTD
pktSize = (pSetupPacket->wLength < pktSize) ? pSetupPacket->wLength : pktSize;
USB2D_EndpointTransmit(pDCProps, USB_ENDPOINT_0, USB_IN, (UINT)payload, pktSize);
//add EP0 RX dTD: size = 0, this is for the status OUT token
USB2D_EndpointTransmit(pDCProps, USB_ENDPOINT_0, USB_OUT, 0, 0);
return;
}
void USB2D_SetAddress(P_DC_Properties_T pDCProps, P_XLLP_USB_SETUP_DATA_T pSetupPacket)
{
//store the address value (and set the Advance bit)
pDCProps->pUSBRegs->DEVICE_ADDR = (pSetupPacket->wValue << 25) | BIT24;
//send a zero length pckt to finish the Set Address
USB2D_EndpointTransmit(pDCProps, USB_ENDPOINT_0, USB_IN, 0, 0);
}
void USB2D_GetStatus(P_DC_Properties_T pDCProps, P_XLLP_USB_SETUP_DATA_T pSetupPacket)
{
UINT value;
//Reply with a "Self Powered" status
value = 0x00000001;
USB2D_EndpointTransmit(pDCProps, USB_ENDPOINT_0, USB_IN, (UINT)&value, 2);
//add EP0 RX dTD: size = 0, this is for the status OUT token
USB2D_EndpointTransmit(pDCProps, USB_ENDPOINT_0, USB_OUT, 0, 0);
}
void USB2D_SetConfig(P_DC_Properties_T pDCProps, P_XLLP_USB_SETUP_DATA_T pSetupPacket)
{
P_USBAPI_T p_usb;
//send a zero length pckt to finish the Set Config
USB2D_EndpointTransmit(pDCProps, USB_ENDPOINT_0, USB_IN, 0, 0);
#if BOOTROM
//bootrom: check DOWNLOAD DISABLE fuse before allowing EP1 and 2 to be setup
if(GetTBREnvStruct()->Fuses.bits.Download_Disable)
return;
#endif
//set the packet size based on speed: HI 512, FULL 64
p_usb = GetUSBAPIhandle_InterruptNum(pDCProps->InterruptNum);
if(p_usb != NULL)
{
p_usb->maxpacketsize = (pDCProps->pUSBRegs->PORTSC & BIT27) ? 512 : 64;
//set the packet size based on speed: HI 512, FULL 64
//GetUSBAPIhandle_InterruptNum(pDCProps->InterruptNum)->maxpacketsize = (pDCProps->pUSBRegs->PORTSC & BIT27) ? 512 : 64;
//enable EP's based on the Config Table
USB2D_Endpoint_Setup(pDCProps, USB_ENDPOINT_B, USB_OUT, USB_BULK);
USB2D_Endpoint_Setup(pDCProps, USB_ENDPOINT_A, USB_IN, USB_BULK);
//prime EP2 for Preamble
USB2D_EndpointTransmit( pDCProps,
USB_ENDPOINT_B,
USB_OUT,
(UINT)pDCProps->BufferSpace,
//GetUSBAPIhandle_InterruptNum(pDCProps->InterruptNum)->maxpacketsize);
p_usb->maxpacketsize);
}
}
//Vendor Request Setup Packet
void USB2D_VendorRequest(P_DC_Properties_T pDCProps, P_XLLP_USB_SETUP_DATA_T pSetupPacket)
{
UCHAR * NoVendorString = "NoVendorString";
UINT pktSize, retval;
void * pPayload;
retval = FindVendorRequestInTIM (pSetupPacket->bRequest, pSetupPacket->bmRequestType, (UINT *)&pPayload, &pktSize);
if(retval != NoError)
{
pktSize = 15;//sizeof(ci2NoVendorString);
pPayload = NoVendorString;
}
pktSize = (pSetupPacket->wLength < pktSize) ? pSetupPacket->wLength : pktSize;
//add EP0 TX dTD
pktSize = (pSetupPacket->wLength < pktSize) ? pSetupPacket->wLength : pktSize;
USB2D_EndpointTransmit(pDCProps, USB_ENDPOINT_0, USB_IN, (UINT)pPayload, pktSize);
//add EP0 RX dTD: size = 0, this is for the status OUT token
USB2D_EndpointTransmit(pDCProps, USB_ENDPOINT_0, USB_OUT, 0, 0);
return;
}