/*! * @brief Send notification to host that a response is available. * * This function is called to send notification to host that a response is available. * * @param handle The pointer the RNDIS device. * @return A USB error code or kStatus_USB_Success. */ usb_status_t USB_DeviceCdcRndisResponseAvailable(usb_device_cdc_rndis_struct_t *handle) { usb_device_cdc_acm_struct_t *cdcAcmHandle; usb_status_t error = kStatus_USB_Error; if (!handle) { return kStatus_USB_InvalidHandle; } cdcAcmHandle = (usb_device_cdc_acm_struct_t *)(handle->cdcAcmHandle); /* update array for current interface */ g_responseAvailableData[4] = cdcAcmHandle->interfaceNumber; error = USB_DeviceCdcAcmSend((uint32_t)cdcAcmHandle, cdcAcmHandle->interruptIn.ep, g_responseAvailableData, NOTIF_PACKET_SIZE); return error; }
/*! * @brief CDC class specific callback function. * * This function handles the CDC class specific requests. * * @param handle The CDC ACM class handle. * @param event The CDC ACM class event type. * @param param The parameter of the class specific request. * * @return A USB error code or kStatus_USB_Success. */ usb_status_t USB_DeviceCdcVcomCallback(class_handle_t handle, uint32_t event, void *param) { uint32_t len; uint16_t *uartBitmap; usb_device_cdc_acm_request_param_struct_t *acmReqParam; usb_device_endpoint_callback_message_struct_t *epCbParam; usb_status_t error = kStatus_USB_Error; usb_cdc_acm_info_t *acmInfo = &s_usbCdcAcmInfo; acmReqParam = (usb_device_cdc_acm_request_param_struct_t *)param; epCbParam = (usb_device_endpoint_callback_message_struct_t *)param; switch (event) { case kUSB_DeviceCdcEventSendResponse: { if ((epCbParam->length != 0) && (!(epCbParam->length % g_UsbDeviceCdcVcomDicEndpoints[0].maxPacketSize))) { /* If the last packet is the size of endpoint, then send also zero-ended packet, ** meaning that we want to inform the host that we do not have any additional ** data, so it can flush the output. */ USB_DeviceCdcAcmSend(handle, USB_CDC_VCOM_BULK_IN_ENDPOINT, NULL, 0); } else if ((1 == s_cdcVcom.attach) && (1 == s_cdcVcom.startTransactions)) { if ((epCbParam->buffer != NULL) || ((epCbParam->buffer == NULL) && (epCbParam->length == 0))) { /* User: add your own code for send complete event */ /* Schedule buffer for next receive event */ USB_DeviceCdcAcmRecv(handle, USB_CDC_VCOM_BULK_OUT_ENDPOINT, s_currRecvBuf, g_UsbDeviceCdcVcomDicEndpoints[0].maxPacketSize); #if defined(FSL_FEATURE_USB_KHCI_KEEP_ALIVE_ENABLED) && (FSL_FEATURE_USB_KHCI_KEEP_ALIVE_ENABLED > 0U) && \ defined(USB_DEVICE_CONFIG_KEEP_ALIVE_MODE) && (USB_DEVICE_CONFIG_KEEP_ALIVE_MODE > 0U) && \ defined(FSL_FEATURE_USB_KHCI_USB_RAM) && (FSL_FEATURE_USB_KHCI_USB_RAM > 0U) s_waitForDataReceive = 1; USB0->INTEN &= ~USB_INTEN_SOFTOKEN_MASK; #endif } } else { } } break; case kUSB_DeviceCdcEventRecvResponse: { if ((1 == s_cdcVcom.attach) && (1 == s_cdcVcom.startTransactions)) { s_recvSize = epCbParam->length; #if defined(FSL_FEATURE_USB_KHCI_KEEP_ALIVE_ENABLED) && (FSL_FEATURE_USB_KHCI_KEEP_ALIVE_ENABLED > 0U) && \ defined(USB_DEVICE_CONFIG_KEEP_ALIVE_MODE) && (USB_DEVICE_CONFIG_KEEP_ALIVE_MODE > 0U) && \ defined(FSL_FEATURE_USB_KHCI_USB_RAM) && (FSL_FEATURE_USB_KHCI_USB_RAM > 0U) s_waitForDataReceive = 0; USB0->INTEN |= USB_INTEN_SOFTOKEN_MASK; #endif if (!s_recvSize) { /* Schedule buffer for next receive event */ USB_DeviceCdcAcmRecv(handle, USB_CDC_VCOM_BULK_OUT_ENDPOINT, s_currRecvBuf, g_UsbDeviceCdcVcomDicEndpoints[0].maxPacketSize); #if defined(FSL_FEATURE_USB_KHCI_KEEP_ALIVE_ENABLED) && (FSL_FEATURE_USB_KHCI_KEEP_ALIVE_ENABLED > 0U) && \ defined(USB_DEVICE_CONFIG_KEEP_ALIVE_MODE) && (USB_DEVICE_CONFIG_KEEP_ALIVE_MODE > 0U) && \ defined(FSL_FEATURE_USB_KHCI_USB_RAM) && (FSL_FEATURE_USB_KHCI_USB_RAM > 0U) s_waitForDataReceive = 1; USB0->INTEN &= ~USB_INTEN_SOFTOKEN_MASK; #endif } } } break; case kUSB_DeviceCdcEventSerialStateNotif: ((usb_device_cdc_acm_struct_t *)handle)->hasSentState = 0; break; case kUSB_DeviceCdcEventSendEncapsulatedCommand: break; case kUSB_DeviceCdcEventGetEncapsulatedResponse: break; case kUSB_DeviceCdcEventSetCommFeature: if (USB_DEVICE_CDC_FEATURE_ABSTRACT_STATE == acmReqParam->setupValue) { if (1 == acmReqParam->isSetup) { *(acmReqParam->buffer) = s_abstractState; } else { *(acmReqParam->length) = 0; } } else if (USB_DEVICE_CDC_FEATURE_COUNTRY_SETTING == acmReqParam->setupValue) { if (1 == acmReqParam->isSetup) { *(acmReqParam->buffer) = s_countryCode; } else { *(acmReqParam->length) = 0; } } else { } error = kStatus_USB_Success; break; case kUSB_DeviceCdcEventGetCommFeature: if (USB_DEVICE_CDC_FEATURE_ABSTRACT_STATE == acmReqParam->setupValue) { *(acmReqParam->buffer) = s_abstractState; *(acmReqParam->length) = COMM_FEATURE_DATA_SIZE; } else if (USB_DEVICE_CDC_FEATURE_COUNTRY_SETTING == acmReqParam->setupValue) { *(acmReqParam->buffer) = s_countryCode; *(acmReqParam->length) = COMM_FEATURE_DATA_SIZE; } else { } error = kStatus_USB_Success; break; case kUSB_DeviceCdcEventClearCommFeature: break; case kUSB_DeviceCdcEventGetLineCoding: *(acmReqParam->buffer) = s_lineCoding; *(acmReqParam->length) = LINE_CODING_SIZE; error = kStatus_USB_Success; break; case kUSB_DeviceCdcEventSetLineCoding: { if (1 == acmReqParam->isSetup) { *(acmReqParam->buffer) = s_lineCoding; } else { *(acmReqParam->length) = 0; } } error = kStatus_USB_Success; break; case kUSB_DeviceCdcEventSetControlLineState: { s_usbCdcAcmInfo.dteStatus = acmReqParam->setupValue; /* activate/deactivate Tx carrier */ if (acmInfo->dteStatus & USB_DEVICE_CDC_CONTROL_SIG_BITMAP_CARRIER_ACTIVATION) { acmInfo->uartState |= USB_DEVICE_CDC_UART_STATE_TX_CARRIER; } else { acmInfo->uartState &= (uint16_t)~USB_DEVICE_CDC_UART_STATE_TX_CARRIER; } /* activate carrier and DTE */ if (acmInfo->dteStatus & USB_DEVICE_CDC_CONTROL_SIG_BITMAP_DTE_PRESENCE) { acmInfo->uartState |= USB_DEVICE_CDC_UART_STATE_RX_CARRIER; } else { acmInfo->uartState &= (uint16_t)~USB_DEVICE_CDC_UART_STATE_RX_CARRIER; } /* Indicates to DCE if DTE is present or not */ acmInfo->dtePresent = (acmInfo->dteStatus & USB_DEVICE_CDC_CONTROL_SIG_BITMAP_DTE_PRESENCE) ? true : false; /* Initialize the serial state buffer */ acmInfo->serialStateBuf[0] = NOTIF_REQUEST_TYPE; /* bmRequestType */ acmInfo->serialStateBuf[1] = USB_DEVICE_CDC_NOTIF_SERIAL_STATE; /* bNotification */ acmInfo->serialStateBuf[2] = 0x00; /* wValue */ acmInfo->serialStateBuf[3] = 0x00; acmInfo->serialStateBuf[4] = 0x00; /* wIndex */ acmInfo->serialStateBuf[5] = 0x00; acmInfo->serialStateBuf[6] = UART_BITMAP_SIZE; /* wLength */ acmInfo->serialStateBuf[7] = 0x00; /* Notifiy to host the line state */ acmInfo->serialStateBuf[4] = acmReqParam->interfaceIndex; /* Lower byte of UART BITMAP */ uartBitmap = (uint16_t *)&acmInfo->serialStateBuf[NOTIF_PACKET_SIZE + UART_BITMAP_SIZE - 2]; *uartBitmap = acmInfo->uartState; len = (uint32_t)(NOTIF_PACKET_SIZE + UART_BITMAP_SIZE); if (0 == ((usb_device_cdc_acm_struct_t *)handle)->hasSentState) { error = USB_DeviceCdcAcmSend(handle, USB_CDC_VCOM_INTERRUPT_IN_ENDPOINT, acmInfo->serialStateBuf, len); if (kStatus_USB_Success != error) { usb_echo("kUSB_DeviceCdcEventSetControlLineState error!"); } ((usb_device_cdc_acm_struct_t *)handle)->hasSentState = 1; } /* Update status */ if (acmInfo->dteStatus & USB_DEVICE_CDC_CONTROL_SIG_BITMAP_CARRIER_ACTIVATION) { /* To do: CARRIER_ACTIVATED */ } else { /* To do: CARRIER_DEACTIVATED */ } if (acmInfo->dteStatus & USB_DEVICE_CDC_CONTROL_SIG_BITMAP_DTE_PRESENCE) { /* DTE_ACTIVATED */ if (1 == s_cdcVcom.attach) { s_cdcVcom.startTransactions = 1; #if defined(FSL_FEATURE_USB_KHCI_KEEP_ALIVE_ENABLED) && (FSL_FEATURE_USB_KHCI_KEEP_ALIVE_ENABLED > 0U) && \ defined(USB_DEVICE_CONFIG_KEEP_ALIVE_MODE) && (USB_DEVICE_CONFIG_KEEP_ALIVE_MODE > 0U) && \ defined(FSL_FEATURE_USB_KHCI_USB_RAM) && (FSL_FEATURE_USB_KHCI_USB_RAM > 0U) s_waitForDataReceive = 1; USB0->INTEN &= ~USB_INTEN_SOFTOKEN_MASK; s_comOpen = 1; usb_echo("USB_APP_CDC_DTE_ACTIVATED\r\n"); #endif } } else { /* DTE_DEACTIVATED */ if (1 == s_cdcVcom.attach) { s_cdcVcom.startTransactions = 0; } } } break; case kUSB_DeviceCdcEventSendBreak: break; default: break; } return error; }