aboutsummaryrefslogtreecommitdiffstats
path: root/firmware/fx3/b200/bootloader/usb_boot.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/fx3/b200/bootloader/usb_boot.c')
-rw-r--r--firmware/fx3/b200/bootloader/usb_boot.c807
1 files changed, 807 insertions, 0 deletions
diff --git a/firmware/fx3/b200/bootloader/usb_boot.c b/firmware/fx3/b200/bootloader/usb_boot.c
new file mode 100644
index 000000000..ba7eb9dfb
--- /dev/null
+++ b/firmware/fx3/b200/bootloader/usb_boot.c
@@ -0,0 +1,807 @@
+//
+// Copyright 2011-2012 Cypress Semiconductor Corporation
+// Copyright 2019 Ettus Research, a National Instruments Brand
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+
+#include "cyfx3usb.h"
+#include "cyfx3device.h"
+#include "cyfx3utils.h"
+#include "cyfx3i2c.h"
+
+#include "common_helpers.h"
+#include "common_descriptors.h"
+#include "usb_descriptors.h"
+
+typedef enum
+{
+ eStall = 0, /* Send STALL */
+ eDataIn, /* Data IN Stage */
+ eDataOut, /* Data Out Stage */
+ eStatus /* Status Stage */
+} eUsbStage;
+
+typedef int (*PFI)();
+
+#define USB_SETUP_DIR (0x80) /* 0x80 = To Host */
+#define USB_SETUP_MASK (0x60) /* Used to mask off request type */
+#define USB_STANDARD_REQUEST (0x00) /* Standard Request */
+#define USB_VENDOR_REQUEST (0x40) /* Vendor Request */
+#define USB_REQ_MASK (0x3F) /* USB Request mask */
+#define USB_REQ_DEV (0) /* Device Request */
+#define USB_REQ_INTERFACE (1) /* Interface Request */
+#define USB_REQ_ENDPOINT (2) /* Endpoint Request */
+#define USB_SET_INTERFACE (11)
+#define USB_SC_SET_SEL (0x30) /* Set system exit latency. */
+#define USB_SC_SET_ISOC_DELAY (0x31)
+
+#define SELF_POWERED (0x01)
+#define REMOTE_WAKEUP (0x02)
+#define U1_ENABLE (0x04)
+#define U2_ENABLE (0x08)
+#define LTM_ENABLE (0x10)
+
+uint8_t glUsbState = 0;
+uint8_t gConfig = 0; /* Variable to hold the config info. */
+uint8_t gAltSetting = 0; /* Variable to hold the interface info. */
+uint8_t gUsbDevStatus = 0;
+uint8_t glCheckForDisconnect = 0;
+uint8_t glInCompliance = 0;
+
+/* 4KB of buffer area used for control endpoint transfers. */
+#define gpUSBData (uint8_t*)(0x40077000)
+#define USB_DATA_BUF_SIZE (1024*4)
+
+CyU3PUsbDescrPtrs *gpUsbDescPtr; /* Pointer to the USB Descriptors */
+CyFx3BootUsbEp0Pkt_t gEP0;
+
+void myMemCopy(uint8_t* d, uint8_t* s, int32_t cnt)
+{
+ int32_t i;
+ for (i = 0; i < cnt; i++) {
+ *d++ = *s++;
+ }
+}
+
+void myMemSet(uint8_t* d, uint8_t c, int32_t cnt)
+{
+ int32_t i;
+ for (i = 0; i < cnt; i++) {
+ *d++ = c;
+ }
+}
+
+/************************************************
+ * Request handlers
+ ***********************************************/
+
+/* Function to handle the GET_STATUS Standard request. */
+int getStatus (void)
+{
+ uint16_t data = 0;
+
+ switch (gEP0.bmReqType & USB_REQ_MASK)
+ {
+ case USB_REQ_DEV:
+ if (CyFx3BootUsbGetSpeed () == CY_FX3_BOOT_SUPER_SPEED)
+ {
+ data = (gpUsbDescPtr->usbSSConfigDesc_p[7] & 0x40) ? 1 : 0;
+ data |= gUsbDevStatus;
+ }
+ else
+ {
+ data = (gpUsbDescPtr->usbHSConfigDesc_p[7] & 0x40) ? 1 : 0;
+ data |= gUsbDevStatus;
+ }
+ break;
+
+ case USB_REQ_INTERFACE:
+ if (!gConfig)
+ {
+ return eStall;
+ }
+ break;
+
+ case USB_REQ_ENDPOINT:
+ if (CyFx3BootUsbGetEpCfg (gEP0.bIdx0, 0, (CyBool_t *)&data) != 0)
+ {
+ return eStall;
+ }
+ break;
+ default:
+ return eStall;
+ }
+
+ *(uint16_t*)gEP0.pData = data;
+ return eDataIn;
+}
+
+/* Function to handle the GET_DESCRIPTOR Standard request */
+int getDescriptor (void)
+{
+ uint32_t len = 0;
+ uint8_t *p = 0;
+ uint8_t *cfg_p = 0;
+ uint8_t usbSpeed;
+
+ usbSpeed = CyFx3BootUsbGetSpeed();
+
+ gpUsbDescPtr->usbHSConfigDesc_p[1] = CY_U3P_USB_CONFIG_DESCR;
+ gpUsbDescPtr->usbFSConfigDesc_p[1] = CY_U3P_USB_CONFIG_DESCR;
+
+ if (usbSpeed == CY_FX3_BOOT_HIGH_SPEED)
+ {
+ cfg_p = (uint8_t*)gpUsbDescPtr->usbHSConfigDesc_p;
+ len = ((gpUsbDescPtr->usbHSConfigDesc_p[3] << 8) | gpUsbDescPtr->usbHSConfigDesc_p[2]);
+ }
+ else if (usbSpeed == CY_FX3_BOOT_SUPER_SPEED)
+ {
+ cfg_p = (uint8_t*)gpUsbDescPtr->usbSSConfigDesc_p;
+ len = ((gpUsbDescPtr->usbSSConfigDesc_p[3] << 8) | gpUsbDescPtr->usbSSConfigDesc_p[2]);
+ }
+ else if (usbSpeed == CY_FX3_BOOT_FULL_SPEED)
+ {
+ cfg_p = (uint8_t*)gpUsbDescPtr->usbFSConfigDesc_p;
+ len = ((gpUsbDescPtr->usbFSConfigDesc_p[3] << 8) | gpUsbDescPtr->usbFSConfigDesc_p[2]);
+ }
+
+ switch (gEP0.bVal1)
+ {
+ case CY_U3P_USB_DEVICE_DESCR:
+ {
+ if ((usbSpeed == CY_FX3_BOOT_HIGH_SPEED) || (usbSpeed == CY_FX3_BOOT_FULL_SPEED))
+ {
+ p = (uint8_t*)gpUsbDescPtr->usbDevDesc_p;
+ len = gpUsbDescPtr->usbDevDesc_p[0];
+ }
+ else if (usbSpeed == CY_FX3_BOOT_SUPER_SPEED)
+ {
+ p = (uint8_t*)gpUsbDescPtr->usbSSDevDesc_p;
+ len = gpUsbDescPtr->usbSSDevDesc_p[0];
+ }
+ break;
+ }
+ case CY_U3P_BOS_DESCR:
+ {
+ p = (uint8_t *)gpUsbDescPtr->usbSSBOSDesc_p;
+ len = (gpUsbDescPtr->usbSSBOSDesc_p[3] << 8) | gpUsbDescPtr->usbSSBOSDesc_p[2];
+ break;
+ }
+ case CY_U3P_USB_CONFIG_DESCR:
+ {
+ p = cfg_p;
+ break;
+ }
+ case CY_U3P_USB_DEVQUAL_DESCR:
+ {
+ if ((usbSpeed == CY_FX3_BOOT_HIGH_SPEED) || (usbSpeed == CY_FX3_BOOT_FULL_SPEED))
+ {
+ p = (uint8_t*)gpUsbDescPtr->usbDevQualDesc_p;
+ len = gpUsbDescPtr->usbDevQualDesc_p[0];
+ break;
+ }
+ return eStall;
+ }
+ case CY_U3P_USB_STRING_DESCR:
+ {
+ /* Ensure that we do not index past the limit of the array. */
+ if (gEP0.bVal0 < CY_FX3_USB_MAX_STRING_DESC_INDEX)
+ {
+ p = (uint8_t*)gpUsbDescPtr->usbStringDesc_p[gEP0.bVal0];
+ if (p != 0)
+ len = p[0];
+ }
+ else
+ return eStall;
+ break;
+ }
+ case CY_U3P_USB_OTHERSPEED_DESCR:
+ {
+ if (usbSpeed == CY_FX3_BOOT_HIGH_SPEED)
+ {
+ gpUsbDescPtr->usbFSConfigDesc_p[1] = CY_U3P_USB_OTHERSPEED_DESCR;
+ p = (uint8_t*)gpUsbDescPtr->usbFSConfigDesc_p;
+
+ len = ((gpUsbDescPtr->usbFSConfigDesc_p[3] < 8) | gpUsbDescPtr->usbFSConfigDesc_p[2]);
+
+ if (len > gEP0.wLen)
+ {
+ len = gEP0.wLen;
+ }
+ }
+ else if (usbSpeed == CY_FX3_BOOT_FULL_SPEED)
+ {
+ gpUsbDescPtr->usbHSConfigDesc_p[1] = CY_U3P_USB_OTHERSPEED_DESCR;
+ p = (uint8_t*)gpUsbDescPtr->usbHSConfigDesc_p;
+ len = ((gpUsbDescPtr->usbHSConfigDesc_p[3] < 8) | gpUsbDescPtr->usbHSConfigDesc_p[2]);
+
+ if (len > gEP0.wLen)
+ {
+ len = gEP0.wLen;
+ }
+ }
+ }
+ break;
+ default:
+ {
+ return eStall;
+ }
+ }
+
+ if (p != 0)
+ {
+ myMemCopy (gpUSBData, p, len);
+ if (gEP0.wLen > len)
+ {
+ gEP0.wLen = len;
+ }
+
+ return eDataIn;
+ }
+ else
+ /* Stall EP0 if the descriptor sought is not available. */
+ return eStall;
+}
+
+/* Function to handle the SET_CONFIG Standard request */
+int setConfig (void)
+{
+ uint8_t usbSpeed = 0;
+ uint32_t retVal = 0;
+ CyFx3BootUsbEpConfig_t epCfg;
+
+ if ((gEP0.bVal0 == 0) || (gEP0.bVal0 == 1))
+ {
+ glUsbState = gEP0.bVal0;
+ gConfig = gEP0.bVal0;
+
+ /* Get the Bus speed */
+ usbSpeed = CyFx3BootUsbGetSpeed();
+
+ epCfg.pcktSize = 512;
+ /* Based on the Bus Speed configure the endpoint packet size */
+ if (usbSpeed == CY_FX3_BOOT_HIGH_SPEED)
+ {
+ epCfg.pcktSize = 512;
+ }
+ if (usbSpeed == CY_FX3_BOOT_SUPER_SPEED)
+ {
+ epCfg.pcktSize = 1024;
+ }
+ if (usbSpeed == CY_FX3_BOOT_FULL_SPEED)
+ {
+ epCfg.pcktSize = 64;
+ }
+
+ /* Producer Endpoint configuration */
+ epCfg.enable = 1;
+ epCfg.epType = CY_FX3_BOOT_USB_EP_BULK;
+ epCfg.burstLen = 1;
+ epCfg.streams = 0;
+ epCfg.isoPkts = 0;
+
+ /* Configure the Endpoint */
+ retVal = CyFx3BootUsbSetEpConfig(0x01, &epCfg);
+ if (retVal != 0)
+ {
+ /* TODO: Error Handling */
+ return eStall;
+ }
+
+ /* Consumer Endpoint configuration */
+ epCfg.enable = 1;
+ epCfg.epType = CY_FX3_BOOT_USB_EP_BULK;
+ epCfg.burstLen = 1;
+ epCfg.streams = 0;
+ epCfg.isoPkts = 0;
+
+ /* Configure the Endpoint */
+ retVal = CyFx3BootUsbSetEpConfig (0x81, &epCfg);
+ if (retVal != 0)
+ {
+ /* TODO: Error Handling */
+ return eStall;
+ }
+
+ return eStatus;
+ }
+
+ return eStall;
+}
+
+/* Function to handle the GET_INTERFACE Standard request */
+int getInterface (void)
+{
+ if (gConfig == 0)
+ {
+ return eStall;
+ }
+
+ gEP0.pData = (uint8_t *)&gAltSetting;
+ return eDataIn;
+}
+
+/* Function to handle the SET_INTERFACE Standard request */
+int setInterface (void)
+{
+ gAltSetting = gEP0.bVal0;
+ return eStatus;
+}
+
+/* This function returns stall for not supported requests. */
+int stall (void)
+{
+ return eStall;
+}
+
+/* Function to handle the SET_ADDRESS Standard request. */
+int setAddress (void)
+{
+ return eStatus;
+}
+
+/* Function to handle the CLEAR_FEATURE Standard request. */
+int clearFeature (void)
+{
+ /* All of the actual handling for the CLEAR_FEATURE request is done in the API.
+ We only need to update the device status flags here.
+ */
+ if (CyFx3BootUsbSetClrFeature (0, (CyBool_t)glUsbState, &gEP0) != 0)
+ {
+ return eStall;
+ }
+
+ if (gEP0.bmReqType == USB_REQ_DEV)
+ {
+ /* Update the device status flags as required. */
+ if (CyFx3BootUsbGetSpeed () == CY_FX3_BOOT_SUPER_SPEED)
+ {
+ switch (gEP0.bVal0)
+ {
+ case 48:
+ gUsbDevStatus &= ~U1_ENABLE;
+ break;
+ case 49:
+ gUsbDevStatus &= ~U2_ENABLE;
+ break;
+ case 50:
+ gUsbDevStatus &= ~LTM_ENABLE;
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ if (gEP0.bVal0 == 1)
+ {
+ gUsbDevStatus &= ~REMOTE_WAKEUP;
+ }
+ }
+ }
+
+ return eStatus;
+}
+
+/* Function to handle the SET_FEATURE Standard request. */
+int setFeature (void)
+{
+ /* All of the actual handling for the SET_FEATURE command is done in the API.
+ * We only need to update the device status flags here.
+ */
+ if (CyFx3BootUsbSetClrFeature (1, (CyBool_t)glUsbState, &gEP0) != 0)
+ {
+ return eStall;
+ }
+
+ if (gEP0.bmReqType == USB_REQ_DEV)
+ {
+ /* Update the device status flags as required. */
+ if (CyFx3BootUsbGetSpeed () == CY_FX3_BOOT_SUPER_SPEED)
+ {
+ switch (gEP0.bVal0)
+ {
+ case 48:
+ gUsbDevStatus |= U1_ENABLE;
+ break;
+ case 49:
+ gUsbDevStatus |= U2_ENABLE;
+ break;
+ case 50:
+ gUsbDevStatus |= LTM_ENABLE;
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ if (gEP0.bVal0 == 1)
+ {
+ gUsbDevStatus |= REMOTE_WAKEUP;
+ }
+ }
+ }
+ return eStatus;
+}
+
+/* Function to handle the GET_CONFIG Standard request. */
+int getConfig (void)
+{
+ gEP0.pData = (uint8_t *)&gConfig;
+ return eDataIn;
+}
+
+const PFI chapter9_cmds[] =
+{
+ getStatus, /* USB_GET_STATUS 0 */
+ clearFeature, /* USB_CLEAR_FEATURE 1 */
+ stall, /* Reserved 2 */
+ setFeature, /* USB_SET_FEATURE 3 */
+ stall, /* Reserved 4 */
+ setAddress, /* USB_SET_ADDRESS 5 */
+ getDescriptor, /* USB_GET_DESCRIPTOR 6 */
+ stall, /* USB_SET_DESCRIPTOR 7 */
+ getConfig, /* USB_GET_CONFIGURATION 8 */
+ setConfig, /* USB_SET_CONFIGURATION 9 */
+ getInterface, /* USB_GET_INTERFACE 10 */
+ setInterface, /* USB_SET_INTERFACE 11 */
+};
+
+/* This function validates the addresses being written to/read from
+ Return Value:
+ 0 - Address is valid
+ -1 - Address is not valid
+*/
+int checkAddress (uint32_t address, uint32_t len)
+{
+ if (address & 3)
+ {
+ /* expect long word boundary */
+ return -1;
+ }
+
+ len += address;
+
+ if ((address >= CY_FX3_BOOT_SYSMEM_BASE1) && (len <= CY_FX3_BOOT_SYSMEM_END))
+ {
+ return 0;
+ }
+
+ if (len <= CY_FX3_BOOT_ITCM_END)
+ {
+ return 0;
+ }
+
+ return -1;
+}
+
+/* Function to handle the vendor commands. */
+void vendorCmdHandler (void)
+{
+ int stage;
+ int status;
+ uint32_t address = ((gEP0.bIdx1 << 24) | (gEP0.bIdx0 << 16) | (gEP0.bVal1 << 8) | (gEP0.bVal0));
+ uint16_t len = gEP0.wLen;
+ uint16_t bReq = gEP0.bReq;
+ uint16_t dir = gEP0.bmReqType & USB_SETUP_DIR;
+
+ if (len > USB_DATA_BUF_SIZE)
+ {
+ CyFx3BootUsbStall (0, CyTrue, CyFalse);
+ return;
+ }
+
+ if (dir)
+ {
+ stage = eDataIn;
+ }
+ else
+ {
+ stage = eDataOut;
+ }
+
+ /* Vendor Command 0xA0 handling */
+ if (bReq == 0xA0)
+ {
+ /* Note: This is a command issued by the CyControl Application to detect the legacy products.
+ As we are an FX3 device we stall the endpoint to indicate that this is not a legacy device.
+ */
+ if (address == 0xE600)
+ {
+ /* Stall the Endpoint */
+ CyFx3BootUsbStall (0, CyTrue, CyFalse);
+ return;
+ }
+
+ status = checkAddress (address, len);
+ if (len == 0)
+ {
+ /* Mask the USB Interrupts and Disconnect the USB Phy. */
+ CyFx3BootUsbConnect (CyFalse, CyTrue);
+ /* Transfer to Program Entry */
+ CyFx3BootJumpToProgramEntry (address);
+ return;
+ }
+
+ if (status < 0)
+ {
+ /* Stall the endpoint */
+ CyFx3BootUsbStall (0, CyTrue, CyFalse);
+ return;
+ }
+
+ /* Validate the SYSMEM address being accessed */
+ if ((address >= CY_FX3_BOOT_SYSMEM_BASE1) && (address < CY_FX3_BOOT_SYSMEM_END))
+ {
+ gEP0.pData = (uint8_t*)address;
+ }
+
+ CyFx3BootUsbAckSetup ();
+
+ if (eDataIn == stage)
+ {
+ if ((address + gEP0.wLen) <= CY_FX3_BOOT_ITCM_END)
+ {
+ myMemCopy(gEP0.pData, (uint8_t *)address , len);
+ }
+
+ status = CyFx3BootUsbDmaXferData (0x80, (uint32_t)gEP0.pData, gEP0.wLen, CY_FX3_BOOT_WAIT_FOREVER);
+ if (status != CY_FX3_BOOT_SUCCESS)
+ {
+ /* USB DMA Transfer failed. Stall the Endpoint. */
+ CyFx3BootUsbStall (0, CyTrue, CyFalse);
+ return;
+ }
+ }
+ else if (stage == eDataOut)
+ {
+ status = CyFx3BootUsbDmaXferData (0x00, (uint32_t)gEP0.pData, gEP0.wLen, CY_FX3_BOOT_WAIT_FOREVER);
+ if (status != CY_FX3_BOOT_SUCCESS)
+ {
+ /* USB DMA Transfer failed. Stall the Endpoint. */
+ CyFx3BootUsbStall (0, CyTrue, CyFalse);
+ return;
+ }
+
+ /* Validate ITCM Memory */
+ if ((address + gEP0.wLen) <= CY_FX3_BOOT_ITCM_END)
+ {
+ /* Avoid writing to the interrupt table. */
+ if (address < 0xFF) {
+ gEP0.pData += 0xFF-address;
+ gEP0.wLen -= 0xFF-address;
+ address = 0xFF;
+ }
+ myMemCopy((uint8_t *)address, gEP0.pData, gEP0.wLen);
+ }
+ }
+ return;
+ }
+
+ /* Version request */
+ if (dir && bReq == 0xB8) {
+ uint8_t version_info[] = {1, 21, 0, 0, 0, 0};
+
+ CyFx3BootUsbAckSetup ();
+ status = CyFx3BootUsbDmaXferData (0x80, (uint32_t)version_info,
+ sizeof(version_info), CY_FX3_BOOT_WAIT_FOREVER);
+ if (status != CY_FX3_BOOT_SUCCESS) {
+ /* USB DMA Transfer failed. Stall the Endpoint. */
+ CyFx3BootUsbStall (0, CyTrue, CyFalse);
+ }
+
+ return;
+ }
+
+ /* Stall the Endpoint */
+ CyFx3BootUsbStall (0, CyTrue, CyFalse);
+ return;
+}
+
+/* Setup Data handler */
+void setupDataHandler (uint32_t setupDat0, uint32_t setupDat1)
+{
+ uint32_t *p;
+ int status = eStall;
+
+ p = (uint32_t*)&gEP0;
+ p[0] = setupDat0;
+ p[1] = setupDat1;
+
+ gEP0.pData = gpUSBData;
+
+ switch (gEP0.bmReqType & USB_SETUP_MASK)
+ {
+ case USB_STANDARD_REQUEST:
+ if (gEP0.bReq <= USB_SET_INTERFACE)
+ {
+ status = (*chapter9_cmds[gEP0.bReq])();
+ }
+ else
+ {
+ if (gEP0.bReq == USB_SC_SET_SEL)
+ {
+ if ((CyFx3BootUsbGetSpeed () == CY_FX3_BOOT_SUPER_SPEED) && (gEP0.bIdx0 == 0) &&
+ (gEP0.bIdx1 == 0) && (gEP0.bVal0 == 0) && (gEP0.bVal1 == 0) && (gEP0.wLen == 6))
+ {
+ gEP0.wLen = 32;
+ status = eDataOut;
+ }
+ else
+ {
+ status = eStall;
+ }
+ }
+ else if (gEP0.bReq == USB_SC_SET_ISOC_DELAY)
+ {
+ status = eStatus;
+ if ((CyFx3BootUsbGetSpeed () != CY_FX3_BOOT_SUPER_SPEED) || (gEP0.bIdx0 != 0) ||
+ (gEP0.bIdx1 != 0) || (gEP0.wLen != 0))
+ {
+ status = eStall;
+ }
+ }
+ else
+ {
+ status = eStall;
+ }
+ }
+ break;
+
+ case USB_VENDOR_REQUEST:
+ vendorCmdHandler();
+ return;
+ }
+
+ switch (status)
+ {
+ case eDataIn:
+ CyFx3BootUsbAckSetup ();
+ status = CyFx3BootUsbDmaXferData (0x80, (uint32_t)gEP0.pData, gEP0.wLen, 1000);
+ if (status != CY_FX3_BOOT_SUCCESS)
+ {
+ CyFx3BootUsbStall (0, CyTrue, CyFalse);
+ }
+ break;
+ case eDataOut:
+ CyFx3BootUsbAckSetup ();
+ status = CyFx3BootUsbDmaXferData (0x00, (uint32_t)gEP0.pData, gEP0.wLen, CY_FX3_BOOT_WAIT_FOREVER);
+ if (status != CY_FX3_BOOT_SUCCESS)
+ {
+ CyFx3BootUsbStall (0, CyTrue, CyFalse);
+ }
+ break;
+ case eStatus:
+ CyFx3BootUsbAckSetup ();
+ break;
+ default:
+ CyFx3BootUsbStall (0, CyTrue, CyFalse);
+ return;
+ }
+
+ return;
+}
+
+/* USB Event Handler. This function is invoked from the USB ISR and as such MUST not be
+ blocked.
+*/
+void usbEventCallback (CyFx3BootUsbEventType_t event)
+{
+ if (event == CY_FX3_BOOT_USB_RESET)
+ {
+ gConfig = 0;
+ gAltSetting = 0;
+ gUsbDevStatus = 0;
+ glUsbState = 0;
+ glInCompliance = 0;
+ }
+
+ if ((event == CY_FX3_BOOT_USB_CONNECT) ||
+ (event == CY_FX3_BOOT_USB_DISCONNECT))
+ {
+ glUsbState = 0;
+ gUsbDevStatus = 0;
+ }
+
+ if (event == CY_FX3_BOOT_USB_IN_SS_DISCONNECT)
+ {
+ glCheckForDisconnect = CyTrue;
+ }
+
+ if (event == CY_FX3_BOOT_USB_COMPLIANCE)
+ {
+ glInCompliance = CyTrue;
+ }
+
+ return;
+}
+
+/* Function passed to common EEPROM functions to access the EEPROM */
+void eeprom_read(uint16_t addr, uint8_t* buffer, uint8_t length)
+{
+ CyFx3BootI2cPreamble_t preamble;
+ preamble.length = 4;
+ preamble.buffer[0] = 0xA0;
+ preamble.buffer[1] = addr >> 8;
+ preamble.buffer[2] = addr & 0xFF;
+ preamble.buffer[3] = 0xA1;
+ preamble.ctrlMask = 0x0004;
+ CyFx3BootI2cReceiveBytes(&preamble, buffer, length, 0);
+}
+
+/* USB initialization */
+void usbBoot()
+{
+ /* Reset globals */
+ gConfig = 0;
+ gAltSetting = 0;
+ gUsbDevStatus = 0;
+ glUsbState = 0;
+ glCheckForDisconnect = 0;
+ glInCompliance = 0;
+
+ /* Init */
+ CyFx3BootUsbStart (CyFalse, usbEventCallback);
+
+ /* Run USB circuitry off of host power, not internal power. */
+ CyFx3BootUsbVBattEnable (CyFalse);
+
+ /* Register callbacks */
+ CyFx3BootRegisterSetupCallback (setupDataHandler);
+
+ /* Enable I2C for EEPROM access */
+ CyFx3BootI2cInit();
+ CyFx3BootI2cConfig_t i2cCfg = {
+ .bitRate = 100000,
+ .isDma = CyFalse,
+ .busTimeout = 0xFFFFFFFF,
+ .dmaTimeout = 0xFFFF};
+ CyFx3BootI2cSetConfig(&i2cCfg);
+
+ /* Retrieve VID and PID from EEPROM */
+ const uint16_t vid = get_vid(&eeprom_read);
+ const uint16_t pid = get_pid(&eeprom_read);
+
+ /* Power down I2C */
+ CyFx3BootI2cDeInit();
+
+ /* Populate device descriptors with IDs */
+ common_usb2_dev_desc[8] = vid & 0xFF;
+ common_usb2_dev_desc[9] = vid >> 8;
+ common_usb2_dev_desc[10] = pid & 0xFF;
+ common_usb2_dev_desc[11] = pid >> 8;
+
+ common_usb3_dev_desc[8] = vid & 0xFF;
+ common_usb3_dev_desc[9] = vid >> 8;
+ common_usb3_dev_desc[10] = pid & 0xFF;
+ common_usb3_dev_desc[11] = pid >> 8;
+
+ /* Copy all descriptors */
+ CyFx3BootUsbSetDesc(
+ CY_U3P_USB_SET_HS_DEVICE_DESCR, 0, (uint8_t*)common_usb2_dev_desc);
+ CyFx3BootUsbSetDesc(
+ CY_U3P_USB_SET_SS_DEVICE_DESCR, 0, (uint8_t*)common_usb3_dev_desc);
+
+ CyFx3BootUsbSetDesc(CY_U3P_USB_SET_DEVQUAL_DESCR, 0, (uint8_t*)common_dev_qual_desc);
+
+ CyFx3BootUsbSetDesc(CY_U3P_USB_SET_HS_CONFIG_DESCR, 0, (uint8_t*)bl_hs_config_desc);
+ CyFx3BootUsbSetDesc(CY_U3P_USB_SET_FS_CONFIG_DESCR, 0, (uint8_t*)bl_fs_config_desc);
+ CyFx3BootUsbSetDesc(CY_U3P_USB_SET_SS_CONFIG_DESCR, 0, (uint8_t*)bl_ss_config_desc);
+
+ CyFx3BootUsbSetDesc(CY_U3P_USB_SET_SS_BOS_DESCR, 0, (uint8_t*)common_usb_bos_desc);
+
+ CyFx3BootUsbSetDesc(
+ CY_U3P_USB_SET_STRING_DESCR, 0, (uint8_t*)common_string_lang_id_desc);
+
+ CyFx3BootUsbSetDesc(CY_U3P_USB_SET_STRING_DESCR, 1, (uint8_t*)bl_manufacturer_desc);
+ CyFx3BootUsbSetDesc(CY_U3P_USB_SET_STRING_DESCR, 2, (uint8_t*)bl_product_desc);
+ CyFx3BootUsbSetDesc(CY_U3P_USB_SET_STRING_DESCR, 3, (uint8_t*)bl_dev_serial_desc);
+
+ gpUsbDescPtr = CyFx3BootUsbGetDesc();
+
+ /* Connect! */
+ CyFx3BootUsbConnect (CyTrue, CyTrue);
+}
+