1 /**************************************************************************/
2 /*                                                                        */
3 /*       Copyright (c) Microsoft Corporation. All rights reserved.        */
4 /*                                                                        */
5 /*       This software is licensed under the Microsoft Software License   */
6 /*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
7 /*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
8 /*       and in the root directory of this software.                      */
9 /*                                                                        */
10 /**************************************************************************/
11 
12 
13 /**************************************************************************/
14 /**************************************************************************/
15 /**                                                                       */
16 /** USBX Component                                                        */
17 /**                                                                       */
18 /**   PIMA Class                                                          */
19 /**                                                                       */
20 /**************************************************************************/
21 /**************************************************************************/
22 
23 
24 /* Include necessary system files.  */
25 
26 #define UX_SOURCE_CODE
27 
28 #include "ux_api.h"
29 #include "ux_host_class_pima.h"
30 #include "ux_host_stack.h"
31 
32 
33 /**************************************************************************/
34 /*                                                                        */
35 /*  FUNCTION                                               RELEASE        */
36 /*                                                                        */
37 /*    _ux_host_class_pima_request_cancel                  PORTABLE C      */
38 /*                                                           6.1          */
39 /*  AUTHOR                                                                */
40 /*                                                                        */
41 /*    Chaoqiong Xiao, Microsoft Corporation                               */
42 /*                                                                        */
43 /*  DESCRIPTION                                                           */
44 /*                                                                        */
45 /*    This function cancels a request.                                    */
46 /*  INPUT                                                                 */
47 /*                                                                        */
48 /*    pima                                       Pointer to pima class    */
49 /*                                                                        */
50 /*  OUTPUT                                                                */
51 /*                                                                        */
52 /*    Completion Status                                                   */
53 /*                                                                        */
54 /*  CALLS                                                                 */
55 /*                                                                        */
56 /*    _ux_host_stack_transfer_request       Transfer request              */
57 /*    _ux_utility_memory_allocate           Allocate memory               */
58 /*    _ux_utility_memory_free               Free memory                   */
59 /*    _ux_utility_short_put                 Put 16-bit value              */
60 /*    _ux_utility_short_get                 Get 16-bit value              */
61 /*    _ux_utility_long_put                  Put 32-bit value              */
62 /*    _ux_utility_delay_ms                  Delay ms                      */
63 /*                                                                        */
64 /*  CALLED BY                                                             */
65 /*                                                                        */
66 /*    USB application                                                     */
67 /*                                                                        */
68 /*  RELEASE HISTORY                                                       */
69 /*                                                                        */
70 /*    DATE              NAME                      DESCRIPTION             */
71 /*                                                                        */
72 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
73 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
74 /*                                            resulting in version 6.1    */
75 /*                                                                        */
76 /**************************************************************************/
_ux_host_class_pima_request_cancel(UX_HOST_CLASS_PIMA * pima)77 UINT  _ux_host_class_pima_request_cancel(UX_HOST_CLASS_PIMA *pima)
78 {
79 
80 UX_TRANSFER                         *transfer_request;
81 UX_ENDPOINT                         *control_endpoint;
82 UCHAR                                 *request_payload;
83 UINT                                status;
84 UINT                                device_status;
85 ULONG                               payload_length;
86 ULONG                               command_retry_counter;
87 
88     /* If trace is enabled, insert this event into the trace buffer.  */
89     UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PIMA_REQUEST_CANCEL, pima, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
90 
91     /* Allocate some DMA safe memory for the command data payload.  We use mode than needed because
92        we use this buffer for both the command and the status phase.  */
93     request_payload =  _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_PIMA_REQUEST_STATUS_DATA_LENGTH);
94     if (request_payload == UX_NULL)
95         return(UX_MEMORY_INSUFFICIENT);
96 
97     /* Fill in the payload buffer with cancellation code.  */
98     _ux_utility_short_put(request_payload + UX_HOST_CLASS_PIMA_REQUEST_CANCEL_OFFSET_CODE,
99                         UX_HOST_CLASS_PIMA_REQUEST_CANCEL_CODE );
100 
101     /* Fill in the payload buffer with transactionID.  */
102     _ux_utility_long_put(request_payload + UX_HOST_CLASS_PIMA_REQUEST_CANCEL_OFFSET_TRANSACTION_ID,
103                         pima -> ux_host_class_pima_transaction_id++);
104 
105     /* We need to get the default control endpoint transfer request pointer.  */
106     control_endpoint =  &pima -> ux_host_class_pima_device -> ux_device_control_endpoint;
107     transfer_request =  &control_endpoint -> ux_endpoint_transfer_request;
108 
109     /* Create a transfer_request for the CANCEL request.  */
110     transfer_request -> ux_transfer_request_data_pointer =      request_payload;
111     transfer_request -> ux_transfer_request_requested_length =  UX_HOST_CLASS_PIMA_REQUEST_CANCEL_DATA_LENGTH;
112     transfer_request -> ux_transfer_request_function =          UX_HOST_CLASS_PIMA_REQUEST_CANCEL_COMMAND;
113     transfer_request -> ux_transfer_request_type =              UX_REQUEST_OUT | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE;
114     transfer_request -> ux_transfer_request_value =             0;
115     transfer_request -> ux_transfer_request_index  =            0;
116 
117     /* Send request to HCD layer.  */
118     status =  _ux_host_stack_transfer_request(transfer_request);
119 
120     /* Check if status is OK. If the command did not work, we have a major problem.  */
121     if(status == UX_SUCCESS)
122     {
123 
124         /* Initialize the command retry counter.  */
125         command_retry_counter = UX_HOST_CLASS_PIMA_REQUEST_STATUS_COMMAND_COUNTER;
126 
127         /* This command may be retried a few times.  */
128         while (command_retry_counter-- != 0)
129         {
130 
131             /* We need to wait for the device to be OK. For that we issue a GET_DEVICE_STATUS command.  */
132             transfer_request -> ux_transfer_request_data_pointer =      request_payload;
133             transfer_request -> ux_transfer_request_requested_length =  UX_HOST_CLASS_PIMA_REQUEST_CANCEL_DATA_LENGTH;
134             transfer_request -> ux_transfer_request_function =          UX_HOST_CLASS_PIMA_REQUEST_STATUS_COMMAND;
135             transfer_request -> ux_transfer_request_type =              UX_REQUEST_IN | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE;
136             transfer_request -> ux_transfer_request_value =             0;
137             transfer_request -> ux_transfer_request_index  =            0;
138 
139             /* Send request to HCD layer.  */
140             status =  _ux_host_stack_transfer_request(transfer_request);
141 
142             /* Check status, abort if there is an error.  */
143             if (status != UX_SUCCESS)
144                 break;
145 
146             /* Extract the payload length from the status buffer.  */
147             payload_length =  _ux_utility_short_get(request_payload + UX_HOST_CLASS_PIMA_REQUEST_STATUS_OFFSET_LENGTH);
148 
149             /* Check the data payload length.  */
150             if (payload_length < UX_HOST_CLASS_PIMA_REQUEST_STATUS_OFFSET_CODE + sizeof(UINT))
151             {
152 
153                 /* We have a data format error.  */
154                 status =  UX_ERROR;
155                 break;
156             }
157 
158             /* Extract the device status.  */
159             device_status =  _ux_utility_short_get(request_payload + UX_HOST_CLASS_PIMA_REQUEST_STATUS_OFFSET_CODE);
160 
161             /* If the device status is OK, we have a successful cancellation.  */
162             if (device_status == UX_HOST_CLASS_PIMA_RC_OK)
163             {
164 
165                 /* Status is OK. exit the command loop.  */
166                 status = UX_SUCCESS;
167                 break;
168             }
169             else
170             {
171                 /* Force the status to error.  */
172                 status = UX_ERROR;
173 
174 
175                 /* We should wait a little bit before re-issuing the command.  */
176                 _ux_utility_delay_ms(UX_HOST_CLASS_PIMA_REQUEST_STATUS_COMMAND_DELAY);
177 
178             }
179         }
180 
181     }
182 
183     /* Free allocated resources.  */
184     _ux_utility_memory_free(request_payload);
185 
186     /* Return completion status.  */
187     return(status);
188 
189 }
190 
191