/*! * @brief Handle get status request. * * This function is used to handle get status request. * * @param handle The device handle. It equals the value returned from USB_DeviceInit. * @param setup The pointer of the setup packet. * @param buffer It is an out parameter, is used to save the buffer address to response the host's request. * @param length It is an out parameter, the data length. * * @retval kStatus_USB_Success The requst is handled successfully. * @retval kStatus_USB_InvalidRequest The request can not be handle in current device state, * or, the request is unsupported. */ static usb_status_t USB_DeviceCh9GetStatus(usb_device_common_class_struct_t *classHandle, usb_setup_struct_t *setup, uint8_t **buffer, uint32_t *length) { usb_status_t error = kStatus_USB_InvalidRequest; uint8_t state; USB_DeviceGetStatus(classHandle->handle, kUSB_DeviceStatusDeviceState, &state); if ((kUSB_DeviceStateAddress != state) && (kUSB_DeviceStateConfigured != state)) { return error; } if ((setup->bmRequestType & USB_REQUEST_TYPE_RECIPIENT_MASK) == USB_REQUEST_TYPE_RECIPIENT_DEVICE) { /* Get the device status */ error = USB_DeviceGetStatus(classHandle->handle, kUSB_DeviceStatusDevice, &classHandle->standardTranscationBuffer); classHandle->standardTranscationBuffer = classHandle->standardTranscationBuffer & USB_GET_STATUS_DEVICE_MASK; classHandle->standardTranscationBuffer = USB_SHORT_TO_LITTLE_ENDIAN(classHandle->standardTranscationBuffer); /* The device status length must be USB_DEVICE_STATUS_SIZE. */ *length = USB_DEVICE_STATUS_SIZE; } else if ((setup->bmRequestType & USB_REQUEST_TYPE_RECIPIENT_MASK) == USB_REQUEST_TYPE_RECIPIENT_INTERFACE) { /* Get the interface status */ error = kStatus_USB_Success; classHandle->standardTranscationBuffer = 0U; /* The interface status length must be USB_INTERFACE_STATUS_SIZE. */ *length = USB_INTERFACE_STATUS_SIZE; } else if ((setup->bmRequestType & USB_REQUEST_TYPE_RECIPIENT_MASK) == USB_REQUEST_TYPE_RECIPIENT_ENDPOINT) { /* Get the endpoint status */ usb_device_endpoint_status_struct_t endpointStatus; endpointStatus.endpointAddress = (uint8_t)setup->wIndex; endpointStatus.endpointStatus = kUSB_DeviceEndpointStateIdle; error = USB_DeviceGetStatus(classHandle->handle, kUSB_DeviceStatusEndpoint, &endpointStatus); classHandle->standardTranscationBuffer = endpointStatus.endpointStatus & USB_GET_STATUS_ENDPOINT_MASK; classHandle->standardTranscationBuffer = USB_SHORT_TO_LITTLE_ENDIAN(classHandle->standardTranscationBuffer); /* The endpoint status length must be USB_INTERFACE_STATUS_SIZE. */ *length = USB_ENDPOINT_STATUS_SIZE; } else { } *buffer = (uint8_t *)&classHandle->standardTranscationBuffer; return error; }
/*! * @brief cdc send control transfer common code. * * @param classHandle the class handle. * @param request_type setup packet request type. * @param request setup packet request value. * @param wvalue_l setup packet wvalue low byte. * @param wvalue_h setup packet wvalue high byte. * @param wlength setup packet wlength value. * @param data data buffer pointer * @param callbackFn this callback is called after this function completes. * @param callbackParam the first parameter in the callback function. * * @return An error code or kStatus_USB_Success. */ usb_status_t USB_HostCdcControl(usb_host_class_handle classHandle, uint8_t request_type, uint8_t request, uint8_t wvalue_l, uint8_t wvalue_h, uint16_t wlength, uint8_t *data, transfer_callback_t callbackFn, void *callbackParam) { usb_host_cdc_instance_struct_t *cdcInstance = (usb_host_cdc_instance_struct_t *)classHandle; usb_host_transfer_t *transfer; if (classHandle == NULL) { return kStatus_USB_InvalidHandle; } 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; transfer->transferBuffer = data; transfer->transferLength = wlength; transfer->callbackFn = USB_HostCdcControlPipeCallback; transfer->callbackParam = cdcInstance; transfer->setupPacket.bmRequestType = request_type; transfer->setupPacket.bRequest = request; transfer->setupPacket.wValue = (wvalue_l | (uint16_t)((uint16_t)wvalue_h << 8)); transfer->setupPacket.wIndex = USB_SHORT_TO_LITTLE_ENDIAN( ((usb_host_interface_t *)cdcInstance->controlInterfaceHandle)->interfaceDesc->bInterfaceNumber); transfer->setupPacket.wLength = USB_SHORT_TO_LITTLE_ENDIAN(wlength); if (USB_HostSendSetup(cdcInstance->hostHandle, cdcInstance->controlPipe, transfer) != kStatus_USB_Success) { #ifdef HOST_ECHO usb_echo("failt for USB_HostSendSetup\r\n"); #endif USB_HostFreeTransfer(cdcInstance->hostHandle, transfer); return kStatus_USB_Error; } cdcInstance->controlTransfer = transfer; return kStatus_USB_Success; }
static usb_status_t USB_HostCdcClearHalt(usb_host_cdc_instance_struct_t *cdcInstance, usb_host_transfer_t *stallTransfer, host_inner_transfer_callback_t callbackFn, uint8_t endpoint) { usb_status_t status; usb_host_transfer_t *transfer; /* malloc one transfer */ status = USB_HostMallocTransfer(cdcInstance->hostHandle, &transfer); if (status != kStatus_USB_Success) { #ifdef HOST_ECHO usb_echo("allocate transfer error\r\n"); #endif return status; } cdcInstance->stallDataBuffer = stallTransfer->transferBuffer; cdcInstance->stallDataLength = stallTransfer->transferSofar; /* save the application callback function */ cdcInstance->controlCallbackFn = NULL; cdcInstance->controlCallbackParam = NULL; /* initialize transfer */ transfer->callbackFn = callbackFn; transfer->callbackParam = cdcInstance; transfer->transferBuffer = NULL; transfer->transferLength = 0; transfer->setupPacket.bRequest = USB_REQUEST_STANDARD_CLEAR_FEATURE; transfer->setupPacket.bmRequestType = USB_REQUEST_TYPE_RECIPIENT_ENDPOINT; transfer->setupPacket.wValue = USB_SHORT_TO_LITTLE_ENDIAN(USB_REQUEST_STANDARD_FEATURE_SELECTOR_ENDPOINT_HALT); transfer->setupPacket.wIndex = USB_SHORT_TO_LITTLE_ENDIAN(endpoint); transfer->setupPacket.wLength = 0; status = USB_HostSendSetup(cdcInstance->hostHandle, cdcInstance->controlPipe, transfer); if (status != kStatus_USB_Success) { USB_HostFreeTransfer(cdcInstance->hostHandle, transfer); } cdcInstance->controlTransfer = transfer; return status; }
/*! * @brief Handle get the alternate setting of a interface request. * * This function is used to handle get the alternate setting of a interface request. * * @param handle The device handle. It equals the value returned from USB_DeviceInit. * @param setup The pointer of the setup packet. * @param buffer It is an out parameter, is used to save the buffer address to response the host's request. * @param length It is an out parameter, the data length. * * @retval kStatus_USB_Success The requst is handled successfully. * @retval kStatus_USB_InvalidRequest The request can not be handle in current device state, * or, the request is unsupported. */ static usb_status_t USB_DeviceCh9GetInterface(usb_device_common_class_struct_t *classHandle, usb_setup_struct_t *setup, uint8_t **buffer, uint32_t *length) { usb_status_t error = kStatus_USB_InvalidRequest; uint8_t state; USB_DeviceGetStatus(classHandle->handle, kUSB_DeviceStatusDeviceState, &state); if (state != kUSB_DeviceStateConfigured) { return error; } *length = USB_INTERFACE_SIZE; *buffer = (uint8_t *)&classHandle->standardTranscationBuffer; classHandle->standardTranscationBuffer = (uint16_t)(((uint32_t)setup->wIndex & 0xFFU) << 8U); /* The Bit[15~8] is used to save the interface index, and the alternate setting will be saved in Bit[7~0] by * application. */ error = USB_DeviceClassCallback(classHandle->handle, kUSB_DeviceEventGetInterface, &classHandle->standardTranscationBuffer); classHandle->standardTranscationBuffer = USB_SHORT_TO_LITTLE_ENDIAN(classHandle->standardTranscationBuffer); return error; }
/*! * @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; }