| /******************************************************************************
|
| *
|
| * (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;
|
| }
|
|
|
|
|
|
|