/*************************************************************************** * 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 CCID Class */ /** */ /**************************************************************************/ /**************************************************************************/ #define UX_SOURCE_CODE /* Include necessary system files. */ #include "ux_api.h" #include "ux_device_class_ccid.h" #include "ux_device_stack.h" /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _ux_device_class_ccid_control_abort PORTABLE C */ /* 6.2.1 */ /* AUTHOR */ /* */ /* Chaoqiong Xiao, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function handles control request Abort of the USB CCID device. */ /* */ /* INPUT */ /* */ /* ccid Pointer to ccid instance */ /* slot Slot to abort */ /* seq Sequence number of message */ /* */ /* OUTPUT */ /* */ /* Completion Status */ /* */ /* CALLS */ /* */ /* */ /* CALLED BY */ /* */ /* USBX Source Code */ /* */ /**************************************************************************/ UINT _ux_device_class_ccid_control_abort(UX_DEVICE_CLASS_CCID *ccid, ULONG slot, ULONG seq) { UX_DEVICE_CLASS_CCID_PARAMETER *parameter; UX_DEVICE_CLASS_CCID_HANDLES *handles; UX_DEVICE_CLASS_CCID_SLOT *ccid_slot; UX_SLAVE_TRANSFER *transfer_in, *transfer_out; UX_DEVICE_CLASS_CCID_MESSAGE_HEADER *msg; /* Get parameter. */ parameter = &ccid -> ux_device_class_ccid_parameter; handles = parameter -> ux_device_class_ccid_handles; /* Check if slot is available. */ if (slot >= parameter -> ux_device_class_ccid_max_n_slots) return(UX_INVALID_PARAMETER); /* Check if command is supported. */ if (handles -> ux_device_class_ccid_handles_abort == UX_NULL) return(UX_FUNCTION_NOT_SUPPORTED); /* Get slot to process. */ ccid_slot = &ccid -> ux_device_class_ccid_slots[slot]; /* Check if message header received. */ transfer_out = &ccid -> ux_device_class_ccid_endpoint_out -> ux_slave_endpoint_transfer_request; if (transfer_out -> ux_slave_transfer_request_actual_length < UX_DEVICE_CLASS_CCID_MESSAGE_HEADER_LENGTH) { /* Message header not available, cancel current bulk OUT transfer. */ _ux_device_stack_transfer_abort(transfer_out, UX_ABORTED); } else { /* Message header available, check message. */ msg = (UX_DEVICE_CLASS_CCID_MESSAGE_HEADER *) transfer_out -> ux_slave_transfer_request_data_pointer; /* Check if abort applies to the slot. */ if (msg -> bSlot == (UCHAR)slot) { /* Yes, aborting current message, cancel current bulk OUT transfer. */ _ux_device_stack_transfer_abort(transfer_out, UX_ABORTED); } else { /* Aborting another slot. */ /* Check slot busy. */ if ((signed char)ccid_slot -> ux_device_class_ccid_slot_runner >= 0) { /* Possible sending something, abort IN transfer. */ transfer_in = &ccid -> ux_device_class_ccid_endpoint_in -> ux_slave_endpoint_transfer_request; _ux_device_stack_transfer_abort(transfer_in, UX_ABORTED); } } } #if defined(UX_DEVICE_STANDALONE) if (ccid -> ux_device_class_ccid_cmd_state == UX_DEVICE_CLASS_CCID_CMD_WAIT) ccid -> ux_device_class_ccid_cmd_state = UX_DEVICE_CLASS_CCID_CMD_START; if (ccid -> ux_device_class_ccid_rsp_state == UX_DEVICE_CLASS_CCID_RSP_WAIT) ccid -> ux_device_class_ccid_rsp_state = UX_DEVICE_CLASS_CCID_RSP_IDLE; #endif /* Set aborting state. */ ccid_slot -> ux_device_class_ccid_slot_aborting = UX_TRUE; ccid_slot -> ux_device_class_ccid_slot_aborting_seq = (UCHAR)seq; /* Invoke control abort to let application do something. */ handles -> ux_device_class_ccid_handles_abort(slot, UX_NULL); return(UX_SUCCESS); }