/*************************************************************************** * Copyright (c) 2024 Microsoft Corporation * Copyright (c) 2026-present Eclipse ThreadX contributors * * This program and the accompanying materials are made available under the * terms of the MIT License which is available at * https://opensource.org/licenses/MIT. * * SPDX-License-Identifier: MIT **************************************************************************/ /**************************************************************************/ /** */ /** USBX Component */ /** */ /** Device CDC Class */ /** */ /**************************************************************************/ /**************************************************************************/ #define UX_SOURCE_CODE /* Include necessary system files. */ #include "ux_api.h" #include "ux_device_class_pima.h" #include "ux_device_stack.h" /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_pima_initialize PORTABLE C */ /* 6.3.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function initializes the USB Pima device class */ /* */ /* INPUT */ /* */ /* command Pointer to pima command */ /* */ /* OUTPUT */ /* */ /* Completion Status */ /* */ /* CALLS */ /* */ /* _ux_utility_memory_allocate Allocate memory */ /* _ux_utility_memory_free Free memory */ /* _ux_device_thread_create Create thread */ /* */ /* CALLED BY */ /* */ /* USBX Source Code */ /* */ /**************************************************************************/ UINT _ux_device_class_pima_initialize(UX_SLAVE_CLASS_COMMAND *command) { #if defined(UX_DEVICE_STANDALONE) UX_PARAMETER_NOT_USED(command); return(UX_FUNCTION_NOT_SUPPORTED); #else UINT status; UX_SLAVE_CLASS_PIMA *pima; UX_SLAVE_CLASS_PIMA_PARAMETER *pima_parameter; UX_SLAVE_CLASS *class_ptr; /* Get the class container. */ class_ptr = command -> ux_slave_class_command_class_ptr; /* Create an instance of the device pima class. */ pima = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_SLAVE_CLASS_PIMA)); /* Check for successful allocation. */ if (pima == UX_NULL) return(UX_MEMORY_INSUFFICIENT); /* Save the address of the PIMA instance inside the PIMA container. */ class_ptr -> ux_slave_class_instance = (VOID *) pima; #if UX_DEVICE_ENDPOINT_BUFFER_OWNER == 1 /* Allocate some memory for endpoints. */ UX_ASSERT(!UX_DEVICE_CLASS_PIMA_ENDPOINT_BUFFER_SIZE_CALC_OVERFLOW); pima -> ux_device_class_pima_endpoint_buffer = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_CACHE_SAFE_MEMORY, UX_DEVICE_CLASS_PIMA_ENDPOINT_BUFFER_SIZE); if (pima -> ux_device_class_pima_endpoint_buffer == UX_NULL) { _ux_utility_memory_free(pima); return(UX_MEMORY_INSUFFICIENT); } #endif /* Allocate some memory for the thread stack. */ class_ptr -> ux_slave_class_thread_stack = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, UX_THREAD_STACK_SIZE); /* Check for successful allocation. */ if (class_ptr -> ux_slave_class_thread_stack == UX_NULL) status = UX_MEMORY_INSUFFICIENT; else status = UX_SUCCESS; /* This instance needs to be running in a different thread. So start a new thread. We pass a pointer to the class to the new thread. This thread does not start until we have a instance of the class. */ if (status == UX_SUCCESS) { status = _ux_device_thread_create(&class_ptr -> ux_slave_class_thread, "ux_slave_class_thread", _ux_device_class_pima_thread, (ULONG) (ALIGN_TYPE) class_ptr, (VOID *) class_ptr -> ux_slave_class_thread_stack, UX_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_CLASS, UX_THREAD_PRIORITY_CLASS, UX_NO_TIME_SLICE, UX_DONT_START); /* Check the creation of this thread. */ if (status != UX_SUCCESS) status = UX_THREAD_ERROR; } UX_THREAD_EXTENSION_PTR_SET(&(class_ptr -> ux_slave_class_thread), class_ptr) /* There is error, free resources and return error. */ if (status != UX_SUCCESS) { /* The last resource, thread is not created or created error, no need to free. */ if (class_ptr -> ux_slave_class_thread_stack) _ux_utility_memory_free(class_ptr -> ux_slave_class_thread_stack); /* Detach instance and free memory. */ class_ptr -> ux_slave_class_instance = UX_NULL; #if UX_DEVICE_ENDPOINT_BUFFER_OWNER == 1 _ux_utility_memory_free(pima -> ux_device_class_pima_endpoint_buffer); #endif _ux_utility_memory_free(pima); /* Return completion status. */ return(status); } /* Success, complete remaining settings. */ /* Get the pointer to the application parameters for the pima class. */ pima_parameter = command -> ux_slave_class_command_parameter; /* Store all the application parameter information about the media. */ pima -> ux_device_class_pima_manufacturer = pima_parameter -> ux_device_class_pima_parameter_manufacturer; pima -> ux_device_class_pima_model = pima_parameter -> ux_device_class_pima_parameter_model; pima -> ux_device_class_pima_device_version = pima_parameter -> ux_device_class_pima_parameter_device_version; pima -> ux_device_class_pima_serial_number = pima_parameter -> ux_device_class_pima_parameter_serial_number; /* Store all the application parameter information about the storage. */ pima -> ux_device_class_pima_storage_id = pima_parameter -> ux_device_class_pima_parameter_storage_id; pima -> ux_device_class_pima_storage_type = pima_parameter -> ux_device_class_pima_parameter_storage_type; pima -> ux_device_class_pima_storage_file_system_type = pima_parameter -> ux_device_class_pima_parameter_storage_file_system_type; pima -> ux_device_class_pima_storage_access_capability = pima_parameter -> ux_device_class_pima_parameter_storage_access_capability; pima -> ux_device_class_pima_storage_max_capacity_low = pima_parameter -> ux_device_class_pima_parameter_storage_max_capacity_low; pima -> ux_device_class_pima_storage_max_capacity_high = pima_parameter -> ux_device_class_pima_parameter_storage_max_capacity_high; pima -> ux_device_class_pima_storage_free_space_low = pima_parameter -> ux_device_class_pima_parameter_storage_free_space_low; pima -> ux_device_class_pima_storage_free_space_high = pima_parameter -> ux_device_class_pima_parameter_storage_free_space_high; pima -> ux_device_class_pima_storage_free_space_image = pima_parameter -> ux_device_class_pima_parameter_storage_free_space_image; pima -> ux_device_class_pima_storage_description = pima_parameter -> ux_device_class_pima_parameter_storage_description; pima -> ux_device_class_pima_storage_volume_label = pima_parameter -> ux_device_class_pima_parameter_storage_volume_label; /* Update device properties supported. */ pima -> ux_device_class_pima_device_properties_list = pima_parameter -> ux_device_class_pima_parameter_device_properties_list; /* Update the capture formats supported list. */ pima -> ux_device_class_pima_supported_capture_formats_list = pima_parameter -> ux_device_class_pima_parameter_supported_capture_formats_list; /* Update the image formats supported list. */ pima -> ux_device_class_pima_supported_image_formats_list = pima_parameter -> ux_device_class_pima_parameter_supported_image_formats_list; #ifdef UX_PIMA_WITH_MTP_SUPPORT /* Update the internal pima structure with the object properties. */ pima -> ux_device_class_pima_object_properties_list = pima_parameter -> ux_device_class_pima_parameter_object_properties_list; #endif /* Store the callback functions for request. */ pima -> ux_device_class_pima_cancel = pima_parameter -> ux_device_class_pima_parameter_cancel; /* Store the callback functions for device. */ pima -> ux_device_class_pima_device_reset = pima_parameter -> ux_device_class_pima_parameter_device_reset; pima -> ux_device_class_pima_device_prop_desc_get = pima_parameter -> ux_device_class_pima_parameter_device_prop_desc_get; pima -> ux_device_class_pima_device_prop_value_get = pima_parameter -> ux_device_class_pima_parameter_device_prop_value_get; pima -> ux_device_class_pima_device_prop_value_set = pima_parameter -> ux_device_class_pima_parameter_device_prop_value_set; /* Store the callback functions for storage. */ pima -> ux_device_class_pima_storage_format = pima_parameter -> ux_device_class_pima_parameter_storage_format; pima -> ux_device_class_pima_storage_info_get = pima_parameter -> ux_device_class_pima_parameter_storage_info_get; /* Store the callback functions for objects. */ pima -> ux_device_class_pima_object_number_get = pima_parameter -> ux_device_class_pima_parameter_object_number_get; pima -> ux_device_class_pima_object_handles_get = pima_parameter -> ux_device_class_pima_parameter_object_handles_get; pima -> ux_device_class_pima_object_info_get = pima_parameter -> ux_device_class_pima_parameter_object_info_get; pima -> ux_device_class_pima_object_data_get = pima_parameter -> ux_device_class_pima_parameter_object_data_get; pima -> ux_device_class_pima_object_info_send = pima_parameter -> ux_device_class_pima_parameter_object_info_send; pima -> ux_device_class_pima_object_data_send = pima_parameter -> ux_device_class_pima_parameter_object_data_send; pima -> ux_device_class_pima_object_delete = pima_parameter -> ux_device_class_pima_parameter_object_delete; #ifdef UX_PIMA_WITH_MTP_SUPPORT /* Add the MTP specific callback functions. */ pima -> ux_device_class_pima_object_prop_desc_get = pima_parameter -> ux_device_class_pima_parameter_object_prop_desc_get; pima -> ux_device_class_pima_object_prop_value_get = pima_parameter -> ux_device_class_pima_parameter_object_prop_value_get; pima -> ux_device_class_pima_object_prop_value_set = pima_parameter -> ux_device_class_pima_parameter_object_prop_value_set; pima -> ux_device_class_pima_object_references_get = pima_parameter -> ux_device_class_pima_parameter_object_references_get; pima -> ux_device_class_pima_object_references_set = pima_parameter -> ux_device_class_pima_parameter_object_references_set; #endif /* Store the application owner. */ pima -> ux_device_class_pima_application = pima_parameter -> ux_device_class_pima_parameter_application; /* Store the start and stop signals if needed by the application. */ pima -> ux_device_class_pima_instance_activate = pima_parameter -> ux_device_class_pima_instance_activate; pima -> ux_device_class_pima_instance_deactivate = pima_parameter -> ux_device_class_pima_instance_deactivate; /* Return completion status. */ return(status); #endif } /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _uxe_device_class_pima_initialize PORTABLE C */ /* 6.3.0 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function checks errors in PIMA initialization function call. */ /* */ /* INPUT */ /* */ /* command Pointer to pima command */ /* */ /* OUTPUT */ /* */ /* Completion Status */ /* */ /* CALLS */ /* */ /* _ux_device_class_pima_initialize Initialize pima instance */ /* */ /* CALLED BY */ /* */ /* Device PIMA Class */ /* */ /**************************************************************************/ UINT _uxe_device_class_pima_initialize(UX_SLAVE_CLASS_COMMAND *command) { UX_SLAVE_CLASS_PIMA_PARAMETER *pima_parameter; /* Get the pointer to the application parameters for the pima class. */ pima_parameter = command -> ux_slave_class_command_parameter; /* Sanity checks. */ if ( /* Property lists check. */ /* pima_parameter -> ux_device_class_pima_parameter_device_properties_list can be UX_NULL */ /* pima_parameter -> ux_device_class_pima_parameter_supported_capture_formats_list can be UX_NULL */ /* pima_parameter -> ux_device_class_pima_parameter_supported_image_formats_list can be UX_NULL */ /* Callback functions check. */ /* pima_parameter -> ux_device_class_pima_parameter_cancel can be NULL */ (pima_parameter -> ux_device_class_pima_parameter_device_reset == UX_NULL) || (pima_parameter -> ux_device_class_pima_parameter_device_prop_desc_get == UX_NULL) || (pima_parameter -> ux_device_class_pima_parameter_device_prop_value_get == UX_NULL) || (pima_parameter -> ux_device_class_pima_parameter_device_prop_value_set == UX_NULL) || (pima_parameter -> ux_device_class_pima_parameter_storage_format == UX_NULL) || /* pima_parameter -> ux_device_class_pima_parameter_storage_info_get can be UX_NULL */ (pima_parameter -> ux_device_class_pima_parameter_object_number_get == UX_NULL) || (pima_parameter -> ux_device_class_pima_parameter_object_handles_get == UX_NULL) || (pima_parameter -> ux_device_class_pima_parameter_object_info_get == UX_NULL) || (pima_parameter -> ux_device_class_pima_parameter_object_data_get == UX_NULL) || (pima_parameter -> ux_device_class_pima_parameter_object_info_send == UX_NULL) || (pima_parameter -> ux_device_class_pima_parameter_object_data_send == UX_NULL) || (pima_parameter -> ux_device_class_pima_parameter_object_delete == UX_NULL) #ifdef UX_PIMA_WITH_MTP_SUPPORT || (pima_parameter -> ux_device_class_pima_parameter_object_properties_list == UX_NULL) || (pima_parameter -> ux_device_class_pima_parameter_object_prop_desc_get == UX_NULL) || (pima_parameter -> ux_device_class_pima_parameter_object_prop_value_get == UX_NULL) || (pima_parameter -> ux_device_class_pima_parameter_object_prop_value_set == UX_NULL) || (pima_parameter -> ux_device_class_pima_parameter_object_references_get == UX_NULL) || (pima_parameter -> ux_device_class_pima_parameter_object_references_set == UX_NULL) #endif ) { return(UX_INVALID_PARAMETER); } /* Invoke PIMA initialize function. */ return(_ux_device_class_pima_initialize(command)); }