/*! * @brief cdc open control interface. * * @param cdcInstance cdc instance pointer. * * @return kStatus_USB_Success or error codes. */ static usb_status_t USB_HostCdcOpenControlInterface(usb_host_cdc_instance_struct_t *cdcInstance) { usb_status_t status; uint8_t ep_index = 0; usb_host_pipe_init_t pipeInit; usb_descriptor_endpoint_t *ep_desc = NULL; usb_host_interface_t *interfaceHandle; if (cdcInstance->interruptPipe != NULL) { status = USB_HostCancelTransfer(cdcInstance->hostHandle, cdcInstance->interruptPipe, NULL); status = USB_HostClosePipe(cdcInstance->hostHandle, cdcInstance->interruptPipe); if (status != kStatus_USB_Success) { #ifdef HOST_ECHO usb_echo("error when close pipe\r\n"); #endif } cdcInstance->interruptPipe = NULL; } status = USB_HostOpenDeviceInterface(cdcInstance->deviceHandle, cdcInstance->controlInterfaceHandle); /* open interface pipes */ interfaceHandle = (usb_host_interface_t *)cdcInstance->controlInterfaceHandle; for (ep_index = 0; ep_index < interfaceHandle->epCount; ++ep_index) { ep_desc = interfaceHandle->epList[ep_index].epDesc; if (((ep_desc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) == USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_IN) && ((ep_desc->bmAttributes & USB_DESCRIPTOR_ENDPOINT_ATTRIBUTE_TYPE_MASK) == USB_ENDPOINT_INTERRUPT)) { pipeInit.devInstance = cdcInstance->deviceHandle; pipeInit.pipeType = USB_ENDPOINT_INTERRUPT; pipeInit.direction = USB_IN; pipeInit.endpointAddress = (ep_desc->bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_NUMBER_MASK); pipeInit.interval = ep_desc->bInterval; pipeInit.maxPacketSize = (uint16_t)(USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(ep_desc->wMaxPacketSize) & USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_SIZE_MASK); pipeInit.numberPerUframe = (USB_SHORT_FROM_LITTLE_ENDIAN_ADDRESS(ep_desc->wMaxPacketSize) & USB_DESCRIPTOR_ENDPOINT_MAXPACKETSIZE_MULT_TRANSACTIONS_MASK); pipeInit.nakCount = USB_HOST_CONFIG_MAX_NAK; cdcInstance->packetSize = pipeInit.maxPacketSize; status = USB_HostOpenPipe(cdcInstance->hostHandle, &cdcInstance->interruptPipe, &pipeInit); if (status != kStatus_USB_Success) { #ifdef HOST_ECHO usb_echo("USB_HostCdcSetControlInterface fail to open pipe\r\n"); #endif return kStatus_USB_Error; } } } return kStatus_USB_Success; }
/*! * @brief de-initialize the cdc instance. * * This function release the resource for cdc instance. * * @param deviceHandle the device handle. * @param classHandle the class handle. * * @retval kStatus_USB_Success The device is de-initialized successfully. */ usb_status_t USB_HostCdcDeinit(usb_device_handle deviceHandle, usb_host_class_handle classHandle) { usb_status_t status; usb_host_cdc_instance_struct_t *cdcInstance = (usb_host_cdc_instance_struct_t *)classHandle; if (deviceHandle == NULL) { return kStatus_USB_InvalidHandle; } if (classHandle != NULL) { if (cdcInstance->interruptPipe != NULL) { status = USB_HostCancelTransfer(cdcInstance->hostHandle, cdcInstance->interruptPipe, NULL); status = USB_HostClosePipe(cdcInstance->hostHandle, cdcInstance->interruptPipe); if (status != kStatus_USB_Success) { #ifdef HOST_ECHO usb_echo("error when close pipe\r\n"); #endif } cdcInstance->interruptPipe = NULL; } USB_HostCloseDeviceInterface(deviceHandle, cdcInstance->controlInterfaceHandle); if (cdcInstance->inPipe != NULL) { status = USB_HostCancelTransfer(cdcInstance->hostHandle, cdcInstance->inPipe, NULL); status = USB_HostClosePipe(cdcInstance->hostHandle, cdcInstance->inPipe); if (status != kStatus_USB_Success) { #ifdef HOST_ECHO usb_echo("error when close pipe\r\n"); #endif } cdcInstance->inPipe = NULL; } if (cdcInstance->outPipe != NULL) { status = USB_HostCancelTransfer(cdcInstance->hostHandle, cdcInstance->outPipe, NULL); status = USB_HostClosePipe(cdcInstance->hostHandle, cdcInstance->outPipe); if (status != kStatus_USB_Success) { #ifdef HOST_ECHO usb_echo("error when close pipe\r\n"); #endif } cdcInstance->outPipe = NULL; } if ((cdcInstance->controlPipe != NULL) && (cdcInstance->controlTransfer != NULL)) { status = USB_HostCancelTransfer(cdcInstance->hostHandle, cdcInstance->controlPipe, cdcInstance->controlTransfer); } USB_HostCloseDeviceInterface(deviceHandle, cdcInstance->dataInterfaceHandle); USB_OsaMemoryFree(cdcInstance); } else { USB_HostCloseDeviceInterface(deviceHandle, NULL); } return kStatus_USB_Success; }
/*! * @brief set data interface. * * This function bind the control interface with the cdc instance. * * @param classHandle the class handle. * @param interfaceHandle the data interface handle. * @param alternateSetting the alternate setting value. * @param callbackFn this callback is called after this function completes. * @param callbackParam the first parameter in the callback function. * * @retval kStatus_USB_Success The device is initialized successfully. * @retval kStatus_USB_InvalidHandle The classHandle is NULL pointer. * @retval kStatus_USB_Busy There is no idle transfer. * @retval kStatus_USB_Error send transfer fail, please reference to USB_HostSendSetup. * @retval kStatus_USB_Busy callback return status, there is no idle pipe. * @retval kStatus_USB_TransferStall callback return status, the transfer is stall by device. * @retval kStatus_USB_Error callback return status, open pipe fail, please reference to USB_HostOpenPipe. */ usb_status_t USB_HostCdcSetDataInterface(usb_host_class_handle classHandle, usb_host_interface_handle interfaceHandle, uint8_t alternateSetting, transfer_callback_t callbackFn, void *callbackParam) { usb_status_t status; usb_host_cdc_instance_struct_t *cdcInstance = (usb_host_cdc_instance_struct_t *)classHandle; usb_host_transfer_t *transfer; status = kStatus_USB_Success; if (classHandle == NULL) { return kStatus_USB_InvalidParameter; } cdcInstance->dataInterfaceHandle = interfaceHandle; /* cancel transfers */ if (cdcInstance->inPipe != NULL) { status = USB_HostCancelTransfer(cdcInstance->hostHandle, cdcInstance->inPipe, NULL); if (status != kStatus_USB_Success) { #ifdef HOST_ECHO usb_echo("error when cancel pipe\r\n"); #endif } } if (cdcInstance->outPipe != NULL) { status = USB_HostCancelTransfer(cdcInstance->hostHandle, cdcInstance->outPipe, NULL); if (status != kStatus_USB_Success) { #ifdef HOST_ECHO usb_echo("error when cancel pipe\r\n"); #endif } } if (alternateSetting == 0) { if (callbackFn != NULL) { status = USB_HostCdcOpenDataInterface(cdcInstance); callbackFn(callbackParam, NULL, 0, status); } } else { if (USB_HostMallocTransfer(cdcInstance->hostHandle, &transfer) != kStatus_USB_Success) { #ifdef HOST_ECHO usb_echo("error to get transfer\r\n"); #endif return kStatus_USB_Error; } cdcInstance->controlCallbackFn = callbackFn; cdcInstance->controlCallbackParam = callbackParam; /* initialize transfer */ transfer->callbackFn = USB_HostCdcSetDataInterfaceCallback; transfer->callbackParam = cdcInstance; transfer->setupPacket.bRequest = USB_REQUEST_STANDARD_SET_INTERFACE; transfer->setupPacket.bmRequestType = USB_REQUEST_TYPE_RECIPIENT_INTERFACE; transfer->setupPacket.wIndex = USB_SHORT_TO_LITTLE_ENDIAN( ((usb_host_interface_t *)cdcInstance->dataInterfaceHandle)->interfaceDesc->bInterfaceNumber); transfer->setupPacket.wValue = USB_SHORT_TO_LITTLE_ENDIAN(alternateSetting); transfer->setupPacket.wLength = 0; transfer->transferBuffer = NULL; transfer->transferLength = 0; status = USB_HostSendSetup(cdcInstance->hostHandle, cdcInstance->controlPipe, transfer); if (status == kStatus_USB_Success) { cdcInstance->controlTransfer = transfer; } else { USB_HostFreeTransfer(cdcInstance->hostHandle, transfer); } } return status; }