/* Initalizes the mouse driver. */ CyU3PReturnStatus_t CyFxMouseDriverInit () { uint16_t length, size, interval; CyU3PReturnStatus_t status; CyU3PUsbHostEpConfig_t epCfg; CyU3PDmaChannelConfig_t dmaCfg; /* Read first four bytes of configuration descriptor to determine * the total length. */ status = CyFxSendSetupRqt (0x80, CY_U3P_USB_SC_GET_DESCRIPTOR, (CY_U3P_USB_CONFIG_DESCR << 8), 0, 4, glEp0Buffer); if (status != CY_U3P_SUCCESS) { goto enum_error; } /* Identify the length of the data received. */ length = CY_U3P_MAKEWORD(glEp0Buffer[3], glEp0Buffer[2]); if (length > CY_FX_HOST_EP0_BUFFER_SIZE) { goto enum_error; } /* Read the full configuration descriptor. */ status = CyFxSendSetupRqt (0x80, CY_U3P_USB_SC_GET_DESCRIPTOR, (CY_U3P_USB_CONFIG_DESCR << 8), 0, length, glEp0Buffer); if (status != CY_U3P_SUCCESS) { goto enum_error; } /* Save the required information. */ glHostMouseEp = glEp0Buffer[29]; size = CY_U3P_MAKEWORD(glEp0Buffer[32], glEp0Buffer[31]); interval = glEp0Buffer[33]; /* Set the new configuration. */ status = CyFxSendSetupRqt (0x00, CY_U3P_USB_SC_SET_CONFIGURATION, 1, 0, 0, glEp0Buffer); if (status != CY_U3P_SUCCESS) { goto enum_error; } /* Set the report mode to idle so that report is sent only * when there is active data. */ status = CyFxSendSetupRqt (0x21, 0x0A, 0, 0, 0, glEp0Buffer); #if 0 /* It does not matter even if the request gets stalled. */ if (status != CY_U3P_SUCCESS) { goto enum_error; } #endif /* Initialize the HID mouse. */ CyU3PMemSet ((uint8_t *)&epCfg, 0, sizeof(epCfg)); epCfg.type = CY_U3P_USB_EP_INTR; epCfg.mult = 1; epCfg.maxPktSize = size; interval = (1 << (interval - 1)) / 8; if (interval > 255) { interval = 255; } epCfg.pollingRate = interval; /* Since DMA buffer sizes can only be multiple of 16 bytes and * also since this is an interrupt endpoint where the max data * packet size is same as the maxPktSize field, the fullPktSize * has to be a multiple of 16 bytes. */ size = ((size + 0x0F) & ~0x0F); epCfg.fullPktSize = size; /* Since the IN token has to be sent out continously, it * is easier to enable the stream mode. Otherwise we will * have to maintain the timing. */ epCfg.isStreamMode = CyTrue; status = CyU3PUsbHostEpAdd (glHostMouseEp, &epCfg); if (status != CY_U3P_SUCCESS) { goto enum_error; } /* Create a DMA channel for this EP. */ CyU3PMemSet ((uint8_t *)&dmaCfg, 0, sizeof(dmaCfg)); dmaCfg.size = size; dmaCfg.count = CY_FX_HOST_DMA_BUF_COUNT; dmaCfg.prodSckId = (CyU3PDmaSocketId_t)(CY_U3P_UIB_SOCKET_PROD_0 + (0x0F & glHostMouseEp)); dmaCfg.consSckId = CY_U3P_CPU_SOCKET_CONS; dmaCfg.dmaMode = CY_U3P_DMA_MODE_BYTE; dmaCfg.notification = CY_U3P_DMA_CB_PROD_EVENT; dmaCfg.cb = CyFxMouseDmaCb; dmaCfg.prodHeader = 0; dmaCfg.prodFooter = 0; dmaCfg.consHeader = 0; dmaCfg.prodAvailCount = 0; status = CyU3PDmaChannelCreate (&glHostMouseCh, CY_U3P_DMA_TYPE_MANUAL_IN, &dmaCfg); if (status != CY_U3P_SUCCESS) { goto app_error; } /* Enable EP transfer. In stream mode, the transfer size should be zero. */ status = CyU3PUsbHostEpSetXfer (glHostMouseEp, CY_U3P_USB_HOST_EPXFER_NORMAL, 0); if (status != CY_U3P_SUCCESS) { goto app_error; } /* Set for infinite transfer. */ status = CyU3PDmaChannelSetXfer (&glHostMouseCh, 0); if (status != CY_U3P_SUCCESS) { goto app_error; } CyU3PDebugPrint (4, "USB HID Mouse driver initialized successfully.\r\n"); return CY_U3P_SUCCESS; app_error: CyU3PDmaChannelDestroy (&glHostMouseCh); if (glHostMouseEp != 0) { CyU3PUsbHostEpRemove (glHostMouseEp); glHostMouseEp = 0; } enum_error: return CY_U3P_ERROR_FAILURE; }
/* This function initializes the mouse driver application. */ void CyFxApplnStart () { uint16_t length; CyU3PReturnStatus_t status; CyU3PUsbHostEpConfig_t epCfg; /* Add EP0 to the scheduler. */ CyU3PMemSet ((uint8_t *)&epCfg, 0, sizeof(epCfg)); epCfg.type = CY_U3P_USB_EP_CONTROL; epCfg.mult = 1; /* Start off with 8 byte EP0 packet size. */ epCfg.maxPktSize = 8; epCfg.pollingRate = 0; epCfg.fullPktSize = 8; epCfg.isStreamMode = CyFalse; status = CyU3PUsbHostEpAdd (0, &epCfg); if (status != CY_U3P_SUCCESS) { goto enum_error; } CyU3PThreadSleep (100); /* Get the device descriptor. */ status = CyFxSendSetupRqt (0x80, CY_U3P_USB_SC_GET_DESCRIPTOR, (CY_U3P_USB_DEVICE_DESCR << 8), 0, 8, glEp0Buffer); if (status != CY_U3P_SUCCESS) { goto enum_error; } /* Identify the EP0 packet size and update the scheduler. */ if (glEp0Buffer[7] != 8) { CyU3PUsbHostEpRemove (0); epCfg.maxPktSize = glEp0Buffer[7]; epCfg.fullPktSize = glEp0Buffer[7]; status = CyU3PUsbHostEpAdd (0, &epCfg); if (status != CY_U3P_SUCCESS) { goto enum_error; } } /* Read the full device descriptor. */ status = CyFxSendSetupRqt (0x80, CY_U3P_USB_SC_GET_DESCRIPTOR, (CY_U3P_USB_DEVICE_DESCR << 8), 0, 18, glEp0Buffer); if (status != CY_U3P_SUCCESS) { goto enum_error; } /* Set the peripheral device address. */ status = CyFxSendSetupRqt (0x00, CY_U3P_USB_SC_SET_ADDRESS, CY_FX_HOST_PERIPHERAL_ADDRESS, 0, 0, glEp0Buffer); if (status != CY_U3P_SUCCESS) { goto enum_error; } status = CyU3PUsbHostSetDeviceAddress (CY_FX_HOST_PERIPHERAL_ADDRESS); if (status != CY_U3P_SUCCESS) { goto enum_error; } /* Read first four bytes of configuration descriptor to determine * the total length. */ status = CyFxSendSetupRqt (0x80, CY_U3P_USB_SC_GET_DESCRIPTOR, (CY_U3P_USB_CONFIG_DESCR << 8), 0, 4, glEp0Buffer); if (status != CY_U3P_SUCCESS) { goto enum_error; } /* Identify the length of the data received. */ length = CY_U3P_MAKEWORD(glEp0Buffer[3], glEp0Buffer[2]); if (length > CY_FX_HOST_EP0_BUFFER_SIZE) { goto enum_error; } /* Read the full configuration descriptor. */ status = CyFxSendSetupRqt (0x80, CY_U3P_USB_SC_GET_DESCRIPTOR, (CY_U3P_USB_CONFIG_DESCR << 8), 0, length, glEp0Buffer); if (status != CY_U3P_SUCCESS) { goto enum_error; } /* Identify if this is an HID mouse or MSC device that can be * supported. If the device cannot be supported, just disable * the port and wait for a new device to be attached. We support * only single interface with interface class = HID(0x03), * interface sub class = Boot (0x01) * and interface protocol = Mouse (0x02). * or single interface with interface class = MSC(0x08), * interface sub class 0x06 and interface protocol BOT (0x50). */ if ((glEp0Buffer[5] == 1) && (glEp0Buffer[14] == 0x03) && (glEp0Buffer[15] == 0x01) && (glEp0Buffer[16] == 0x02) && (glEp0Buffer[28] == CY_U3P_USB_ENDPNT_DESCR)) { status = CyFxMouseDriverInit (); if (status == CY_U3P_SUCCESS) { glIsApplnActive = CyTrue; glHostOwner = CY_FX_HOST_OWNER_MOUSE_DRIVER; return; } } else if ((glEp0Buffer[5] == 1) && (glEp0Buffer[14] == 0x08) && (glEp0Buffer[15] == 0x06) && (glEp0Buffer[16] == 0x50)) { status = CyFxMscDriverInit (); if (status == CY_U3P_SUCCESS) { glIsApplnActive = CyTrue; glHostOwner = CY_FX_HOST_OWNER_MSC_DRIVER; return; } } else { /* Do nothing here. Fall-through to disable the USB port. * We do not support this device. */ status = CY_U3P_ERROR_NOT_SUPPORTED; } enum_error: /* Remove EP0. and disable the port. */ glHostOwner = CY_FX_HOST_OWNER_NONE; CyU3PUsbHostEpRemove (0); CyU3PUsbHostPortDisable (); CyU3PDebugPrint (4, "Application start failed with error: %d.\r\n", status); }
void CyFxMscDriverDoWork () { uint32_t upTime = 0; uint16_t index = 0; CyU3PReturnStatus_t status = CY_U3P_SUCCESS; #ifdef CY_FX_MSC_ENABLE_WRITE_TEST uint16_t temp; uint8_t pattern = 0; #endif /* CY_FX_MSC_ENABLE_WRITE_TEST */ /* Host polling interval. */ upTime = glTimerCount * CY_FX_HOST_POLL_INTERVAL; glTimerCount++; if ((glMscIsActive) && ((upTime % CY_FX_MSC_TEST_INTERVAL) == 0)) { CyU3PDebugPrint (4, "Starting MSC read / write tests.\r\n"); /* Write the sectors to memory. */ for (index = 0; index < CY_FX_MSC_TEST_SECTOR_COUNT; index++) { if ((glMscTestSector >= (glMscCapacity - CY_FX_MSC_TEST_SECTOR_COUNT)) || (glMscTestSector < CY_FX_MSC_TEST_SECTOR_OFFSET)) { glMscTestSector = CY_FX_MSC_TEST_SECTOR_OFFSET; } #ifdef CY_FX_MSC_ENABLE_WRITE_TEST /* Pre-fill the buffer with known pattern. */ pattern = (uint8_t)(glMscTestSector + index); CyU3PMemSet (glMscSector, pattern, glMscSectorSize); CyU3PDebugPrint (6, "Writing to sector: %d.\r\n", glMscSector); status = CyFxMscWriteSectors (glMscTestLun, glMscTestSector, 1, glMscSector); if (status != CY_U3P_SUCCESS) { break; } #endif /* CY_FX_MSC_ENABLE_WRITE_TEST */ /* Read back and verify. */ CyU3PMemSet (glMscSector, 0, glMscSectorSize); CyU3PDebugPrint (6, "Reading from sector: %d.\r\n", glMscSector); status = CyFxMscReadSectors (glMscTestLun, glMscTestSector, 1, glMscSector); if (status != CY_U3P_SUCCESS) { break; } #ifdef CY_FX_MSC_ENABLE_WRITE_TEST for (temp = 0; temp < glMscSectorSize; temp++) { if (glMscSector[temp] != pattern) { CyU3PDebugPrint (6, "Compare failed for sector: %d at byte %d.\r\n", glMscSector, temp); status = CY_U3P_ERROR_FAILURE; break; } } if (status != CY_U3P_SUCCESS) { break; } #endif /* CY_FX_MSC_ENABLE_WRITE_TEST */ /* Increment the test sector. */ glMscTestSector++; } /* If an error was encountered, stop the test. */ if (status == CY_U3P_SUCCESS) { CyU3PDebugPrint (4, "Completed MSC read / write tests.\r\n"); } else { CyU3PDebugPrint (4, "MSC test failed with status: %d.\r\n", status); glMscIsActive = CyFalse; } } }
CyU3PReturnStatus_t CyFxMscDriverInit () { uint8_t maxLun = 0, i, retry; uint16_t length, size, offset; CyU3PReturnStatus_t status; CyU3PUsbHostEpConfig_t epCfg; CyU3PDmaChannelConfig_t dmaCfg; /* Read first four bytes of configuration descriptor to determine * the total length. */ status = CyFxSendSetupRqt (0x80, CY_U3P_USB_SC_GET_DESCRIPTOR, (CY_U3P_USB_CONFIG_DESCR << 8), 0, 4, glEp0Buffer); if (status != CY_U3P_SUCCESS) { goto enum_error; } /* Identify the length of the data received. */ length = CY_U3P_MAKEWORD(glEp0Buffer[3], glEp0Buffer[2]); if (length > CY_FX_HOST_EP0_BUFFER_SIZE) { goto enum_error; } /* Read the full configuration descriptor. */ status = CyFxSendSetupRqt (0x80, CY_U3P_USB_SC_GET_DESCRIPTOR, (CY_U3P_USB_CONFIG_DESCR << 8), 0, length, glEp0Buffer); if (status != CY_U3P_SUCCESS) { goto enum_error; } /* Identify the EP characteristics. */ offset = 0; while (offset < length) { if (glEp0Buffer[offset + 1] == CY_U3P_USB_ENDPNT_DESCR) { if (glEp0Buffer[offset + 3] != CY_U3P_USB_EP_BULK) { goto enum_error; } /* Retreive the information. */ glMscEpSize = CY_U3P_MAKEWORD(glEp0Buffer[offset + 5], glEp0Buffer[offset + 4]); if (glEp0Buffer[offset + 2] & 0x80) { glMscInEp = glEp0Buffer[offset + 2]; } else { glMscOutEp = glEp0Buffer[offset + 2]; } } /* Advance to next descriptor. */ offset += glEp0Buffer[offset]; } /* Set the new configuration. */ status = CyFxSendSetupRqt (0x00, CY_U3P_USB_SC_SET_CONFIGURATION, 1, 0, 0, glEp0Buffer); if (status != CY_U3P_SUCCESS) { goto enum_error; } /* Identify the number of LUNs available. * We will use only the first available LUN. */ status = CyFxSendSetupRqt (0xA1, CY_FX_MSC_GET_MAX_LUN, 0, 0, 1, glEp0Buffer); if (status != CY_U3P_SUCCESS) { goto enum_error; } maxLun = glEp0Buffer[0]; /* Add the IN endpoint. */ CyU3PMemSet ((uint8_t *)&epCfg, 0, sizeof(epCfg)); epCfg.type = CY_U3P_USB_EP_BULK; epCfg.mult = 1; epCfg.maxPktSize = glMscEpSize; epCfg.pollingRate = 0; /* Since DMA buffer sizes can only be multiple of 16 bytes and * also since this is an interrupt endpoint where the max data * packet size is same as the maxPktSize field, the fullPktSize * has to be a multiple of 16 bytes. */ size = ((glMscEpSize + 0x0F) & ~0x0F); epCfg.fullPktSize = size; epCfg.isStreamMode = CyFalse; status = CyU3PUsbHostEpAdd (glMscInEp, &epCfg); if (status != CY_U3P_SUCCESS) { goto enum_error; } /* Add the OUT EP. */ status = CyU3PUsbHostEpAdd (glMscOutEp, &epCfg); if (status != CY_U3P_SUCCESS) { goto enum_error; } /* Create a DMA channel for IN EP. */ CyU3PMemSet ((uint8_t *)&dmaCfg, 0, sizeof(dmaCfg)); dmaCfg.size = glMscEpSize; dmaCfg.count = 0; dmaCfg.prodSckId = (CyU3PDmaSocketId_t)(CY_U3P_UIB_SOCKET_PROD_0 + (0x0F & glMscInEp)); dmaCfg.consSckId = CY_U3P_CPU_SOCKET_CONS; dmaCfg.dmaMode = CY_U3P_DMA_MODE_BYTE; dmaCfg.notification = 0; dmaCfg.cb = NULL; dmaCfg.prodHeader = 0; dmaCfg.prodFooter = 0; dmaCfg.consHeader = 0; dmaCfg.prodAvailCount = 0; status = CyU3PDmaChannelCreate (&glMscInCh, CY_U3P_DMA_TYPE_MANUAL_IN, &dmaCfg); if (status != CY_U3P_SUCCESS) { goto app_error; } /* Create a DMA channel for OUT EP. */ dmaCfg.prodSckId = CY_U3P_CPU_SOCKET_PROD; dmaCfg.consSckId = (CyU3PDmaSocketId_t)(CY_U3P_UIB_SOCKET_CONS_0 + (0x0F & glMscOutEp)); status = CyU3PDmaChannelCreate (&glMscOutCh, CY_U3P_DMA_TYPE_MANUAL_OUT, &dmaCfg); if (status != CY_U3P_SUCCESS) { goto app_error; } for (retry = 0; retry < CY_FX_MSC_MAX_RETRY; retry++) { /* Give some time for the device to initialize. */ CyU3PThreadSleep (1000); for (i = 0; i <= maxLun; i++) { /* Check if the unit is ready. */ status = CyFxMscTestUnitReady (maxLun); if (status == CY_U3P_SUCCESS) { glMscTestLun = i; break; } } if (status == CY_U3P_SUCCESS) { break; } } if (status != CY_U3P_SUCCESS) { glMscTestLun = 0; goto app_error; } /* Read the device capacity. */ status = CyFxMscReadCapacity (glMscTestLun); if (status != CY_U3P_SUCCESS) { goto app_error; } glMscIsActive = CyTrue; return status; app_error: CyU3PDmaChannelDestroy (&glMscInCh); if (glMscInEp != 0) { CyU3PUsbHostEpRemove (glMscInEp); glMscInEp = 0; } CyU3PDmaChannelDestroy (&glMscOutCh); if (glMscOutEp != 0) { CyU3PUsbHostEpRemove (glMscOutEp); glMscOutEp = 0; } glMscEpSize = 0; glMscSectorSize = 0; glMscCapacity = 0; glMscTestLun = 0; glMscTestSector = 0; glTimerCount = 0; enum_error: return CY_U3P_ERROR_FAILURE; }
static void NuandFpgaConfigStart(void) { uint16_t size = 0; CyU3PEpConfig_t epCfg; CyU3PDmaChannelConfig_t dmaCfg; CyU3PReturnStatus_t apiRetStatus = CY_U3P_SUCCESS; CyU3PUSBSpeed_t usbSpeed = CyU3PUsbGetSpeed(); static int first_call = 1; NuandAllowSuspend(CyFalse); NuandGPIOReconfigure(CyFalse, !first_call); first_call = 0; apiRetStatus = NuandConfigureGpif(GPIF_CONFIG_FPGA_LOAD); if (apiRetStatus != CY_U3P_SUCCESS) { LOG_ERROR(apiRetStatus); CyFxAppErrorHandler(apiRetStatus); } /* Determine max packet size based on USB speed */ switch (usbSpeed) { case CY_U3P_FULL_SPEED: size = 64; break; case CY_U3P_HIGH_SPEED: size = 512; break; case CY_U3P_SUPER_SPEED: size = 1024; break; default: LOG_ERROR(usbSpeed); CyFxAppErrorHandler(CY_U3P_ERROR_FAILURE); break; } CyU3PMemSet((uint8_t *)&epCfg, 0, sizeof (epCfg)); epCfg.enable = CyTrue; epCfg.epType = CY_U3P_USB_EP_BULK; epCfg.burstLen = 1; epCfg.streams = 0; epCfg.pcktSize = size; apiRetStatus = CyU3PSetEpConfig(BLADE_FPGA_EP_PRODUCER, &epCfg); if (apiRetStatus != CY_U3P_SUCCESS) { LOG_ERROR(apiRetStatus); CyFxAppErrorHandler (apiRetStatus); } dmaCfg.size = size * 4; dmaCfg.count = BLADE_DMA_BUF_COUNT; dmaCfg.prodSckId = BLADE_FPGA_CONFIG_SOCKET; dmaCfg.consSckId = CY_U3P_PIB_SOCKET_3; dmaCfg.dmaMode = CY_U3P_DMA_MODE_BYTE; /* Enable the callback for produce event, this is where the bits will get flipped */ dmaCfg.notification = CY_U3P_DMA_CB_PROD_EVENT; dmaCfg.cb = bladeRFConfigUtoPDmaCallback; dmaCfg.prodHeader = 0; dmaCfg.prodFooter = size * 3; dmaCfg.consHeader = 0; dmaCfg.prodAvailCount = 0; apiRetStatus = CyU3PDmaChannelCreate(&glChHandlebladeRFUtoP, CY_U3P_DMA_TYPE_MANUAL, &dmaCfg); if (apiRetStatus != CY_U3P_SUCCESS) { LOG_ERROR(apiRetStatus); CyFxAppErrorHandler(apiRetStatus); } /* Flush the endpoint memory */ CyU3PUsbFlushEp(BLADE_FPGA_EP_PRODUCER); /* Set DMA channel transfer size. */ apiRetStatus = CyU3PDmaChannelSetXfer(&glChHandlebladeRFUtoP, BLADE_DMA_TX_SIZE); if (apiRetStatus != CY_U3P_SUCCESS) { LOG_ERROR(apiRetStatus); CyFxAppErrorHandler(apiRetStatus); } glAppMode = MODE_FPGA_CONFIG; }
/* This function initializes the mouse driver application. */ static void CyFxApplnStart () { uint16_t length, size, offset; CyU3PDmaBuffer_t buf_p; CyU3PReturnStatus_t status; CyU3PUsbHostEpConfig_t epCfg; CyU3PDmaChannelConfig_t dmaCfg; CyU3PUsbHostEpStatus_t epStatus; /* Add EP0 to the scheduler. */ CyU3PMemSet ((uint8_t *)&epCfg, 0, sizeof(epCfg)); epCfg.type = CY_U3P_USB_EP_CONTROL; epCfg.mult = 1; /* Start off with 8 byte EP0 packet size. */ epCfg.maxPktSize = 8; epCfg.pollingRate = 0; epCfg.fullPktSize = 8; epCfg.isStreamMode = CyFalse; status = CyU3PUsbHostEpAdd (0, &epCfg); if (status != CY_U3P_SUCCESS) { goto enum_error; } CyU3PThreadSleep (100); /* Get the device descriptor. */ CyFxFormatSetupRqt (glSetupPkt, 0x80, CY_U3P_USB_SC_GET_DESCRIPTOR, (CY_U3P_USB_DEVICE_DESCR << 8), 0, 8); status = CyU3PUsbHostSendSetupRqt (glSetupPkt, glEp0Buffer); if (status != CY_U3P_SUCCESS) { goto enum_error; } status = CyU3PUsbHostEpWaitForCompletion (0, &epStatus, CY_FX_HOST_EP0_WAIT_TIMEOUT); if (status != CY_U3P_SUCCESS) { goto enum_error; } /* Identify the EP0 packet size and update the scheduler. */ if (glEp0Buffer[7] != 8) { status = CyU3PUsbHostEpRemove (0); if (status != CY_U3P_SUCCESS) { goto enum_error; } /* Update the correct size. */ epCfg.maxPktSize = glEp0Buffer[7]; epCfg.fullPktSize = glEp0Buffer[7]; status = CyU3PUsbHostEpAdd (0, &epCfg); if (status != CY_U3P_SUCCESS) { goto enum_error; } } /* Read the full device descriptor. */ CyFxFormatSetupRqt (glSetupPkt, 0x80, CY_U3P_USB_SC_GET_DESCRIPTOR, (CY_U3P_USB_DEVICE_DESCR << 8), 0, 18); status = CyU3PUsbHostSendSetupRqt (glSetupPkt, glEp0Buffer); if (status != CY_U3P_SUCCESS) { goto enum_error; } status = CyU3PUsbHostEpWaitForCompletion (0, &epStatus, CY_FX_HOST_EP0_WAIT_TIMEOUT); if (status != CY_U3P_SUCCESS) { goto enum_error; } /* Check for the VID and PID of the attached peripheral. */ if ((CY_U3P_MAKEWORD(glEp0Buffer[9], glEp0Buffer[8]) != CY_FX_HOST_PERIPHERAL_VID) || (CY_U3P_MAKEWORD(glEp0Buffer[11], glEp0Buffer[10]) != CY_FX_HOST_PERIPHERAL_PID)) { status = CY_U3P_ERROR_NOT_SUPPORTED; goto enum_error; } /* Check for device class, sub-class and protocol all of which has to be zero. */ if ((glEp0Buffer[4] != 0) || (glEp0Buffer[5] != 0) || (glEp0Buffer[6] != 0)) { status = CY_U3P_ERROR_NOT_SUPPORTED; goto enum_error; } /* Set the peripheral device address. */ CyFxFormatSetupRqt (glSetupPkt, 0x00, CY_U3P_USB_SC_SET_ADDRESS, CY_FX_HOST_PERIPHERAL_ADDRESS, 0, 0); status = CyU3PUsbHostSendSetupRqt (glSetupPkt, glEp0Buffer); if (status != CY_U3P_SUCCESS) { goto enum_error; } status = CyU3PUsbHostEpWaitForCompletion (0, &epStatus, CY_FX_HOST_EP0_WAIT_TIMEOUT); if (status != CY_U3P_SUCCESS) { goto enum_error; } status = CyU3PUsbHostSetDeviceAddress (CY_FX_HOST_PERIPHERAL_ADDRESS); if (status != CY_U3P_SUCCESS) { goto enum_error; } /* Read the OTG descriptor to identify its characteristics. * Do this only if we are not already in role change. */ glIsHnpSupported = CyFalse; if (!CyU3POtgIsHnpEnabled ()) { CyFxFormatSetupRqt (glSetupPkt, 0x80, CY_U3P_USB_SC_GET_DESCRIPTOR, (CY_U3P_USB_OTG_DESCR << 8), 0, 5); status = CyU3PUsbHostSendSetupRqt (glSetupPkt, glEp0Buffer); if (status != CY_U3P_SUCCESS) { goto enum_error; } status = CyU3PUsbHostEpWaitForCompletion (0, &epStatus, CY_FX_HOST_EP0_WAIT_TIMEOUT); /* If the device does not support OTG, the request will be stalled. */ if ((status == CY_U3P_SUCCESS) && (glEp0Buffer[2] & 0x02)) { /* Let the device know that the host is HNP capable. */ CyFxFormatSetupRqt (glSetupPkt, 0x00, CY_U3P_USB_SC_SET_FEATURE, CY_U3P_USB2_OTG_A_HNP_SUPPORT, 0, 0); status = CyU3PUsbHostSendSetupRqt (glSetupPkt, glEp0Buffer); if (status != CY_U3P_SUCCESS) { goto enum_error; } status = CyU3PUsbHostEpWaitForCompletion (0, &epStatus, CY_FX_HOST_EP0_WAIT_TIMEOUT); } if (status == CY_U3P_SUCCESS) { glIsHnpSupported = CyTrue; } } /* Read first four bytes of configuration descriptor to determine * the total length. */ CyFxFormatSetupRqt (glSetupPkt, 0x80, CY_U3P_USB_SC_GET_DESCRIPTOR, (CY_U3P_USB_CONFIG_DESCR << 8), 0, 4); status = CyU3PUsbHostSendSetupRqt (glSetupPkt, glEp0Buffer); if (status != CY_U3P_SUCCESS) { goto enum_error; } status = CyU3PUsbHostEpWaitForCompletion (0, &epStatus, CY_FX_HOST_EP0_WAIT_TIMEOUT); if (status != CY_U3P_SUCCESS) { goto enum_error; } /* Identify the length of the data received. */ length = CY_U3P_MAKEWORD(glEp0Buffer[3], glEp0Buffer[2]); if (length > CY_FX_HOST_EP0_BUFFER_SIZE) { goto enum_error; } /* Read the full configuration descriptor. */ CyFxFormatSetupRqt (glSetupPkt, 0x80, CY_U3P_USB_SC_GET_DESCRIPTOR, (CY_U3P_USB_CONFIG_DESCR << 8), 0, length); status = CyU3PUsbHostSendSetupRqt (glSetupPkt, glEp0Buffer); if (status != CY_U3P_SUCCESS) { goto enum_error; } status = CyU3PUsbHostEpWaitForCompletion (0, &epStatus, CY_FX_HOST_EP0_WAIT_TIMEOUT); if (status != CY_U3P_SUCCESS) { goto enum_error; } /* Check if the device can be supported. Number of interfaces should be 1, * the intreface class must be vendor (0xFF) and the subclass and protocol * must be zero. The number of endpoints must be two. Also the endpoints * should be bulk. */ if ((glEp0Buffer[5] != 1) || (glEp0Buffer[14] != 0xFF) || (glEp0Buffer[15] != 0x00) || (glEp0Buffer[16] != 0x00) || (glEp0Buffer[13] != 2)) { status = CY_U3P_ERROR_NOT_SUPPORTED; goto enum_error; } /* Identify the EP characteristics. */ offset = 0; while (offset < length) { if (glEp0Buffer[offset + 1] == CY_U3P_USB_ENDPNT_DESCR) { if (glEp0Buffer[offset + 3] != CY_U3P_USB_EP_BULK) { status = CY_U3P_ERROR_NOT_SUPPORTED; goto enum_error; } /* Retreive the information. */ glHostEpSize = CY_U3P_MAKEWORD(glEp0Buffer[offset + 5], glEp0Buffer[offset + 4]); if (glEp0Buffer[offset + 2] & 0x80) { glHostInEp = glEp0Buffer[offset + 2]; } else { glHostOutEp = glEp0Buffer[offset + 2]; } } /* Advance to next descriptor. */ offset += glEp0Buffer[offset]; } /* If there is any error in the configuration abort. */ if ((glHostOutEp == 0) || (glHostInEp == 0)) { status = CY_U3P_ERROR_NOT_SUPPORTED; goto enum_error; } /* Set the new configuration. */ CyFxFormatSetupRqt (glSetupPkt, 0x00, CY_U3P_USB_SC_SET_CONFIGURATION, 1, 0, 0); status = CyU3PUsbHostSendSetupRqt (glSetupPkt, glEp0Buffer); if (status != CY_U3P_SUCCESS) { goto enum_error; } status = CyU3PUsbHostEpWaitForCompletion (0, &epStatus, CY_FX_HOST_EP0_WAIT_TIMEOUT); if (status != CY_U3P_SUCCESS) { goto enum_error; } /* Initialize the loopback application. */ CyU3PMemSet ((uint8_t *)&epCfg, 0, sizeof(epCfg)); epCfg.type = CY_U3P_USB_EP_BULK; epCfg.mult = 1; epCfg.maxPktSize = glHostEpSize; epCfg.pollingRate = 0; size = ((glHostEpSize + 0x0F) & ~0x0F); epCfg.fullPktSize = glHostEpSize; epCfg.isStreamMode = CyFalse; status = CyU3PUsbHostEpAdd (glHostOutEp, &epCfg); if (status != CY_U3P_SUCCESS) { goto enum_error; } status = CyU3PUsbHostEpAdd (glHostInEp, &epCfg); if (status != CY_U3P_SUCCESS) { glHostInEp = 0; goto app_error; } /* Reset counter to zero. */ glDMARxCount = 0; glDMATxCount = 0; /* Create a DMA channels for IN and OUT directions. */ CyU3PMemSet ((uint8_t *)&dmaCfg, 0, sizeof(dmaCfg)); dmaCfg.size = size; dmaCfg.count = CY_FX_HOST_DMA_BUF_COUNT; dmaCfg.prodHeader = 0; dmaCfg.prodFooter = 0; dmaCfg.consHeader = 0; dmaCfg.prodAvailCount = 0; dmaCfg.prodSckId = (CyU3PDmaSocketId_t)(CY_U3P_UIB_SOCKET_PROD_0 + (0x0F & glHostInEp)); dmaCfg.consSckId = CY_U3P_CPU_SOCKET_CONS; dmaCfg.dmaMode = CY_U3P_DMA_MODE_BYTE; dmaCfg.notification = CY_U3P_DMA_CB_PROD_EVENT; dmaCfg.cb = CyFxHostDmaCb; status = CyU3PDmaChannelCreate (&glHostInCh, CY_U3P_DMA_TYPE_MANUAL_IN, &dmaCfg); if (status != CY_U3P_SUCCESS) { goto app_error; } dmaCfg.prodSckId = CY_U3P_CPU_SOCKET_PROD; dmaCfg.consSckId = (CyU3PDmaSocketId_t)(CY_U3P_UIB_SOCKET_CONS_0 + (0x0F & glHostOutEp)); dmaCfg.dmaMode = CY_U3P_DMA_MODE_BYTE; dmaCfg.notification = CY_U3P_DMA_CB_CONS_EVENT; dmaCfg.cb = CyFxHostDmaCb; status = CyU3PDmaChannelCreate (&glHostOutCh, CY_U3P_DMA_TYPE_MANUAL_OUT, &dmaCfg); if (status != CY_U3P_SUCCESS) { goto app_error; } /* Set infinite transfer on both the channels. */ status = CyU3PDmaChannelSetXfer (&glHostInCh, 0); if (status != CY_U3P_SUCCESS) { goto app_error; } status = CyU3PDmaChannelSetXfer (&glHostOutCh, 0); if (status != CY_U3P_SUCCESS) { goto app_error; } /* Pre-load all OUT buffers with fixed data. */ for (offset = 0; offset < CY_FX_HOST_DMA_BUF_COUNT; offset++) { status = CyU3PDmaChannelGetBuffer (&glHostOutCh, &buf_p, CYU3P_NO_WAIT); if (status != CY_U3P_SUCCESS) { goto app_error; } CyU3PMemSet (buf_p.buffer, (uint8_t)CY_FX_HOST_DATA_BYTE, glHostEpSize); status = CyU3PDmaChannelCommitBuffer (&glHostOutCh, glHostEpSize, 0); if (status != CY_U3P_SUCCESS) { goto app_error; } } /* Queue a single read and single write request. */ status = CyU3PUsbHostEpSetXfer (glHostInEp, CY_U3P_USB_HOST_EPXFER_NORMAL, glHostEpSize); if (status != CY_U3P_SUCCESS) { goto app_error; } status = CyU3PUsbHostEpSetXfer (glHostOutEp, CY_U3P_USB_HOST_EPXFER_NORMAL, glHostEpSize); if (status != CY_U3P_SUCCESS) { goto app_error; } glTimerCount = 0; glIsApplnActive = CyTrue; glIsHnp = CyFalse; glDoHnp = CyFalse; if (glIsHnpSupported) { CyU3PDebugPrint (4, "USB bulk loopback host mode operation started with HNP enabled.\r\n"); } else { CyU3PDebugPrint (4, "USB bulk loopback host mode operation started with HNP disabled.\r\n"); } return; app_error: CyU3PDmaChannelDestroy (&glHostInCh); if (glHostInEp != 0) { CyU3PUsbHostEpRemove (glHostInEp); glHostInEp = 0; } CyU3PDmaChannelDestroy (&glHostOutCh); if (glHostOutEp != 0) { CyU3PUsbHostEpRemove (glHostOutEp); glHostOutEp = 0; } enum_error: /* Remove EP0. and disable the port. */ CyU3PUsbHostEpRemove (0); glHostEpSize = 0; CyU3PUsbHostPortDisable (); CyU3PDebugPrint (4, "Host mode application start failed with error: %d.\r\n", status); }