b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame^] | 1 | /****************************************************************************** |
| 2 | * |
| 3 | * (C)Copyright 2013 Marvell. All Rights Reserved. |
| 4 | * |
| 5 | * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MARVELL. |
| 6 | * The copyright notice above does not evidence any actual or intended |
| 7 | * publication of such source code. |
| 8 | * This Module contains Proprietary Information of Marvell and should be |
| 9 | * treated as Confidential. |
| 10 | * The information in this file is provided for the exclusive use of the |
| 11 | * licensees of Marvell. |
| 12 | * Such users have the right to use, modify, and incorporate this code into |
| 13 | * products for purposes authorized by the license agreement provided they |
| 14 | * include this notice and the associated copyright notice with any such |
| 15 | * product. |
| 16 | * The information in this file is provided "AS IS" without warranty. |
| 17 | * |
| 18 | ******************************************************************************/ |
| 19 | |
| 20 | |
| 21 | #include "Typedef.h" |
| 22 | #include "misc.h" |
| 23 | #include "usb_descriptors.h" |
| 24 | #include "usbdefs.h" |
| 25 | #include "usb2_main.h" |
| 26 | #include "usb2_enumeration.h" |
| 27 | #include "usbapi.h" |
| 28 | #include "snps_usb.h" |
| 29 | #if BOOTROM |
| 30 | #include "Bootrom.h" |
| 31 | #endif |
| 32 | |
| 33 | //these are allocated in UsbDescriptors.c |
| 34 | extern OPT_USB_DESCRIPTOR_LOADS USBDescriptors[NUM_USB_DESCRIPTORS]; |
| 35 | extern CHAR USB2DevQualDesc[]; |
| 36 | extern CHAR USB1ConfigDesc[]; |
| 37 | extern UINT_T USBStringIndexTable[MAX_USB_STRINGS]; |
| 38 | extern void USB2D_VendorRequest(P_DC_Properties_T pDCProps, P_XLLP_USB_SETUP_DATA_T pSetupPacket); |
| 39 | extern int DWC3_GET_CONN_SPEED(void); |
| 40 | |
| 41 | UINT usbstatus_value = 0x00000001; |
| 42 | void USB2D_EnumerationHandler(P_DC_Properties_T pDCProps, P_XLLP_USB_SETUP_DATA_T pSetupPacket) |
| 43 | { |
| 44 | switch ((pSetupPacket->bmRequestType & 0x60) >> 5) |
| 45 | { |
| 46 | case STANDARD_REQ: |
| 47 | switch (pSetupPacket->bRequest) |
| 48 | { |
| 49 | case REQ_GET_STATUS: |
| 50 | USB2D_GetStatus(pDCProps, pSetupPacket); |
| 51 | break; |
| 52 | // case REQ_CLEAR_FEATURE: |
| 53 | // mvUsbCh9ClearFeature(handle, setup, &ci_otg_setupPacket); |
| 54 | // break; |
| 55 | // case REQ_SET_FEATURE: |
| 56 | // mvUsbCh9SetFeature(handle, setup, &ci_otg_setupPacket); |
| 57 | // break; |
| 58 | case REQ_SET_ADDRESS: |
| 59 | USB2D_SetAddress(pDCProps, pSetupPacket); |
| 60 | break; |
| 61 | case REQ_GET_DESCRIPTOR: |
| 62 | USB2D_GetDescriptor(pDCProps, pSetupPacket); |
| 63 | break; |
| 64 | // case REQ_SET_DESCRIPTOR: |
| 65 | // mvUsbCh9SetDescriptior(handle, setup, &ci_otg_setupPacket); |
| 66 | // break; |
| 67 | // case REQ_GET_CONFIGURATION: |
| 68 | // mvUsbCh9GetConfig(handle, setup, &ci_otg_setupPacket); |
| 69 | // break; |
| 70 | case REQ_SET_CONFIGURATION: |
| 71 | USB2D_SetConfig(pDCProps, pSetupPacket); |
| 72 | break; |
| 73 | // case REQ_GET_INTERFACE: |
| 74 | // mvUsbCh9GetInterface(handle, setup, &ci_otg_setupPacket); |
| 75 | // break; |
| 76 | // case REQ_SET_INTERFACE: |
| 77 | // mvUsbCh9SetInterface(handle, setup, &ci_otg_setupPacket); |
| 78 | // break; |
| 79 | default: |
| 80 | //unhandled descriptor. send a STALL PID |
| 81 | //TODO |
| 82 | DWC3_EP0_STALL_AND_RESTART(pDCProps); |
| 83 | break; |
| 84 | } // Endswitch |
| 85 | break; |
| 86 | case VENDOR_REQ: |
| 87 | USB2D_VendorRequest(pDCProps, pSetupPacket); |
| 88 | break; |
| 89 | default: |
| 90 | //unhandled descriptor. send a STALL PID |
| 91 | //TODO |
| 92 | DWC3_EP0_STALL_AND_RESTART(pDCProps); |
| 93 | break; |
| 94 | } //Endswitch |
| 95 | } |
| 96 | |
| 97 | void USB2D_GetDescriptor(P_DC_Properties_T pDCProps, P_XLLP_USB_SETUP_DATA_T pSetupPacket) |
| 98 | { |
| 99 | UINT pktSize, stringLength, stringIndex; |
| 100 | UCHAR *payload = "UNHANDLED"; |
| 101 | |
| 102 | // Load the appropriate string depending on the descriptor requested |
| 103 | switch (pSetupPacket->wValue >> 8) |
| 104 | { |
| 105 | case DESC_TYPE_DEVICE: |
| 106 | pktSize = USBDescriptors[USB_DEVICE_DESCRIPTOR & 0xFF].DesSize; |
| 107 | payload = (UCHAR*)(USBDescriptors[USB_DEVICE_DESCRIPTOR & 0xFF].pDesPayload); |
| 108 | break; |
| 109 | case DESC_TYPE_CONFIG: |
| 110 | pktSize = USBDescriptors[USB_CONFIG_DESCRIPTOR & 0xFF].DesSize; |
| 111 | payload = (UCHAR*)(USBDescriptors[USB_CONFIG_DESCRIPTOR & 0xFF].pDesPayload); |
| 112 | break; |
| 113 | case DESC_TYPE_STRING: |
| 114 | stringIndex = ((pSetupPacket->wValue) & 0xFF); |
| 115 | // Bounds protection |
| 116 | if (stringIndex >= MAX_USB_STRINGS) |
| 117 | { |
| 118 | stringLength = (pSetupPacket->wLength); |
| 119 | if (stringLength > USBDescriptors[USB_DEFAULT_STRING_DESCRIPTOR & 0xFF].DesSize) |
| 120 | pktSize = USBDescriptors[USB_DEFAULT_STRING_DESCRIPTOR & 0xFF].DesSize; |
| 121 | else |
| 122 | pktSize = stringLength; |
| 123 | payload =(UCHAR*)(USBDescriptors[USB_DEFAULT_STRING_DESCRIPTOR & 0xFF].pDesPayload); |
| 124 | break; |
| 125 | } |
| 126 | switch (USBStringIndexTable[stringIndex]) |
| 127 | { |
| 128 | case USB_LANGUAGE_STRING_DESCRIPTOR: |
| 129 | case USB_MANUFACTURER_STRING_DESCRIPTOR: |
| 130 | case USB_PRODUCT_STRING_DESCRIPTOR: |
| 131 | case USB_SERIAL_STRING_DESCRIPTOR: |
| 132 | case USB_INTERFACE_STRING_DESCRIPTOR: |
| 133 | case USB_DEFAULT_STRING_DESCRIPTOR: |
| 134 | stringLength = (pSetupPacket->wLength); |
| 135 | if (stringLength > USBDescriptors[USBStringIndexTable[stringIndex] & 0xFF].DesSize) |
| 136 | pktSize = USBDescriptors[USBStringIndexTable[stringIndex] & 0xFF].DesSize; |
| 137 | else |
| 138 | pktSize = stringLength; |
| 139 | payload = (UCHAR*)(USBDescriptors[USBStringIndexTable[stringIndex] & 0xFF].pDesPayload); |
| 140 | break; |
| 141 | default: |
| 142 | //unhandled descriptor. set length to 0 |
| 143 | pktSize = 0; |
| 144 | break; |
| 145 | } |
| 146 | break; // from DESC_TYPE_STRING |
| 147 | case DESC_TYPE_INTERFACE: |
| 148 | pktSize = USBDescriptors[USB_INTERFACE_DESCRIPTOR & 0xFF].DesSize; |
| 149 | payload = (UCHAR*)(USBDescriptors[USB_INTERFACE_DESCRIPTOR & 0xFF].pDesPayload); |
| 150 | break; |
| 151 | case DESC_TYPE_ENDPOINT: |
| 152 | pktSize = USBDescriptors[USB_ENDPOINT_DESCRIPTOR & 0xFF].DesSize; |
| 153 | payload = (UCHAR*)(USBDescriptors[USB_ENDPOINT_DESCRIPTOR & 0xFF].pDesPayload); |
| 154 | break; |
| 155 | case DESC_TYPE_QUALIFIER: |
| 156 | //getting this request means the host wants us to run at FULL speed... |
| 157 | pktSize = USB2DevQualDesc[0]; //bLength field |
| 158 | payload = (UCHAR*) USB2DevQualDesc; |
| 159 | //overwrite the CONFIG descriptor to point to the FULL speed version |
| 160 | USBDescriptors[USB_CONFIG_DESCRIPTOR & 0xFF].DesSize = (USB1ConfigDesc[2]) + (USB1ConfigDesc[3] << 8); //LSB + MSB |
| 161 | USBDescriptors[USB_CONFIG_DESCRIPTOR & 0xFF].pDesPayload = (UINT8_T *)USB1ConfigDesc; |
| 162 | break; |
| 163 | default: |
| 164 | //unhandled descriptor. set length to 0 |
| 165 | pktSize = 0; |
| 166 | break; |
| 167 | } // Endswitch |
| 168 | |
| 169 | //zero length means a valid descriptor was not found. |
| 170 | if(pktSize == 0) |
| 171 | { //unhandled descriptor. send a STALL PID |
| 172 | DWC3_EP0_STALL_AND_RESTART(pDCProps); |
| 173 | return; |
| 174 | } |
| 175 | |
| 176 | pDCProps->ctrl_direction = USB_OUT; |
| 177 | //3 stages |
| 178 | pDCProps->ctrl_stages = 3; |
| 179 | |
| 180 | //add EP0 TX dTD |
| 181 | pktSize = (pSetupPacket->wLength < pktSize) ? pSetupPacket->wLength : pktSize; |
| 182 | USB2D_Endpoint0Transmit(pDCProps, USB_ENDPOINT_0, |
| 183 | USB_IN, (UINT)(payload), pktSize, DWC3_TRBCTL_CONTROL_DATA); |
| 184 | |
| 185 | #ifndef DWC3_ENABLE_XFERNOTREADY |
| 186 | //add EP0 RX dTD: size = 0, this is for the status OUT token |
| 187 | //USB2D_Endpoint0Transmit(pDCProps, USB_ENDPOINT_0, USB_OUT, |
| 188 | // pDCProps->BufferSpace2, 0, DWC3_TRBCTL_CONTROL_STATUS3); |
| 189 | #endif |
| 190 | return; |
| 191 | } |
| 192 | void USB2D_SetAddress(P_DC_Properties_T pDCProps, P_XLLP_USB_SETUP_DATA_T pSetupPacket) |
| 193 | { |
| 194 | UINT reg; |
| 195 | |
| 196 | reg = DWC3_REG_READ(DWC3_DCFG); |
| 197 | reg &= ~(DWC3_DCFG_DEVADDR_MASK); |
| 198 | reg |= DWC3_DCFG_DEVADDR(pSetupPacket->wValue); |
| 199 | DWC3_REG_WRITE(DWC3_DCFG, reg); |
| 200 | |
| 201 | #ifndef DWC3_ENABLE_XFERNOTREADY |
| 202 | //send a zero length pckt to finish the Set Address |
| 203 | USB2D_Endpoint0Transmit(pDCProps, USB_ENDPOINT_0, USB_IN, |
| 204 | pDCProps->BufferSpace2, 0, DWC3_TRBCTL_CONTROL_STATUS2); |
| 205 | #endif |
| 206 | pDCProps->ctrl_direction = USB_IN; |
| 207 | pDCProps->ctrl_stages = 2; |
| 208 | |
| 209 | if (pSetupPacket->wValue) |
| 210 | pDCProps->dev_state = USB_STATE_ADDRESS; |
| 211 | else |
| 212 | pDCProps->dev_state = USB_STATE_DEFAULT; |
| 213 | } |
| 214 | |
| 215 | void USB2D_GetStatus(P_DC_Properties_T pDCProps, P_XLLP_USB_SETUP_DATA_T pSetupPacket) |
| 216 | { |
| 217 | usbstatus_value = 0x00000001; |
| 218 | //Reply with a "Self Powered" status |
| 219 | USB2D_Endpoint0Transmit(pDCProps, USB_ENDPOINT_0, USB_IN, |
| 220 | (UINT)(&usbstatus_value), 2, DWC3_TRBCTL_CONTROL_DATA); |
| 221 | |
| 222 | //add EP0 RX dTD: size = 0, this is for the status OUT token |
| 223 | //handled in DATA COMPLETE PHASE |
| 224 | //USB2D_Endpoint0Transmit(pDCProps, USB_ENDPOINT_0, USB_OUT, |
| 225 | // pDCProps->BufferSpace2, 0, DWC3_TRBCTL_CONTROL_STATUS3); |
| 226 | pDCProps->ctrl_direction = USB_OUT; |
| 227 | pDCProps->ctrl_stages = 3; |
| 228 | } |
| 229 | |
| 230 | void USB2D_SetConfig(P_DC_Properties_T pDCProps, P_XLLP_USB_SETUP_DATA_T pSetupPacket) |
| 231 | { |
| 232 | P_USBAPI_T p_usb; |
| 233 | |
| 234 | #ifndef DWC3_ENABLE_XFERNOTREADY |
| 235 | //send a zero length pckt to finish the Set Config |
| 236 | USB2D_Endpoint0Transmit(pDCProps, USB_ENDPOINT_0, USB_IN, |
| 237 | pDCProps->BufferSpace2, 0, DWC3_TRBCTL_CONTROL_STATUS2); |
| 238 | #endif |
| 239 | pDCProps->ctrl_direction = USB_IN; |
| 240 | pDCProps->ctrl_stages = 2; |
| 241 | |
| 242 | #if BOOTROM |
| 243 | //bootrom: check DOWNLOAD DISABLE fuse before allowing EP1 and 2 to be setup |
| 244 | if(GetTBREnvStruct()->Fuses.bits.Download_Disable) |
| 245 | return; |
| 246 | #endif |
| 247 | |
| 248 | //set the packet size based on speed: HI 512, FULL 64 |
| 249 | p_usb = GetUSBAPIhandle_InterruptNum(pDCProps->InterruptNum); |
| 250 | if(p_usb != NULL) |
| 251 | { |
| 252 | #if 0 |
| 253 | p_usb->maxpacketsize = (pDCProps->pUSBRegs->PORTSC & BIT27) ? 512 : 64; |
| 254 | #endif |
| 255 | //TODO: set it as 512 even for full speed as the buffer in PM manager is 1024 |
| 256 | if (USB_MODE_FS == DWC3_GET_CONN_SPEED()) |
| 257 | p_usb->maxpacketsize = 64; |
| 258 | else |
| 259 | p_usb->maxpacketsize = 512; |
| 260 | |
| 261 | //set the packet size based on speed: HI 512, FULL 64 |
| 262 | //GetUSBAPIhandle_InterruptNum(pDCProps->InterruptNum)->maxpacketsize = (pDCProps->pUSBRegs->PORTSC & BIT27) ? 512 : 64; |
| 263 | |
| 264 | //enable EP's based on the Config Table |
| 265 | USB2D_Endpoint_Setup(pDCProps, USB_ENDPOINT_A, USB_OUT, USB_BULK); |
| 266 | USB2D_Endpoint_Setup(pDCProps, USB_ENDPOINT_A, USB_IN, USB_BULK); |
| 267 | pDCProps->dev_state = USB_STATE_CONFIGURED; |
| 268 | //prime EP2 for Preamble |
| 269 | USB2D_EndpointTransmit( pDCProps, |
| 270 | USB_ENDPOINT_A, |
| 271 | USB_OUT, |
| 272 | (UINT)(pDCProps->BufferSpace), |
| 273 | p_usb->maxpacketsize); |
| 274 | } |
| 275 | } |
| 276 | |
| 277 | |
| 278 | //Vendor Request Setup Packet |
| 279 | void USB2D_VendorRequest(P_DC_Properties_T pDCProps, P_XLLP_USB_SETUP_DATA_T pSetupPacket) |
| 280 | { |
| 281 | UCHAR * NoVendorString = "NoVendorString"; |
| 282 | UINT pktSize, retval; |
| 283 | void * pPayload; |
| 284 | |
| 285 | retval = FindVendorRequestInTIM (pSetupPacket->bRequest, pSetupPacket->bmRequestType, (UINT *)&pPayload, &pktSize); |
| 286 | |
| 287 | if(retval != NoError) |
| 288 | { |
| 289 | pktSize = 15;//sizeof(ci2NoVendorString); |
| 290 | pPayload = NoVendorString; |
| 291 | } |
| 292 | |
| 293 | pktSize = (pSetupPacket->wLength < pktSize) ? pSetupPacket->wLength : pktSize; |
| 294 | |
| 295 | //add EP0 TX dTD |
| 296 | pktSize = (pSetupPacket->wLength < pktSize) ? pSetupPacket->wLength : pktSize; |
| 297 | USB2D_Endpoint0Transmit(pDCProps, USB_ENDPOINT_0, USB_IN, |
| 298 | (UINT)(pPayload), pktSize, DWC3_TRBCTL_CONTROL_DATA); |
| 299 | |
| 300 | pDCProps->ctrl_direction = USB_OUT; |
| 301 | pDCProps->ctrl_stages = 3; |
| 302 | return; |
| 303 | } |
| 304 | |
| 305 | |
| 306 | |