1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 *
4 * This program and the accompanying materials are made available under the
5 * terms of the MIT License which is available at
6 * https://opensource.org/licenses/MIT.
7 *
8 * SPDX-License-Identifier: MIT
9 **************************************************************************/
10
11 /**************************************************************************/
12 /** */
13 /** USBX Component */
14 /** */
15 /** Device CCID Class */
16 /** */
17 /**************************************************************************/
18 /**************************************************************************/
19
20 #define UX_SOURCE_CODE
21
22
23 /* Include necessary system files. */
24
25 #include "ux_api.h"
26 #include "ux_device_class_ccid.h"
27 #include "ux_device_stack.h"
28
29
30 /**************************************************************************/
31 /* */
32 /* FUNCTION RELEASE */
33 /* */
34 /* _ux_device_class_ccid_activate PORTABLE C */
35 /* 6.3.0 */
36 /* AUTHOR */
37 /* */
38 /* Chaoqiong Xiao, Microsoft Corporation */
39 /* */
40 /* DESCRIPTION */
41 /* */
42 /* This function activates the USB CCID device. */
43 /* */
44 /* INPUT */
45 /* */
46 /* command Pointer to ccid command */
47 /* */
48 /* OUTPUT */
49 /* */
50 /* Completion Status */
51 /* */
52 /* CALLS */
53 /* */
54 /* None */
55 /* */
56 /* CALLED BY */
57 /* */
58 /* USBX Device CCID */
59 /* */
60 /* RELEASE HISTORY */
61 /* */
62 /* DATE NAME DESCRIPTION */
63 /* */
64 /* 04-25-2022 Chaoqiong Xiao Initial Version 6.1.11 */
65 /* 07-29-2022 Chaoqiong Xiao Modified comment(s), */
66 /* fixed parameter/variable */
67 /* names conflict C++ keyword, */
68 /* resulting in version 6.1.12 */
69 /* 03-08-2023 Chaoqiong Xiao Modified comment(s), */
70 /* added standalone support, */
71 /* resulting in version 6.2.1 */
72 /* 10-31-2023 Chaoqiong Xiao Modified comment(s), */
73 /* added a new mode to manage */
74 /* endpoint buffer in classes, */
75 /* resulting in version 6.3.0 */
76 /* */
77 /**************************************************************************/
_ux_device_class_ccid_activate(UX_SLAVE_CLASS_COMMAND * command)78 UINT _ux_device_class_ccid_activate(UX_SLAVE_CLASS_COMMAND *command)
79 {
80
81 UX_SLAVE_INTERFACE *ccid_interface;
82 UX_SLAVE_CLASS *ccid_class;
83 UX_DEVICE_CLASS_CCID *ccid;
84 UX_SLAVE_ENDPOINT *endpoint;
85 ULONG endpoint_type;
86 #if !defined(UX_DEVICE_STANDALONE)
87 UINT i;
88 #endif
89
90 /* Get the class container. */
91 ccid_class = command -> ux_slave_class_command_class_ptr;
92
93 /* Get the class instance in the container. */
94 ccid = (UX_DEVICE_CLASS_CCID *) ccid_class -> ux_slave_class_instance;
95
96 /* Get the interface that owns this instance. */
97 ccid_interface = (UX_SLAVE_INTERFACE *) command -> ux_slave_class_command_interface;
98
99 /* Store the class instance into the interface. */
100 ccid_interface -> ux_slave_interface_class_instance = (VOID *)ccid;
101
102 /* Now the opposite, store the interface in the class instance. */
103 ccid -> ux_device_class_ccid_interface = ccid_interface;
104
105 /* Save endpoints. */
106 ccid -> ux_device_class_ccid_endpoint_notify = UX_NULL;
107 endpoint = ccid_interface -> ux_slave_interface_first_endpoint;
108 while(endpoint)
109 {
110 endpoint_type = endpoint -> ux_slave_endpoint_descriptor.bmAttributes;
111 endpoint_type &= UX_MASK_ENDPOINT_TYPE;
112 if (endpoint_type == UX_INTERRUPT_ENDPOINT)
113 {
114 ccid -> ux_device_class_ccid_endpoint_notify = endpoint;
115 #if UX_DEVICE_ENDPOINT_BUFFER_OWNER == 1
116 endpoint -> ux_slave_endpoint_transfer_request.
117 ux_slave_transfer_request_data_pointer =
118 UX_DEVICE_CLASS_CCID_INTERRUPTIN_BUFFER(ccid);
119 #endif
120 }
121 if (endpoint_type == UX_BULK_ENDPOINT)
122 {
123 if (endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_IN)
124 {
125 ccid -> ux_device_class_ccid_endpoint_in = endpoint;
126 #if UX_DEVICE_ENDPOINT_BUFFER_OWNER == 1
127 endpoint -> ux_slave_endpoint_transfer_request.
128 ux_slave_transfer_request_data_pointer =
129 UX_DEVICE_CLASS_CCID_BULKIN_BUFFER(ccid);
130 #endif
131 }
132 else
133 {
134 ccid -> ux_device_class_ccid_endpoint_out = endpoint;
135 #if UX_DEVICE_ENDPOINT_BUFFER_OWNER == 1
136 endpoint -> ux_slave_endpoint_transfer_request.
137 ux_slave_transfer_request_data_pointer =
138 UX_DEVICE_CLASS_CCID_BULKOUT_BUFFER(ccid);
139 #endif
140 }
141 }
142 endpoint = endpoint -> ux_slave_endpoint_next_endpoint;
143 }
144
145 #if defined(UX_DEVICE_STANDALONE)
146
147 /* Initialize slots (optimized for 1 slot). */
148 ccid -> ux_device_class_ccid_slots -> ux_device_class_ccid_slot_runner = -1;
149 ccid -> ux_device_class_ccid_slots -> ux_device_class_ccid_slot_icc_status =
150 UX_DEVICE_CLASS_CCID_ICC_NOT_PRESENT;
151
152 /* Initialize task states. */
153 ccid -> ux_device_class_ccid_cmd_state = UX_DEVICE_CLASS_CCID_CMD_START;
154 ccid -> ux_device_class_ccid_rsp_state = UX_DEVICE_CLASS_CCID_RSP_IDLE;
155 ccid -> ux_device_class_ccid_notify_state = UX_DEVICE_CLASS_CCID_NOTIFY_IDLE;
156
157 /* Initialize runner task state (optimized for 1 slot). */
158 ccid -> ux_device_class_ccid_runners -> ux_device_class_ccid_runner_state = UX_DEVICE_CLASS_CCID_RUNNER_IDLE;
159 #else
160
161 /* Initialize slots. */
162 for (i = 0;
163 i < ccid -> ux_device_class_ccid_parameter.ux_device_class_ccid_max_n_slots;
164 i ++)
165 {
166 ccid -> ux_device_class_ccid_slots[i].ux_device_class_ccid_slot_runner = -1;
167 ccid -> ux_device_class_ccid_slots[i].ux_device_class_ccid_slot_icc_status =
168 UX_DEVICE_CLASS_CCID_ICC_NOT_PRESENT;
169 }
170
171 /* Activate thread for Bulk-OUT command messages. */
172 _ux_device_thread_resume(&ccid -> ux_device_class_ccid_thread);
173
174 /* Activate thread for Interrupt-IN notification messages. */
175 _ux_device_thread_resume(&ccid -> ux_device_class_ccid_notify_thread);
176
177 /* Activate threads for runners. */
178 for (i = 0;
179 i < ccid -> ux_device_class_ccid_parameter.ux_device_class_ccid_max_n_busy_slots;
180 i ++)
181 {
182 _ux_device_thread_resume(&ccid -> ux_device_class_ccid_runners[i].
183 ux_device_class_ccid_runner_thread);
184 }
185 #endif
186
187 /* If there is a activate function call it. */
188 if (ccid -> ux_device_class_ccid_parameter.ux_device_class_ccid_instance_activate != UX_NULL)
189 {
190
191 /* Invoke the application callback. */
192 ccid -> ux_device_class_ccid_parameter.ux_device_class_ccid_instance_activate(ccid);
193 }
194
195 /* If trace is enabled, insert this event into the trace buffer. */
196 UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_CCID_ACTIVATE, ccid, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0)
197
198 /* If trace is enabled, register this object. */
199 UX_TRACE_OBJECT_REGISTER(UX_TRACE_DEVICE_OBJECT_TYPE_INTERFACE, ccid, 0, 0, 0)
200
201 /* Return completion status. */
202 return(UX_SUCCESS);
203 }
204