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 /** Prolific 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_prolific.h"
30 #include "ux_host_stack.h"
31
32
33 /**************************************************************************/
34 /* */
35 /* FUNCTION RELEASE */
36 /* */
37 /* _ux_host_class_prolific_ioctl PORTABLE C */
38 /* 6.1.11 */
39 /* AUTHOR */
40 /* */
41 /* Chaoqiong Xiao, Microsoft Corporation */
42 /* */
43 /* DESCRIPTION */
44 /* */
45 /* This function is the ioctl entry point for the application to */
46 /* configure the Prolific device. */
47 /* */
48 /* */
49 /* INPUT */
50 /* */
51 /* prolific Pointer to prolific class */
52 /* ioctl_function ioctl function */
53 /* parameter pointer to structure */
54 /* */
55 /* OUTPUT */
56 /* */
57 /* Completion Status */
58 /* */
59 /* CALLS */
60 /* */
61 /* _ux_host_stack_transfer_request Transfer request */
62 /* _ux_host_stack_endpoint_transfer_abort */
63 /* Abort transfer */
64 /* _ux_host_class_prolific_command Send command to device */
65 /* _ux_utility_memory_allocate Allocate memory */
66 /* _ux_utility_memory_free Free memory */
67 /* _ux_utility_long_put Put 32-bit value */
68 /* */
69 /* CALLED BY */
70 /* */
71 /* Storage Class */
72 /* */
73 /* RELEASE HISTORY */
74 /* */
75 /* DATE NAME DESCRIPTION */
76 /* */
77 /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */
78 /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
79 /* resulting in version 6.1 */
80 /* 04-25-2022 Chaoqiong Xiao Modified comment(s), */
81 /* internal clean up, */
82 /* resulting in version 6.1.11 */
83 /* */
84 /**************************************************************************/
_ux_host_class_prolific_ioctl(UX_HOST_CLASS_PROLIFIC * prolific,ULONG ioctl_function,VOID * parameter)85 UINT _ux_host_class_prolific_ioctl(UX_HOST_CLASS_PROLIFIC *prolific, ULONG ioctl_function,
86 VOID *parameter)
87 {
88
89 UINT status;
90 UCHAR *data_buffer;
91 UX_HOST_CLASS_PROLIFIC_LINE_CODING *line_coding;
92 UX_HOST_CLASS_PROLIFIC_LINE_STATE *line_state;
93 ULONG value;
94 UX_ENDPOINT *control_endpoint;
95 UX_TRANSFER *transfer_request;
96 VOID (*callback_function) (struct UX_HOST_CLASS_PROLIFIC_STRUCT *, ULONG );
97
98 /* Ensure the instance is valid. */
99 if ((prolific -> ux_host_class_prolific_state != UX_HOST_CLASS_INSTANCE_LIVE) &&
100 (prolific -> ux_host_class_prolific_state != UX_HOST_CLASS_INSTANCE_MOUNTING))
101 {
102
103 /* Error trap. */
104 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_ENDPOINT_HANDLE_UNKNOWN);
105
106 /* If trace is enabled, insert this event into the trace buffer. */
107 UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, prolific, 0, 0, UX_TRACE_ERRORS, 0, 0)
108
109 return(UX_HOST_CLASS_INSTANCE_UNKNOWN);
110 }
111
112 /* The command request will tell us we need to do here. */
113 switch (ioctl_function)
114 {
115
116 case UX_HOST_CLASS_PROLIFIC_IOCTL_SET_LINE_CODING:
117
118 /* If trace is enabled, insert this event into the trace buffer. */
119 UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PROLIFIC_IOCTL_SET_LINE_CODING, prolific, parameter, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
120
121 /* Allocate some cache safe memory for the control command. */
122 data_buffer = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_PROLIFIC_LINE_CODING_LENGTH);
123
124 /* Check if error. Return with error if no memory could be allocated. */
125 if (data_buffer == UX_NULL)
126
127 /* Do not proceed. Set error code. */
128 status = UX_MEMORY_INSUFFICIENT;
129 else
130 {
131
132 /* Build the buffer from the calling parameter. Cast the calling parameter. */
133 line_coding = (UX_HOST_CLASS_PROLIFIC_LINE_CODING *) parameter;
134
135 /* Put the data rate. */
136 _ux_utility_long_put(data_buffer + UX_HOST_CLASS_PROLIFIC_LINE_CODING_RATE,
137 line_coding -> ux_host_class_prolific_line_coding_dter);
138
139 /* Then the stop bit. */
140 *(data_buffer + UX_HOST_CLASS_PROLIFIC_LINE_CODING_STOP_BIT) =
141 (UCHAR) line_coding -> ux_host_class_prolific_line_coding_stop_bit;
142
143 /* Then the parity. */
144 *(data_buffer + UX_HOST_CLASS_PROLIFIC_LINE_CODING_PARITY) =
145 (UCHAR) line_coding -> ux_host_class_prolific_line_coding_parity;
146
147 /* Finally the data bits. */
148 *(data_buffer + UX_HOST_CLASS_PROLIFIC_LINE_CODING_DATA_BIT) =
149 (UCHAR) line_coding -> ux_host_class_prolific_line_coding_data_bits;
150
151 /* Send the command to the device. */
152 status = _ux_host_class_prolific_command(prolific, UX_HOST_CLASS_PROLIFIC_REQ_SET_LINE_CODING,
153 0, data_buffer, UX_HOST_CLASS_PROLIFIC_LINE_CODING_LENGTH);
154
155 /* We free the resources allocated no matter what. */
156 _ux_utility_memory_free(data_buffer);
157 }
158 break;
159
160 case UX_HOST_CLASS_PROLIFIC_IOCTL_GET_LINE_CODING:
161
162 /* If trace is enabled, insert this event into the trace buffer. */
163 UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PROLIFIC_IOCTL_GET_LINE_CODING, prolific, parameter, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
164
165 /* Allocate some cache safe memory for the control command. */
166 data_buffer = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_PROLIFIC_LINE_CODING_LENGTH);
167
168 /* Check if error. Return with error if no memory could be allocated. */
169 if (data_buffer == UX_NULL)
170
171 /* Do not proceed. Set error code. */
172 status = UX_MEMORY_INSUFFICIENT;
173 else
174 {
175
176 /* Send the command to the device. */
177 status = _ux_host_class_prolific_command(prolific, UX_HOST_CLASS_PROLIFIC_REQ_GET_LINE_CODING,
178 0, data_buffer, UX_HOST_CLASS_PROLIFIC_LINE_CODING_LENGTH);
179
180 /* Fill in the calling buffer if the result is successful. */
181 if (status == UX_SUCCESS)
182 {
183
184 /* Build the buffer from the calling parameter. Cast the calling parameter. */
185 line_coding = (UX_HOST_CLASS_PROLIFIC_LINE_CODING *) parameter;
186
187 /* Get the data rate. */
188 line_coding -> ux_host_class_prolific_line_coding_dter = _ux_utility_long_get(data_buffer + UX_HOST_CLASS_PROLIFIC_LINE_CODING_RATE);
189
190 /* Then the stop bit. */
191 line_coding -> ux_host_class_prolific_line_coding_stop_bit =
192 (ULONG) *(data_buffer + UX_HOST_CLASS_PROLIFIC_LINE_CODING_STOP_BIT);
193
194 /* Then the parity. */
195 line_coding -> ux_host_class_prolific_line_coding_parity =
196 (ULONG) *(data_buffer + UX_HOST_CLASS_PROLIFIC_LINE_CODING_PARITY);
197
198 /* Finally the data bits. */
199 line_coding -> ux_host_class_prolific_line_coding_data_bits =
200 (ULONG) *(data_buffer + UX_HOST_CLASS_PROLIFIC_LINE_CODING_DATA_BIT);
201 }
202
203 /* We free the resources allocated no matter what. */
204 _ux_utility_memory_free(data_buffer);
205 }
206 break;
207
208 case UX_HOST_CLASS_PROLIFIC_IOCTL_SET_LINE_STATE:
209
210 /* If trace is enabled, insert this event into the trace buffer. */
211 UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PROLIFIC_IOCTL_SET_LINE_STATE, prolific, parameter, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
212
213 /* Cast the calling parameter. */
214 line_state = (UX_HOST_CLASS_PROLIFIC_LINE_STATE *) parameter;
215
216 /* Build the value field. */
217 value = (line_state -> ux_host_class_prolific_line_state_rts |
218 (line_state -> ux_host_class_prolific_line_state_dtr << 1));
219
220 /* Send the command to the device. */
221 status = _ux_host_class_prolific_command(prolific, UX_HOST_CLASS_PROLIFIC_REQ_SET_LINE_STATE,
222 value, UX_NULL,0);
223 break;
224
225 case UX_HOST_CLASS_PROLIFIC_IOCTL_SEND_BREAK :
226
227 /* If trace is enabled, insert this event into the trace buffer. */
228 UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PROLIFIC_IOCTL_SEND_BREAK, prolific, parameter, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
229
230 /* Build the value field. */
231 value = *((ULONG *) parameter);
232
233 /* Send the command to the device. */
234 status = _ux_host_class_prolific_command(prolific, UX_HOST_CLASS_PROLIFIC_REQ_SEND_BREAK,
235 value, UX_NULL,0);
236 break;
237
238 case UX_HOST_CLASS_PROLIFIC_IOCTL_PURGE :
239
240 /* If trace is enabled, insert this event into the trace buffer. */
241 UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PROLIFIC_IOCTL_PURGE, prolific, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
242
243 /* We need to get the default control endpoint transfer request pointer. */
244 control_endpoint = &prolific -> ux_host_class_prolific_device -> ux_device_control_endpoint;
245 transfer_request = &control_endpoint -> ux_endpoint_transfer_request;
246
247 /* Reset upstream data pipes part 1. */
248 transfer_request -> ux_transfer_request_data_pointer = UX_NULL;
249 transfer_request -> ux_transfer_request_requested_length = 0;
250 transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_PROLIFIC_VENDOR_WRITE_REQUEST;
251 transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE;
252 transfer_request -> ux_transfer_request_value = UX_HOST_CLASS_PROLIFIC_COMMAND_PIPE1_RESET;
253 transfer_request -> ux_transfer_request_index = 0;
254
255 /* Send request to HCD layer. */
256 _ux_host_stack_transfer_request(transfer_request);
257
258 /* Reset upstream data pipes part 1. */
259 transfer_request -> ux_transfer_request_data_pointer = UX_NULL;
260 transfer_request -> ux_transfer_request_requested_length = 0;
261 transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_PROLIFIC_VENDOR_WRITE_REQUEST;
262 transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE;
263 transfer_request -> ux_transfer_request_value = UX_HOST_CLASS_PROLIFIC_COMMAND_PIPE2_RESET;
264 transfer_request -> ux_transfer_request_index = 0;
265
266 /* Send request to HCD layer. */
267 status = _ux_host_stack_transfer_request(transfer_request);
268
269 break;
270
271 case UX_HOST_CLASS_PROLIFIC_IOCTL_ABORT_IN_PIPE :
272
273 /* If trace is enabled, insert this event into the trace buffer. */
274 UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PROLIFIC_IOCTL_ABORT_IN_PIPE, prolific, prolific -> ux_host_class_prolific_bulk_in_endpoint, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
275
276 /* We need to abort transactions on the bulk In pipe. */
277 _ux_host_stack_endpoint_transfer_abort(prolific -> ux_host_class_prolific_bulk_in_endpoint);
278
279 /* Status is successful. */
280 status = UX_SUCCESS;
281 break;
282
283 case UX_HOST_CLASS_PROLIFIC_IOCTL_ABORT_OUT_PIPE :
284
285 /* If trace is enabled, insert this event into the trace buffer. */
286 UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PROLIFIC_IOCTL_ABORT_OUT_PIPE, prolific, prolific -> ux_host_class_prolific_bulk_out_endpoint, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
287
288 /* We need to abort transactions on the bulk Out pipe. */
289 _ux_host_stack_endpoint_transfer_abort(prolific -> ux_host_class_prolific_bulk_out_endpoint);
290
291 /* Status is successful. */
292 status = UX_SUCCESS;
293 break;
294
295 case UX_HOST_CLASS_PROLIFIC_IOCTL_REPORT_DEVICE_STATUS_CHANGE :
296
297 /* If trace is enabled, insert this event into the trace buffer. */
298 UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PROLIFIC_IOCTL_REPORT_DEVICE_STATUS_CHANGE, prolific, parameter, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
299
300 /* Register a callback when the line state has changed. */
301 callback_function = ((VOID (*) (struct UX_HOST_CLASS_PROLIFIC_STRUCT *, ULONG )) (ALIGN_TYPE)parameter);
302 prolific -> ux_host_class_prolific_device_status_change_callback = callback_function;
303
304 /* Status is successful. */
305 status = UX_SUCCESS;
306 break;
307
308 case UX_HOST_CLASS_PROLIFIC_IOCTL_GET_DEVICE_STATUS :
309
310 /* If trace is enabled, insert this event into the trace buffer. */
311 UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PROLIFIC_IOCTL_GET_DEVICE_STATUS, prolific, prolific -> ux_host_class_prolific_device_state, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
312
313 /* Return the device status. */
314 * ((ULONG *) parameter) = prolific -> ux_host_class_prolific_device_state;
315
316 /* Status is successful. */
317 status = UX_SUCCESS;
318 break;
319
320
321 default:
322
323 /* Error trap. */
324 _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_FUNCTION_NOT_SUPPORTED);
325
326 /* If trace is enabled, insert this event into the trace buffer. */
327 UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_FUNCTION_NOT_SUPPORTED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0)
328
329 /* Function not supported. Return an error. */
330 status = UX_FUNCTION_NOT_SUPPORTED;
331 break;
332 }
333
334 /* Return status to caller. */
335 return(status);
336 }
337
338