/* This function disables the mouse driver application. */ static void CyFxApplnStop () { /* Destroy the DMA channel. */ CyU3PDmaChannelDestroy (&glHostInCh); if (glHostInEp != 0) { CyU3PUsbHostEpRemove (glHostInEp); glHostInEp = 0; } CyU3PDmaChannelDestroy (&glHostOutCh); if (glHostOutEp != 0) { CyU3PUsbHostEpRemove (glHostOutEp); glHostOutEp = 0; } /* Remove EP0. and disable the port. */ CyU3PUsbHostEpRemove (0); glHostEpSize = 0; CyU3PUsbHostPortDisable (); /* Clear state variables. */ glIsApplnActive = CyFalse; glTimerCount = 0; glIsHnp = CyFalse; glDoHnp = CyFalse; glIsHnpSupported = CyFalse; /* Reset counter to zero. */ glDMARxCount = 0; glDMATxCount = 0; CyU3PDebugPrint (4, "Host mode application stopped.\r\n"); }
/* This function disables the mouse driver application. */ void CyFxApplnStop () { if (glHostOwner == CY_FX_HOST_OWNER_MOUSE_DRIVER) { CyFxMouseDriverDeInit (); } if (glHostOwner == CY_FX_HOST_OWNER_MSC_DRIVER) { CyFxMscDriverDeInit (); } /* Remove EP0. and disable the port. */ CyU3PUsbHostEpRemove (0); CyU3PUsbHostPortDisable (); glHostOwner = CY_FX_HOST_OWNER_NONE; /* Clear state variables. */ glIsApplnActive = CyFalse; }
/* 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); }
/* 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); }