/*! * @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 Handle set current configuration request. * * This function is used to handle set current configuration 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_DeviceCh9SetConfiguration(usb_device_common_class_struct_t *classHandle, usb_setup_struct_t *setup, uint8_t **buffer, uint32_t *length) { uint8_t state; USB_DeviceGetStatus(classHandle->handle, kUSB_DeviceStatusDeviceState, &state); if ((kUSB_DeviceStateAddress != state) && (kUSB_DeviceStateConfigured != state)) { return kStatus_USB_InvalidRequest; } /* The device state is changed to kUSB_DeviceStateConfigured */ state = kUSB_DeviceStateConfigured; USB_DeviceSetStatus(classHandle->handle, kUSB_DeviceStatusDeviceState, &state); if (!setup->wValue) { /* If the new configuration is zero, the device state is changed to kUSB_DeviceStateAddress */ state = kUSB_DeviceStateAddress; USB_DeviceSetStatus(classHandle->handle, kUSB_DeviceStatusDeviceState, &state); } /* Notify the class layer the configuration is changed */ USB_DeviceClassEvent(classHandle->handle, kUSB_DeviceClassEventSetConfiguration, &setup->wValue); /* Notify the application the configuration is changed */ return USB_DeviceClassCallback(classHandle->handle, kUSB_DeviceEventSetConfiguration, &setup->wValue); }
/*! * @brief USB device callback function. * * This function handles the usb device specific requests. * * @param handle The USB device handle. * @param event The USB device event type. * @param param The parameter of the device specific request. * * @return A USB error code or kStatus_USB_Success. */ usb_status_t USB_DeviceCallback(usb_device_handle handle, uint32_t event, void *param) { usb_status_t error = kStatus_USB_Error; uint8_t *temp8 = (uint8_t *)param; switch (event) { case kUSB_DeviceEventBusReset: { USB_DeviceControlPipeInit(handle); g_composite.attach = 0; #if defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 0) if (kStatus_USB_Success == USB_DeviceGetStatus(handle, kUSB_DeviceStatusSpeed, &g_composite.speed)) { USB_DeviceSetSpeed(handle, g_composite.speed); } #endif } break; case kUSB_DeviceEventSetConfiguration: if (param) { g_composite.attach = 1; g_composite.currentConfiguration = *temp8; USB_DeviceCdcVcomSetConfigure(handle, *temp8); USB_DeviceMscDiskSetConfigure(handle, *temp8); error = kStatus_USB_Success; } break; default: break; } return error; }
/*! * @brief USB device callback function. * * This function handles the usb device specific requests. * * @param handle The USB device handle. * @param event The USB device event type. * @param param The parameter of the device specific request. * * @return A USB error code or kStatus_USB_Success. */ usb_status_t USB_DeviceCallback(usb_device_handle handle, uint32_t event, void *param) { usb_status_t error = kStatus_USB_Error; uint8_t *temp8 = (uint8_t *)param; switch (event) { case kUSB_DeviceEventBusReset: { /* USB bus reset signal detected */ /* Initialize the control IN and OUT pipes */ USB_DeviceControlPipeInit(handle); g_composite.attach = 0U; g_InterfaceIsSet = 0U; #if defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 0U) if (kStatus_USB_Success == USB_DeviceGetStatus(handle, kUSB_DeviceStatusSpeed, &g_composite.speed)) { USB_DeviceSetSpeed(g_composite.speed); } #endif } break; case kUSB_DeviceEventSetConfiguration: if (USB_COMPOSITE_CONFIGURE_INDEX == (*temp8)) { g_composite.attach = 1U; g_composite.currentConfiguration = *temp8; USB_DeviceAudioGeneratorSetConfigure(handle, *temp8); USB_DeviceHidMouseSetConfigure(handle, *temp8); error = kStatus_USB_Success; } break; case kUSB_DeviceEventSetInterface: if (g_composite.attach) { uint8_t interface = (uint8_t)(*temp8); uint8_t alternateSetting = (uint8_t)g_UsbDeviceInterface[interface]; if (interface < USB_DEVICE_INTERFACE_COUNT) { if (USB_AUDIO_GENERATOR_STREAM_INTERFACE_INDEX == interface) { USB_DeviceAudioGeneratorSetInterface(handle, interface, alternateSetting); } error = kStatus_USB_Success; } } break; default: break; } return error; }
/*! * @brief Handle get sync frame request. * * This function is used to handle get sync frame 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_DeviceCh9SynchFrame(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; } classHandle->standardTranscationBuffer = setup->wIndex; /* Get the sync frame value */ error = USB_DeviceGetStatus(classHandle->handle, kUSB_DeviceStatusSynchFrame, &classHandle->standardTranscationBuffer); *buffer = (uint8_t *)&classHandle->standardTranscationBuffer; *length = sizeof(classHandle->standardTranscationBuffer); return error; }
/*! * @brief Handle get current configuration request. * * This function is used to handle get current configuration 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_DeviceCh9GetConfiguration(usb_device_common_class_struct_t *classHandle, usb_setup_struct_t *setup, uint8_t **buffer, uint32_t *length) { uint8_t state; USB_DeviceGetStatus(classHandle->handle, kUSB_DeviceStatusDeviceState, &state); if ((kUSB_DeviceStateAddress != state) && ((kUSB_DeviceStateConfigured != state))) { return kStatus_USB_InvalidRequest; } *length = USB_CONFIGURE_SIZE; *buffer = (uint8_t *)&classHandle->standardTranscationBuffer; return USB_DeviceClassCallback(classHandle->handle, kUSB_DeviceEventGetConfiguration, &classHandle->standardTranscationBuffer); }
/*! * @brief Get the USB bus speed. * * This function is used to get the USB bus speed. * * @param controllerId The controller id of the USB IP. Please refer to the enumeration usb_controller_index_t. * @param speed It is an OUT parameter, return current speed of the controller. * * @return A USB error code or kStatus_USB_Success. */ usb_status_t USB_DeviceClassGetSpeed(uint8_t controllerId, /*!< [IN] Controller ID */ uint8_t *speed /*!< [OUT] Current speed */ ) { usb_device_common_class_struct_t *classHandle; usb_status_t error = kStatus_USB_Error; /* Get the common class handle according to the controller id. */ error = USB_DeviceClassGetHandleByControllerId(controllerId, &classHandle); if (kStatus_USB_Success != error) { return error; } /* Get the current speed. */ error = USB_DeviceGetStatus(classHandle->handle, kUSB_DeviceStatusSpeed, speed); return error; }
/* Device callback */ usb_status_t USB_DeviceCallback(usb_device_handle handle, uint32_t event, void *param) { usb_status_t error = kStatus_USB_Success; uint8_t *temp8 = (uint8_t *)param; switch (event) { case kUSB_DeviceEventBusReset: { /* USB bus reset signal detected */ /* Initialize the control IN and OUT pipes */ USB_DeviceControlPipeInit(handle); g_UsbDeviceComposite.attach = 0U; #if defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 0U) /* Get USB speed to configure the device, including max packet size and interval of the endpoints. */ if (kStatus_USB_Success == USB_DeviceGetStatus(handle, kUSB_DeviceStatusSpeed, &g_UsbDeviceComposite.speed)) { USB_DeviceSetSpeed(g_UsbDeviceComposite.speed); } #endif } break; case kUSB_DeviceEventSetConfiguration: if (USB_COMPOSITE_CONFIGURE_INDEX == (*temp8)) { /* If the confguration is valid, set HID keyboard */ USB_DeviceHidKeyboardSetConfigure(handle, (*temp8)); /* If the confguration is valid, set HID mouse */ USB_DeviceHidMouseSetConfigure(handle, (*temp8)); } else { } g_UsbDeviceComposite.attach = 1U; break; default: break; } return error; }
/*! * @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 = setup->wIndex & 0xFFU; /* The Bit[15~8] is used to save the interface index, and the alternate setting will be saved in Bit[7~0] by * application. */ return USB_DeviceClassCallback(classHandle->handle, kUSB_DeviceEventGetInterface, &classHandle->standardTranscationBuffer); }
/*! * @brief Handle set address request. * * This function is used to handle set address 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. */ static usb_status_t USB_DeviceCh9SetAddress(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_DeviceStateAddressing != state) && (kUSB_DeviceStateAddress != state) && (kUSB_DeviceStateDefault != state) && (kUSB_DeviceStateConfigured != state)) { return error; } if (kUSB_DeviceStateAddressing != state) { /* If the device address is not setting, pass the address and the device state will change to * kUSB_DeviceStateAddressing internally. */ state = setup->wValue & 0xFFU; error = USB_DeviceSetStatus(classHandle->handle, kUSB_DeviceStatusAddress, &state); } else { /* If the device address is setting, set device address and the address will be write into the controller * internally. */ error = USB_DeviceSetStatus(classHandle->handle, kUSB_DeviceStatusAddress, NULL); /* And then change the device state to kUSB_DeviceStateAddress. */ if (kStatus_USB_Success == error) { state = kUSB_DeviceStateAddress; error = USB_DeviceSetStatus(classHandle->handle, kUSB_DeviceStatusDeviceState, &state); } } return error; }
/*! * @brief Handle set the alternate setting of a interface request. * * This function is used to handle set 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_DeviceCh9SetInterface(usb_device_common_class_struct_t *classHandle, usb_setup_struct_t *setup, uint8_t **buffer, uint32_t *length) { uint8_t state; USB_DeviceGetStatus(classHandle->handle, kUSB_DeviceStatusDeviceState, &state); if (state != kUSB_DeviceStateConfigured) { return kStatus_USB_InvalidRequest; } classHandle->standardTranscationBuffer = ((setup->wIndex & 0xFFU) << 8U) | (setup->wValue & 0xFFU); /* Notify the class driver the alternate setting of the interface is changed. */ /* The Bit[15~8] is used to save the interface index, and the alternate setting is saved in Bit[7~0]. */ USB_DeviceClassEvent(classHandle->handle, kUSB_DeviceClassEventSetInterface, &classHandle->standardTranscationBuffer); /* Notify the application the alternate setting of the interface is changed. */ /* The Bit[15~8] is used to save the interface index, and the alternate setting will is saved in Bit[7~0]. */ return USB_DeviceClassCallback(classHandle->handle, kUSB_DeviceEventSetInterface, &classHandle->standardTranscationBuffer); }
/*! * @brief Control endpoint callback function. * * This callback function is used to notify uplayer the tranfser result of a transfer. * This callback pointer is passed when a sepcified endpoint initialied by calling API USB_DeviceInitEndpoint. * * @param handle The device handle. It equals the value returned from USB_DeviceInit. * @param message The result of a transfer, includes transfer buffer, transfer length and whether is in setup * phase for control pipe. * @param callbackParam The paramter for this callback. It is same with * usb_device_endpoint_callback_struct_t::callbackParam. * * @return A USB error code or kStatus_USB_Success. */ usb_status_t USB_DeviceControlCallback(usb_device_handle handle, usb_device_endpoint_callback_message_struct_t *message, void *callbackParam) { usb_setup_struct_t *deviceSetup; usb_device_common_class_struct_t *classHandle; uint8_t *buffer = (uint8_t *)NULL; uint32_t length = 0U; usb_status_t error = kStatus_USB_InvalidRequest; uint8_t state; if ((0xFFFFFFFFU == message->length) || (NULL == callbackParam)) { return error; } classHandle = (usb_device_common_class_struct_t *)callbackParam; deviceSetup = (usb_setup_struct_t *)&classHandle->setupBuffer[0]; USB_DeviceGetStatus(handle, kUSB_DeviceStatusDeviceState, &state); if (message->isSetup) { if ((USB_SETUP_PACKET_SIZE != message->length) || (NULL == message->buffer)) { /* If a invalid setup is received, the control pipes should be de-init and init again. * Due to the IP can not meet this require, it is revesed for feature. */ /* USB_DeviceDeinitEndpoint(handle, USB_CONTROL_ENDPOINT | (USB_IN << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT)); USB_DeviceDeinitEndpoint(handle, USB_CONTROL_ENDPOINT | (USB_OUT << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT)); USB_DeviceControlPipeInit(handle, callbackParam); */ return error; } /* Receive a setup request */ usb_setup_struct_t *setup = (usb_setup_struct_t *)(message->buffer); /* Copy the setup packet to the application buffer */ deviceSetup->wValue = USB_SHORT_FROM_LITTLE_ENDIAN(setup->wValue); deviceSetup->wIndex = USB_SHORT_FROM_LITTLE_ENDIAN(setup->wIndex); deviceSetup->wLength = USB_SHORT_FROM_LITTLE_ENDIAN(setup->wLength); deviceSetup->bRequest = setup->bRequest; deviceSetup->bmRequestType = setup->bmRequestType; if ((deviceSetup->bmRequestType & USB_REQUEST_TYPE_TYPE_MASK) == USB_REQUEST_TYPE_TYPE_STANDARD) { /* Handle the standard request */ if (s_UsbDeviceStandardRequest[deviceSetup->bRequest] != (usb_standard_request_callback_t)NULL) { error = s_UsbDeviceStandardRequest[deviceSetup->bRequest](classHandle, deviceSetup, &buffer, &length); } } else { if ((deviceSetup->wLength) && ((deviceSetup->bmRequestType & USB_REQUEST_TYPE_DIR_MASK) == USB_REQUEST_TYPE_DIR_OUT)) { /* Class or vendor request with the OUT data phase. */ if ((deviceSetup->wLength) && ((deviceSetup->bmRequestType & USB_REQUEST_TYPE_TYPE_CLASS) == USB_REQUEST_TYPE_TYPE_CLASS)) { /* Get data buffer to receive the data from the host. */ usb_device_control_request_struct_t controlRequest; controlRequest.buffer = (uint8_t *)NULL; controlRequest.isSetup = 1U; controlRequest.setup = deviceSetup; controlRequest.length = deviceSetup->wLength; error = USB_DeviceClassEvent(handle, kUSB_DeviceClassEventClassRequest, &controlRequest); length = controlRequest.length; buffer = controlRequest.buffer; } else if ((deviceSetup->wLength) && ((deviceSetup->bmRequestType & USB_REQUEST_TYPE_TYPE_VENDOR) == USB_REQUEST_TYPE_TYPE_VENDOR)) { /* Get data buffer to receive the data from the host. */ usb_device_control_request_struct_t controlRequest; controlRequest.buffer = (uint8_t *)NULL; controlRequest.isSetup = 1U; controlRequest.setup = deviceSetup; controlRequest.length = deviceSetup->wLength; error = USB_DeviceClassCallback(handle, kUSB_DeviceEventVendorRequest, &controlRequest); length = controlRequest.length; buffer = controlRequest.buffer; } else { } if (kStatus_USB_Success == error) { /* Prime an OUT transfer */ error = USB_DeviceRecvRequest(handle, USB_CONTROL_ENDPOINT, buffer, deviceSetup->wLength); return error; } } else { /* Class or vendor request with the IN data phase. */ if (((deviceSetup->bmRequestType & USB_REQUEST_TYPE_TYPE_CLASS) == USB_REQUEST_TYPE_TYPE_CLASS)) { /* Get data buffer to response the host. */ usb_device_control_request_struct_t controlRequest; controlRequest.buffer = (uint8_t *)NULL; controlRequest.isSetup = 1U; controlRequest.setup = deviceSetup; controlRequest.length = deviceSetup->wLength; error = USB_DeviceClassEvent(handle, kUSB_DeviceClassEventClassRequest, &controlRequest); length = controlRequest.length; buffer = controlRequest.buffer; } else if (((deviceSetup->bmRequestType & USB_REQUEST_TYPE_TYPE_VENDOR) == USB_REQUEST_TYPE_TYPE_VENDOR)) { /* Get data buffer to response the host. */ usb_device_control_request_struct_t controlRequest; controlRequest.buffer = (uint8_t *)NULL; controlRequest.isSetup = 1U; controlRequest.setup = deviceSetup; controlRequest.length = deviceSetup->wLength; error = USB_DeviceClassCallback(handle, kUSB_DeviceEventVendorRequest, &controlRequest); length = controlRequest.length; buffer = controlRequest.buffer; } else { } } } /* Send the reponse to the host. */ error = USB_DeviceControlCallbackFeedback(handle, deviceSetup, error, kUSB_DeviceControlPipeSetupStage, &buffer, &length); } else if (kUSB_DeviceStateAddressing == state) { /* Set the device address to controller. */ error = s_UsbDeviceStandardRequest[deviceSetup->bRequest](classHandle, deviceSetup, &buffer, &length); } #if (defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 0U)) && \ (defined(USB_DEVICE_CONFIG_EHCI_TEST_MODE) && (USB_DEVICE_CONFIG_EHCI_TEST_MODE > 0U)) else if (kUSB_DeviceStateTestMode == state) { uint8_t portTestControl = (uint8_t)(deviceSetup->wIndex >> 8); /* Set the controller.into test mode. */ error = USB_DeviceSetStatus(handle, kUSB_DeviceStatusTestMode, &portTestControl); }
/*! * @brief Handle get descriptor request. * * This function is used to handle get descriptor 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_DeviceCh9GetDescriptor(usb_device_common_class_struct_t *classHandle, usb_setup_struct_t *setup, uint8_t **buffer, uint32_t *length) { usb_device_get_descriptor_common_union_t commonDescriptor; usb_status_t error = kStatus_USB_InvalidRequest; uint8_t state; uint8_t descriptorType = (uint8_t)((setup->wValue & 0xFF00U) >> 8U); uint8_t descriptorIndex = (uint8_t)((setup->wValue & 0x00FFU)); USB_DeviceGetStatus(classHandle->handle, kUSB_DeviceStatusDeviceState, &state); if ((kUSB_DeviceStateAddress != state) && (kUSB_DeviceStateConfigured != state) && (kUSB_DeviceStateDefault != state)) { return error; } commonDescriptor.commonDescriptor.length = setup->wLength; if (USB_DESCRIPTOR_TYPE_DEVICE == descriptorType) { /* Get the device descriptor */ error = USB_DeviceClassCallback(classHandle->handle, kUSB_DeviceEventGetDeviceDescriptor, &commonDescriptor.deviceDescriptor); } else if (USB_DESCRIPTOR_TYPE_CONFIGURE == descriptorType) { /* Get the configuration descriptor */ commonDescriptor.configurationDescriptor.configuration = descriptorIndex; error = USB_DeviceClassCallback(classHandle->handle, kUSB_DeviceEventGetConfigurationDescriptor, &commonDescriptor.configurationDescriptor); } else if (USB_DESCRIPTOR_TYPE_STRING == descriptorType) { /* Get the string descriptor */ commonDescriptor.stringDescriptor.stringIndex = descriptorIndex; commonDescriptor.stringDescriptor.languageId = setup->wIndex; error = USB_DeviceClassCallback(classHandle->handle, kUSB_DeviceEventGetStringDescriptor, &commonDescriptor.stringDescriptor); } #if (defined(USB_DEVICE_CONFIG_HID) && (USB_DEVICE_CONFIG_HID > 0U)) else if (USB_DESCRIPTOR_TYPE_HID == descriptorType) { /* Get the hid descriptor */ commonDescriptor.hidDescriptor.interfaceNumber = setup->wIndex; error = USB_DeviceClassCallback(classHandle->handle, kUSB_DeviceEventGetHidDescriptor, &commonDescriptor.hidDescriptor); } else if (USB_DESCRIPTOR_TYPE_HID_REPORT == descriptorType) { /* Get the hid report descriptor */ commonDescriptor.hidReportDescriptor.interfaceNumber = setup->wIndex; error = USB_DeviceClassCallback(classHandle->handle, kUSB_DeviceEventGetHidReportDescriptor, &commonDescriptor.hidReportDescriptor); } else if (USB_DESCRIPTOR_TYPE_HID_PHYSICAL == descriptorType) { /* Get the hid physical descriptor */ commonDescriptor.hidPhysicalDescriptor.index = descriptorIndex; commonDescriptor.hidPhysicalDescriptor.interfaceNumber = setup->wIndex; error = USB_DeviceClassCallback(classHandle->handle, kUSB_DeviceEventGetHidPhysicalDescriptor, &commonDescriptor.hidPhysicalDescriptor); } #endif #if (defined(USB_DEVICE_CONFIG_EHCI_TEST_MODE) && (USB_DEVICE_CONFIG_EHCI_TEST_MODE > 0U)) else if (USB_DESCRIPTOR_TYPE_DEVICE_QUALITIER == descriptorType) { /* Get the device descriptor */ error = USB_DeviceClassCallback(classHandle->handle, kUSB_DeviceEventGetDeviceQualifierDescriptor, &commonDescriptor.deviceDescriptor); } #endif else { } *buffer = commonDescriptor.commonDescriptor.buffer; *length = commonDescriptor.commonDescriptor.length; return error; }
/*! * @brief Handle set or clear device feature request. * * This function is used to handle set or clear device feature 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_DeviceCh9SetClearFeature(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; uint8_t isSet = 0U; USB_DeviceGetStatus(classHandle->handle, kUSB_DeviceStatusDeviceState, &state); if ((kUSB_DeviceStateAddress != state) && (kUSB_DeviceStateConfigured != state)) { return error; } /* Identify the request is set or clear the feature. */ if (USB_REQUEST_STANDARD_SET_FEATURE == setup->bRequest) { isSet = 1U; } if ((setup->bmRequestType & USB_REQUEST_TYPE_RECIPIENT_MASK) == USB_REQUEST_TYPE_RECIPIENT_DEVICE) { /* Set or Clear the device featrue. */ if (USB_REQUEST_STANDARD_FEATURE_SELECTOR_DEVICE_REMOTE_WAKEUP == setup->wValue) { /* Set or Clear the device remote wakeup featrue. */ error = USB_DeviceClassCallback(classHandle->handle, kUSB_DeviceEventSetRemoteWakeup, &isSet); } #if (defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 0U)) && \ (defined(USB_DEVICE_CONFIG_EHCI_TEST_MODE) && (USB_DEVICE_CONFIG_EHCI_TEST_MODE > 0U)) else if (USB_REQUEST_STANDARD_FEATURE_SELECTOR_DEVICE_TEST_MODE == setup->wValue) { state = kUSB_DeviceStateTestMode; error = USB_DeviceSetStatus(classHandle->handle, kUSB_DeviceStatusDeviceState, &state); } #endif else { } } else if ((setup->bmRequestType & USB_REQUEST_TYPE_RECIPIENT_MASK) == USB_REQUEST_TYPE_RECIPIENT_ENDPOINT) { /* Set or Clear the endpoint featrue. */ if (USB_REQUEST_STANDARD_FEATURE_SELECTOR_ENDPOINT_HALT == setup->wValue) { if (USB_CONTROL_ENDPOINT == (setup->wIndex & USB_ENDPOINT_NUMBER_MASK)) { /* Set or Clear the control endpoint status(halt or not). */ if (isSet) { USB_DeviceStallEndpoint(classHandle->handle, (uint8_t)setup->wIndex); } else { USB_DeviceUnstallEndpoint(classHandle->handle, (uint8_t)setup->wIndex); } } /* Set or Clear the endpoint status featrue. */ if (isSet) { error = USB_DeviceClassEvent(classHandle->handle, kUSB_DeviceClassEventSetEndpointHalt, &setup->wIndex); } else { error = USB_DeviceClassEvent(classHandle->handle, kUSB_DeviceClassEventClearEndpointHalt, &setup->wIndex); } } else { } } else { } return error; }
/*! * @brief USB device callback function. * * This function handles the usb device specific requests. * * @param handle The USB device handle. * @param event The USB device event type. * @param param The parameter of the device specific request. * * @return A USB error code or kStatus_USB_Success. */ usb_status_t USB_DeviceCallback(usb_device_handle handle, uint32_t event, void *param) { usb_status_t error = kStatus_USB_Error; uint8_t *temp8 = (uint8_t *)param; switch (event) { case kUSB_DeviceEventBusReset: { USB_DeviceControlPipeInit(s_cdcVcom.deviceHandle); s_cdcVcom.attach = 0; #if (defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 0)) || \ (defined(USB_DEVICE_CONFIG_LPCIP3511HS) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U)) if (kStatus_USB_Success == USB_DeviceGetStatus(s_cdcVcom.deviceHandle, kUSB_DeviceStatusSpeed, &s_cdcVcom.speed)) { USB_DeviceSetSpeed(handle, s_cdcVcom.speed); } #endif } break; case kUSB_DeviceEventSetConfiguration: if (param) { s_cdcVcom.attach = 1; s_cdcVcom.currentConfiguration = *temp8; if (USB_CDC_VCOM_CONFIGURE_INDEX == (*temp8)) { usb_device_endpoint_init_struct_t epInitStruct; usb_device_endpoint_callback_struct_t endpointCallback; /* Initiailize endpoint for interrupt pipe */ endpointCallback.callbackFn = USB_DeviceCdcAcmInterruptIn; endpointCallback.callbackParam = handle; epInitStruct.zlt = 0; epInitStruct.transferType = USB_ENDPOINT_INTERRUPT; epInitStruct.endpointAddress = USB_CDC_VCOM_INTERRUPT_IN_ENDPOINT | (USB_IN << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT); if (USB_SPEED_HIGH == s_cdcVcom.speed) { epInitStruct.maxPacketSize = HS_CDC_VCOM_INTERRUPT_IN_PACKET_SIZE; } else { epInitStruct.maxPacketSize = FS_CDC_VCOM_INTERRUPT_IN_PACKET_SIZE; } USB_DeviceInitEndpoint(s_cdcVcom.deviceHandle, &epInitStruct, &endpointCallback); /* Initiailize endpoints for bulk pipe */ endpointCallback.callbackFn = USB_DeviceCdcAcmBulkIn; endpointCallback.callbackParam = handle; epInitStruct.zlt = 0; epInitStruct.transferType = USB_ENDPOINT_BULK; epInitStruct.endpointAddress = USB_CDC_VCOM_BULK_IN_ENDPOINT | (USB_IN << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT); if (USB_SPEED_HIGH == s_cdcVcom.speed) { epInitStruct.maxPacketSize = HS_CDC_VCOM_BULK_IN_PACKET_SIZE; } else { epInitStruct.maxPacketSize = FS_CDC_VCOM_BULK_IN_PACKET_SIZE; } USB_DeviceInitEndpoint(s_cdcVcom.deviceHandle, &epInitStruct, &endpointCallback); endpointCallback.callbackFn = USB_DeviceCdcAcmBulkOut; endpointCallback.callbackParam = handle; epInitStruct.zlt = 0; epInitStruct.transferType = USB_ENDPOINT_BULK; epInitStruct.endpointAddress = USB_CDC_VCOM_BULK_OUT_ENDPOINT | (USB_OUT << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT); if (USB_SPEED_HIGH == s_cdcVcom.speed) { epInitStruct.maxPacketSize = HS_CDC_VCOM_BULK_OUT_PACKET_SIZE; } else { epInitStruct.maxPacketSize = FS_CDC_VCOM_BULK_OUT_PACKET_SIZE; } USB_DeviceInitEndpoint(s_cdcVcom.deviceHandle, &epInitStruct, &endpointCallback); if (USB_SPEED_HIGH == s_cdcVcom.speed) { s_usbBulkMaxPacketSize = HS_CDC_VCOM_BULK_OUT_PACKET_SIZE; } else { s_usbBulkMaxPacketSize = FS_CDC_VCOM_BULK_OUT_PACKET_SIZE; } } } break; default: break; } return error; }
/* The device callback */ static usb_status_t USB_DeviceCallback(usb_device_handle handle, uint32_t event, void *param) { usb_status_t error = kStatus_USB_Success; uint8_t *temp8 = (uint8_t *)param; uint16_t *temp16 = (uint16_t *)param; switch (event) { case kUSB_DeviceEventBusReset: { /* The device BUS reset signal detected */ USB_DeviceVideoApplicationSetDefault(); #if defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 0U) if (kStatus_USB_Success == USB_DeviceGetStatus(g_UsbDeviceVideoVirtualCamera.deviceHandle, kUSB_DeviceStatusSpeed, &g_UsbDeviceVideoVirtualCamera.speed)) { USB_DeviceSetSpeed(g_UsbDeviceVideoVirtualCamera.deviceHandle, g_UsbDeviceVideoVirtualCamera.speed); } if (USB_SPEED_HIGH == g_UsbDeviceVideoVirtualCamera.speed) { g_UsbDeviceVideoVirtualCamera.currentMaxPacketSize = HS_STREAM_IN_PACKET_SIZE; } #endif } break; case kUSB_DeviceEventSetConfiguration: if (USB_VIDEO_VIRTUAL_CAMERA_CONFIGURE_INDEX == (*temp8)) { /* Set the configuration request */ g_UsbDeviceVideoVirtualCamera.attach = 1U; g_UsbDeviceVideoVirtualCamera.currentConfiguration = *temp8; } break; case kUSB_DeviceEventSetInterface: if ((g_UsbDeviceVideoVirtualCamera.attach) && param) { /* Set alternateSetting of the interface request */ uint8_t interface = (uint8_t)((*temp16 & 0xFF00U) >> 0x08U); uint8_t alternateSetting = (uint8_t)(*temp16 & 0x00FFU); if (g_UsbDeviceVideoVirtualCamera.currentInterfaceAlternateSetting[interface] != alternateSetting) { if (!g_UsbDeviceVideoVirtualCamera.currentInterfaceAlternateSetting[interface]) { if (USB_VIDEO_VIRTUAL_CAMERA_STREAM_INTERFACE_INDEX == interface) { USB_DeviceVideoPrepareVideoData(); error = USB_DeviceSendRequest(g_UsbDeviceVideoVirtualCamera.deviceHandle, USB_VIDEO_VIRTUAL_CAMERA_STREAM_ENDPOINT_IN, g_UsbDeviceVideoVirtualCamera.imageBuffer, g_UsbDeviceVideoVirtualCamera.imageBufferLength); } } g_UsbDeviceVideoVirtualCamera.currentInterfaceAlternateSetting[interface] = alternateSetting; } } break; case kUSB_DeviceEventGetConfiguration: if (param) { /* Get the current configuration request */ *temp8 = g_UsbDeviceVideoVirtualCamera.currentConfiguration; error = kStatus_USB_Success; } break; case kUSB_DeviceEventGetInterface: if (param) { /* Set the alternateSetting of the interface request */ uint8_t interface = (uint8_t)((*temp16 & 0xFF00U) >> 0x08U); if (interface < USB_VIDEO_VIRTUAL_CAMERA_INTERFACE_COUNT) { *temp16 = (*temp16 & 0xFF00U) | g_UsbDeviceVideoVirtualCamera.currentInterfaceAlternateSetting[interface]; error = kStatus_USB_Success; } else { error = kStatus_USB_InvalidRequest; } } break; case kUSB_DeviceEventGetDeviceDescriptor: if (param) { /* Get the device descriptor request */ error = USB_DeviceGetDeviceDescriptor(handle, (usb_device_get_device_descriptor_struct_t *)param); } break; case kUSB_DeviceEventGetConfigurationDescriptor: if (param) { /* Get the configuration descriptor request */ error = USB_DeviceGetConfigurationDescriptor(handle, (usb_device_get_configuration_descriptor_struct_t *)param); } break; case kUSB_DeviceEventGetStringDescriptor: if (param) { /* Get the string descriptor request */ error = USB_DeviceGetStringDescriptor(handle, (usb_device_get_string_descriptor_struct_t *)param); } break; default: break; }