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 /** Generic Serial Host module 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_gser.h"
30 #include "ux_host_stack.h"
31
32
33 /**************************************************************************/
34 /* */
35 /* FUNCTION RELEASE */
36 /* */
37 /* _ux_host_class_gser_ioctl PORTABLE C */
38 /* 6.1 */
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 ACM device. */
47 /* */
48 /* */
49 /* INPUT */
50 /* */
51 /* acm Pointer to acm 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_class_gser_command Send command to acm device */
62 /* _ux_host_stack_endpoint_transfer_abort */
63 /* Abort transfer */
64 /* _ux_utility_memory_allocate Allocate memory */
65 /* _ux_utility_memory_free Free memory */
66 /* _ux_utility_long_put Put 32-bit value */
67 /* */
68 /* CALLED BY */
69 /* */
70 /* Storage Class */
71 /* */
72 /* RELEASE HISTORY */
73 /* */
74 /* DATE NAME DESCRIPTION */
75 /* */
76 /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */
77 /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
78 /* resulting in version 6.1 */
79 /* */
80 /**************************************************************************/
_ux_host_class_gser_ioctl(UX_HOST_CLASS_GSER * gser,ULONG interface_index,ULONG ioctl_function,VOID * parameter)81 UINT _ux_host_class_gser_ioctl(UX_HOST_CLASS_GSER *gser, ULONG interface_index, ULONG ioctl_function,
82 VOID *parameter)
83 {
84
85 UINT status;
86 UCHAR *data_buffer;
87 UX_HOST_CLASS_GSER_LINE_CODING *line_coding;
88 UX_HOST_CLASS_GSER_LINE_STATE *line_state;
89 VOID (*callback_function) (struct UX_HOST_CLASS_GSER_STRUCT *, ULONG, ULONG );
90 ULONG value;
91
92 /* Ensure the instance is valid. */
93 if (gser -> ux_host_class_gser_state != UX_HOST_CLASS_INSTANCE_LIVE)
94 {
95
96 /* If trace is enabled, insert this event into the trace buffer. */
97 UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, gser, 0, 0, UX_TRACE_ERRORS, 0, 0)
98
99 return(UX_HOST_CLASS_INSTANCE_UNKNOWN);
100 }
101
102 /* The command request will tell us we need to do here. */
103 switch (ioctl_function)
104 {
105
106 case UX_HOST_CLASS_GSER_IOCTL_SET_LINE_CODING:
107
108 /* If trace is enabled, insert this event into the trace buffer. */
109 UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_GSER_IOCTL_SET_LINE_CODING, gser, parameter, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
110
111 /* Allocate some cache safe memory for the control command. */
112 data_buffer = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_GSER_LINE_CODING_LENGTH);
113
114 /* Check if error. Return with error if no memory could be allocated. */
115 if (data_buffer == UX_NULL)
116
117 /* Do not proceed. Set error code. */
118 status = UX_MEMORY_INSUFFICIENT;
119 else
120 {
121
122 /* Build the buffer from the calling parameter. Cast the calling parameter. */
123 line_coding = (UX_HOST_CLASS_GSER_LINE_CODING *) parameter;
124
125 /* Put the data rate. */
126 _ux_utility_long_put(data_buffer + UX_HOST_CLASS_GSER_LINE_CODING_RATE,
127 line_coding -> ux_host_class_gser_line_coding_dter);
128
129 /* Then the stop bit. */
130 *(data_buffer + UX_HOST_CLASS_GSER_LINE_CODING_STOP_BIT) =
131 (UCHAR) line_coding -> ux_host_class_gser_line_coding_stop_bit;
132
133 /* Then the parity. */
134 *(data_buffer + UX_HOST_CLASS_GSER_LINE_CODING_PARITY) =
135 (UCHAR) line_coding -> ux_host_class_gser_line_coding_parity;
136
137 /* Finally the data bits. */
138 *(data_buffer + UX_HOST_CLASS_GSER_LINE_CODING_DATA_BIT) =
139 (UCHAR) line_coding -> ux_host_class_gser_line_coding_data_bits;
140
141 /* Send the command to the device. */
142 status = _ux_host_class_gser_command(gser, interface_index, UX_HOST_CLASS_GSER_REQ_SET_LINE_CODING,
143 0, data_buffer, UX_HOST_CLASS_GSER_LINE_CODING_LENGTH);
144
145 /* We free the resources allocated no matter what. */
146 _ux_utility_memory_free(data_buffer);
147 }
148 break;
149
150 case UX_HOST_CLASS_GSER_IOCTL_GET_LINE_CODING:
151
152 /* If trace is enabled, insert this event into the trace buffer. */
153 UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_GSER_IOCTL_GET_LINE_CODING, gser, parameter, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
154
155 /* Allocate some cache safe memory for the control command. */
156 data_buffer = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_GSER_LINE_CODING_LENGTH);
157
158 /* Check if error. Return with error if no memory could be allocated. */
159 if (data_buffer == UX_NULL)
160
161 /* Do not proceed. Set error code. */
162 status = UX_MEMORY_INSUFFICIENT;
163 else
164 {
165
166 /* Send the command to the device. */
167 status = _ux_host_class_gser_command(gser, interface_index, UX_HOST_CLASS_GSER_REQ_GET_LINE_CODING,
168 0, data_buffer, UX_HOST_CLASS_GSER_LINE_CODING_LENGTH);
169
170 /* Fill in the calling buffer if the result is successful. */
171 if (status == UX_SUCCESS)
172 {
173
174 /* Build the buffer from the calling parameter. Cast the calling parameter. */
175 line_coding = (UX_HOST_CLASS_GSER_LINE_CODING *) parameter;
176
177 /* Get the data rate. */
178 line_coding -> ux_host_class_gser_line_coding_dter = _ux_utility_long_get(data_buffer + UX_HOST_CLASS_GSER_LINE_CODING_RATE);
179
180 /* Then the stop bit. */
181 line_coding -> ux_host_class_gser_line_coding_stop_bit =
182 (ULONG) *(data_buffer + UX_HOST_CLASS_GSER_LINE_CODING_STOP_BIT);
183
184 /* Then the parity. */
185 line_coding -> ux_host_class_gser_line_coding_parity =
186 (ULONG) *(data_buffer + UX_HOST_CLASS_GSER_LINE_CODING_PARITY);
187
188 /* Finally the data bits. */
189 line_coding -> ux_host_class_gser_line_coding_data_bits =
190 (ULONG) *(data_buffer + UX_HOST_CLASS_GSER_LINE_CODING_DATA_BIT);
191 }
192
193 /* We free the resources allocated no matter what. */
194 _ux_utility_memory_free(data_buffer);
195 }
196 break;
197
198 case UX_HOST_CLASS_GSER_IOCTL_SET_LINE_STATE:
199
200 /* If trace is enabled, insert this event into the trace buffer. */
201 UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_GSER_IOCTL_SET_LINE_STATE, gser, parameter, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
202
203 /* Cast the calling parameter. */
204 line_state = (UX_HOST_CLASS_GSER_LINE_STATE *) parameter;
205
206 /* Build the value field. */
207 value = (line_state -> ux_host_class_gser_line_state_dtr |
208 (line_state -> ux_host_class_gser_line_state_rts << 1));
209
210 /* Send the command to the device. */
211 status = _ux_host_class_gser_command(gser, interface_index, UX_HOST_CLASS_GSER_REQ_SET_LINE_STATE,
212 value, UX_NULL,0);
213 break;
214
215 case UX_HOST_CLASS_GSER_IOCTL_SEND_BREAK :
216
217 /* If trace is enabled, insert this event into the trace buffer. */
218 UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_GSER_IOCTL_SEND_BREAK, gser, parameter, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
219
220 /* Build the value field. */
221 value = *((ULONG *) parameter);
222
223 /* Send the command to the device. */
224 status = _ux_host_class_gser_command(gser, interface_index, UX_HOST_CLASS_GSER_REQ_SEND_BREAK,
225 value, UX_NULL,0);
226 break;
227
228 case UX_HOST_CLASS_GSER_IOCTL_ABORT_IN_PIPE :
229
230 /* If trace is enabled, insert this event into the trace buffer. */
231 UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_GSER_IOCTL_ABORT_IN_PIPE, gser, gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_bulk_in_endpoint, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
232
233 /* We need to abort transactions on the bulk In pipe. */
234 _ux_host_stack_endpoint_transfer_abort(gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_bulk_in_endpoint);
235
236 /* Status is successful. */
237 status = UX_SUCCESS;
238 break;
239
240 case UX_HOST_CLASS_GSER_IOCTL_ABORT_OUT_PIPE :
241
242 /* If trace is enabled, insert this event into the trace buffer. */
243 UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_GSER_IOCTL_ABORT_OUT_PIPE, gser, gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_bulk_out_endpoint, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
244
245 /* We need to abort transactions on the bulk Out pipe. */
246 _ux_host_stack_endpoint_transfer_abort(gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_bulk_out_endpoint);
247
248 /* Status is successful. */
249 status = UX_SUCCESS;
250 break;
251
252 case UX_HOST_CLASS_GSER_IOCTL_NOTIFICATION_CALLBACK :
253
254 /* If trace is enabled, insert this event into the trace buffer. */
255 UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_GSER_IOCTL_NOTIFICATION_CALLBACK, gser, parameter, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
256
257 /* Register a callback when the line state has changed. */
258 callback_function = ((VOID (*) (struct UX_HOST_CLASS_GSER_STRUCT *, ULONG, ULONG )) (ALIGN_TYPE)parameter);
259 gser -> ux_host_class_gser_device_status_change_callback = callback_function;
260
261 /* Status is successful. */
262 status = UX_SUCCESS;
263 break;
264
265 case UX_HOST_CLASS_GSER_IOCTL_GET_DEVICE_STATUS :
266
267 /* If trace is enabled, insert this event into the trace buffer. */
268 UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_GSER_IOCTL_GET_DEVICE_STATUS, gser, gser -> ux_host_class_gser_device_state, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0)
269
270 /* Return the device status. */
271 * ((ULONG *) parameter) = gser -> ux_host_class_gser_device_state;
272
273 /* Status is successful. */
274 status = UX_SUCCESS;
275 break;
276
277 default:
278
279 /* If trace is enabled, insert this event into the trace buffer. */
280 UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_FUNCTION_NOT_SUPPORTED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0)
281
282 /* Function not supported. Return an error. */
283 status = UX_FUNCTION_NOT_SUPPORTED;
284 }
285
286 /* Return status to caller. */
287 return(status);
288 }
289
290