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 /** Device Storage Class */
19 /** */
20 /**************************************************************************/
21 /**************************************************************************/
22
23 #define UX_SOURCE_CODE
24
25
26 /* Include necessary system files. */
27
28 #include "ux_api.h"
29 #include "ux_device_class_storage.h"
30 #include "ux_device_stack.h"
31
32 #define USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_PROFILE_LENGTH 228
33 #define USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_HEADER_LENGTH 8
34 #define USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_FEATURE_DESCRIPTOR_LENGTH 32
35 #define USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_FEATURE_HEADER_LENGTH 4
36 #define USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_FEATURE_LENGTH (USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_PROFILE_LENGTH - USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_FEATURE_DESCRIPTOR_LENGTH - USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_HEADER_LENGTH)
37 UCHAR usbx_device_class_storage_configuration_profile[] = {
38
39 /* Feature Header */
40 0x00, 0x00, /* Entire length of profile filled by firmware */
41 0x00, 0x00,
42 0x00, 0x00,
43 0x00, 0x00, /* Current profile */
44
45 /* Feature Descriptor */
46 0x00, 0x00, /* Feature Code : profile list */
47 0x00, /* Persistent/current */
48 0x1c, /* Additional Length */
49
50 0x00, 0x12, 0x00, 0x00, /* DVD-RAM */
51 0x00, 0x11, 0x00, 0x00, /* DVD-R */
52 0x00, 0x10, 0x00, 0x00, /* DVD-ROM */
53 0x00, 0x0A, 0x00, 0x00, /* CD-RW */
54 0x00, 0x09, 0x00, 0x00, /* CD-R */
55 0x00, 0x08, 0x00, 0x00, /* CD-ROM */
56 0x00, 0x02, 0x00, 0x00, /* Writable capable with removable media. */
57
58
59 /* Feature Descriptor */
60 0x00, 0x01, /* Feature Code : core feature */
61 0x0b, /* Persistent/current */
62 0x08, /* Additional Length */
63
64 0x00, 0x00, 0x00, 0x07, /* Physical Interface Standard */
65 0x01, 0x00, 0x00, 0x00, /* */
66
67 /* Feature Descriptor */
68 0x00, 0x02, /* Feature Code : morphing (Ability to notify initiator about
69 operational changes and accept initiator requests to prevent
70 operational changes) */
71 0x07, /* Persistent/current */
72 0x04, /* Additional Length */
73
74 0x02, 0x00, 0x00, 0x00, /* Physical Interface Standard */
75
76 /* Feature Descriptor */
77 0x00, 0x03, /* Feature Code : Removable Medium (The medium may be removed
78 from the device ) */
79 0x0b, /* Persistent/current */
80 0x04, /* Additional Length */
81
82 0x2b, 0x00, 0x00, 0x00, /* Physical Interface Standard */
83
84 /* Feature Descriptor */
85 0x00, 0x10, /* Feature Code : Random Readable (Read ability for storage devices
86 with random addressing) */
87 0x00, /* Persistent/current */
88 0x08, /* Additional Length */
89
90 0x00, 0x00, 0x08, 0x00, /* */
91 0x00, 0x01, 0x01, 0x00, /* */
92
93 /* Feature Descriptor */
94 0x00, 0x1d, /* Feature Code : MultiRead (The logical unit can read all CD media types) */
95 0x00, /* Persistent/current */
96 0x00, /* Additional Length */
97
98
99 /* Feature Descriptor */
100 0x00, 0x1e, /* Feature Code : CD Read (The ability to read CD specific structures) */
101 0x08, /* Persistent/current */
102 0x04, /* Additional Length */
103
104 0x03, 0x00, 0x00, 0x00, /* */
105
106 /* Feature Descriptor */
107 0x00, 0x1f, /* Feature Code : DVD Read (The ability to read DVD specific structures) */
108 0x08, /* Persistent/current */
109 0x04, /* Additional Length */
110
111 0x01, 0x00, 0x01, 0x00, /* */
112
113 /* Feature Descriptor */
114 0x00, 0x20, /* Feature Code : Random Writable (Write support for randomly addressed writes) */
115 0x04, /* Persistent/current */
116 0x0c, /* Additional Length */
117
118 0x00, 0x00, 0x00, 0x00, /* */
119 0x00, 0x00, 0x08, 0x00, /* */
120 0x00, 0x00, 0x01, 0x00, /* */
121
122
123 /* Feature Descriptor */
124 0x00, 0x21, /* Feature Code : Incremental Streaming Writable (Write support for sequential recording) */
125 0x0C, /* Persistent/current */
126 0x08, /* Additional Length */
127
128 0x00, 0x00, 0x00, 0x00, /* */
129 0x00, 0x00, 0x00, 0x00, /* */
130
131 /* Feature Descriptor */
132 0x00, 0x23, /* Feature Code : Formattable (Support for formatting of media.) */
133 0x08, /* Persistent/current */
134 0x08, /* Additional Length */
135
136 0x00, 0x00, 0x00, 0x00, /* */
137 0x00, 0x00, 0x00, 0x00, /* */
138
139 /* Feature Descriptor */
140 0x00, 0x24, /* Feature Code : Defect Management (Ability of the drive/media system to provide an
141 apparently defect-free space.) */
142 0x04, /* Persistent/current */
143 0x04, /* Additional Length */
144
145 0x80, 0x00, 0x00, 0x00, /* */
146
147 /* Feature Descriptor */
148 0x00, 0x26, /* Feature Code : Restricted Overwrite (Write support for media that must be written
149 in multiples of logical blocks.) */
150 0x00, /* Persistent/current */
151 0x00, /* Additional Length */
152
153
154 /* Feature Descriptor */
155 0x00, 0x2d, /* Feature Code : CD Track at Once (Ability to write CD with Track at Once recording) */
156 0x08, /* Persistent/current */
157 0x04, /* Additional Length */
158
159 0x46, 0x00, 0x3f, 0x0f, /* */
160
161 /* Feature Descriptor */
162 0x00, 0x2e, /* Feature Code : CD Mastering (The ability to write CD with Session at Once or Raw write methods.) */
163 0x04, /* Persistent/current */
164 0x04, /* Additional Length */
165
166 0x7f, 0x00, 0x0d, 0x00, /* */
167
168 /* Feature Descriptor */
169 0x00, 0x2f, /* Feature Code : DVD-R Write (The ability to write DVD specific structures) */
170 0x08, /* Persistent/current */
171 0x04, /* Additional Length */
172
173 0x4e, 0x00, 0x00, 0x00, /* */
174
175
176 0x01, 0x00, /* Feature Code : Power Management (Initiator and device directed power management) */
177 0x07, /* Persistent/current */
178 0x04, /* Additional Length */
179
180 0x00, 0x00, 0x00, 0x00, /* */
181
182
183 0x01, 0x01, /* Feature Code : S.M.A.R.T. (Self Monitoring Analysis and Reporting Technology (Failure prediction)) */
184 0x00, /* Persistent/current */
185 0x04, /* Additional Length */
186
187 0x00, 0x00, 0x00, 0x00, /* */
188
189 0x01, 0x08, /* Feature Code : Logical Unit serial number (Logical unit has a unique identifier) */
190 0x03, /* Persistent/current */
191 0x10, /* Additional Length */
192
193 0x53, 0x31, 0x33, 0x36, /* Serial Number */
194 0x36, 0x59, 0x42, 0x46,
195 0x37, 0x30, 0x30, 0x39,
196 0x45, 0x48, 0x20, 0x20,
197
198 0x01, 0x0a, /* Feature Code : Not sure : says FDC STC TOC */
199 0x00, /* Persistent/current */
200 0x0c, /* Additional Length */
201
202 0x46, 0x44, 0x43, 0x00,
203 0x53, 0x54, 0x43, 0x00,
204 0x54, 0x4F, 0x43, 0x00,
205 };
206
207
208 #define USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_ACTIVE_PROFILE_LENGTH 112
209 #define USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_ACTIVE_HEADER_LENGTH 8
210 #define USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_ACTIVE_FEATURE_DESCRIPTOR_LENGTH 32
211 #define USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_ACTIVE_FEATURE_HEADER_LENGTH 4
212 #define USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_ACTIVE_FEATURE_LENGTH (USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_ACTIVE_PROFILE_LENGTH - USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_ACTIVE_FEATURE_DESCRIPTOR_LENGTH - USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_ACTIVE_HEADER_LENGTH)
213 UCHAR usbx_device_class_storage_configuration_active_profile[] = {
214
215 /* Feature Header */
216 0x00, 0x00, /* Entire length of profile filled by firmware */
217 0x00, 0x00,
218 0x00, 0x00,
219 0x00, 0x08, /* Current profile is CD-ROM*/
220
221 /* Feature Descriptor */
222 0x00, 0x00, /* Feature Code : profile list */
223 0x00, /* Persistent/current */
224 0x1c, /* Additional Length */
225
226 0x00, 0x12, 0x00, 0x00, /* DVD-RAM */
227 0x00, 0x11, 0x00, 0x00, /* DVD-R */
228 0x00, 0x10, 0x00, 0x00, /* DVD-ROM */
229 0x00, 0x0A, 0x00, 0x00, /* CD-RW */
230 0x00, 0x09, 0x00, 0x00, /* CD-R */
231 0x00, 0x08, 0x01, 0x00, /* CD-ROM : active profile */
232 0x00, 0x02, 0x00, 0x00, /* Writable capable with removable media. */
233
234
235 /* Feature Descriptor */
236 0x00, 0x01, /* Feature Code : core feature */
237 0x0b, /* Persistent/current */
238 0x08, /* Additional Length */
239
240 0x00, 0x00, 0x00, 0x07, /* Physical Interface Standard */
241 0x01, 0x00, 0x00, 0x00, /* */
242
243 /* Feature Descriptor */
244 0x00, 0x02, /* Feature Code : morphing (Ability to notify initiator about
245 operational changes and accept initiator requests to prevent
246 operational changes) */
247 0x07, /* Persistent/current */
248 0x04, /* Additional Length */
249
250 0x02, 0x00, 0x00, 0x00, /* Physical Interface Standard */
251
252 /* Feature Descriptor */
253 0x00, 0x03, /* Feature Code : Removable Medium (The medium may be removed
254 from the device ) */
255 0x0b, /* Persistent/current */
256 0x04, /* Additional Length */
257
258 0x2b, 0x00, 0x00, 0x00, /* Physical Interface Standard */
259
260 /* Feature Descriptor */
261 0x00, 0x10, /* Feature Code : Random Readable (Read ability for storage devices
262 with random addressing) */
263 0x01, /* Persistent/current */
264 0x08, /* Additional Length */
265
266 0x00, 0x00, 0x08, 0x00, /* */
267 0x00, 0x01, 0x01, 0x00, /* */
268
269 /* Feature Descriptor */
270 0x00, 0x1d, /* Feature Code : MultiRead (The logical unit can read all CD media types) */
271 0x01, /* Persistent/current */
272 0x00, /* Additional Length */
273
274
275 /* Feature Descriptor */
276 0x00, 0x1e, /* Feature Code : CD Read (The ability to read CD specific structures) */
277 0x09, /* Persistent/current */
278 0x04, /* Additional Length */
279
280 0x03, 0x00, 0x00, 0x00, /* */
281
282
283 0x01, 0x08, /* Feature Code : Logical Unit serial number (Logical unit has a unique identifier) */
284 0x03, /* Persistent/current */
285 0x10, /* Additional Length */
286
287 0x53, 0x31, 0x33, 0x36, /* Serial Number */
288 0x36, 0x59, 0x42, 0x46,
289 0x37, 0x30, 0x30, 0x39,
290 0x45, 0x48, 0x20, 0x20,
291
292 };
293
294 #if (UX_SLAVE_REQUEST_DATA_MAX_LENGTH < USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_ACTIVE_PROFILE_LENGTH) ||\
295 (UX_SLAVE_REQUEST_DATA_MAX_LENGTH < USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_PROFILE_LENGTH)
296 #error UX_SLAVE_REQUEST_DATA_MAX_LENGTH too small, please check
297 #endif
298
299
300 /**************************************************************************/
301 /* */
302 /* FUNCTION RELEASE */
303 /* */
304 /* _ux_device_class_storage_get_configuration PORTABLE C */
305 /* 6.1.10 */
306 /* AUTHOR */
307 /* */
308 /* Chaoqiong Xiao, Microsoft Corporation */
309 /* */
310 /* DESCRIPTION */
311 /* */
312 /* This function performs a GET_CONFIGURATION command. */
313 /* */
314 /* INPUT */
315 /* */
316 /* storage Pointer to storage class */
317 /* endpoint_in Pointer to IN endpoint */
318 /* endpoint_out Pointer to OUT endpoint */
319 /* cbwcb Pointer to CBWCB */
320 /* */
321 /* OUTPUT */
322 /* */
323 /* Completion Status */
324 /* */
325 /* CALLS */
326 /* */
327 /* _ux_device_class_storage_csw_send Send CSW */
328 /* _ux_device_stack_transfer_request Transfer request */
329 /* _ux_device_stack_endpoint_stall Stall endpoint */
330 /* _ux_utility_short_get_big_endian Get 16-bit big endian */
331 /* _ux_utility_long_put_big_endian Put 32-bit big endian */
332 /* _ux_utility_memory_copy Copy memory */
333 /* */
334 /* CALLED BY */
335 /* */
336 /* Device Storage Class */
337 /* */
338 /* RELEASE HISTORY */
339 /* */
340 /* DATE NAME DESCRIPTION */
341 /* */
342 /* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */
343 /* 09-30-2020 Chaoqiong Xiao Modified comment(s), */
344 /* optimized command logic, */
345 /* verified memset and memcpy */
346 /* cases, */
347 /* resulting in version 6.1 */
348 /* 01-31-2022 Chaoqiong Xiao Modified comment(s), */
349 /* added standalone support, */
350 /* resulting in version 6.1.10 */
351 /* */
352 /**************************************************************************/
_ux_device_class_storage_get_configuration(UX_SLAVE_CLASS_STORAGE * storage,ULONG lun,UX_SLAVE_ENDPOINT * endpoint_in,UX_SLAVE_ENDPOINT * endpoint_out,UCHAR * cbwcb)353 UINT _ux_device_class_storage_get_configuration(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun,
354 UX_SLAVE_ENDPOINT *endpoint_in,
355 UX_SLAVE_ENDPOINT *endpoint_out, UCHAR * cbwcb)
356 {
357
358 UINT status = 0;
359 UX_SLAVE_TRANSFER *transfer_request;
360 ULONG starting_feature;
361 ULONG allocation_length;
362 ULONG additional_length;
363 ULONG profile_counter;
364 UCHAR *profile_pointer;
365 ULONG feature;
366
367 UX_PARAMETER_NOT_USED(endpoint_out);
368
369 /* If trace is enabled, insert this event into the trace buffer. */
370 UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_STORAGE_GET_CONFIGURATION, storage, lun, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0)
371
372 /* Initialize the length of the configuration profile. */
373 _ux_utility_long_put_big_endian(usbx_device_class_storage_configuration_profile, (USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_PROFILE_LENGTH - 4));
374
375 /* Initialize the length of the active configuration profile. */
376 _ux_utility_long_put_big_endian(usbx_device_class_storage_configuration_active_profile, (USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_ACTIVE_PROFILE_LENGTH - 4));
377
378 /* Obtain the pointer to the transfer request. */
379 transfer_request = &endpoint_in -> ux_slave_endpoint_transfer_request;
380
381 /* Get the Starting Feature. */
382 starting_feature = _ux_utility_short_get_big_endian(cbwcb + UX_SLAVE_CLASS_STORAGE_GET_CONFIGURATION_STARTING_FEATURE);
383
384 /* Get the allocation length. */
385 allocation_length = _ux_utility_short_get_big_endian(cbwcb + UX_SLAVE_CLASS_STORAGE_GET_CONFIGURATION_ALLOCATION_LENGTH);
386
387 /* Default CSW to success. */
388 storage -> ux_slave_class_storage_csw_status = UX_SLAVE_CLASS_STORAGE_CSW_PASSED;
389
390 /* Is the request demanding all the features ? */
391 if (starting_feature == 0)
392 {
393
394 /* Is the requester demanding the active profile ? */
395 if ((*(cbwcb + UX_SLAVE_CLASS_STORAGE_GET_CONFIGURATION_RT) & 3) == 1)
396 {
397
398 /* We get the active profile. */
399 /* Can we send all the activeconfiguration profile ? If not, the host may demand the first part of the configuration to get the entire length.
400 In this case, return the length demanded by the host. */
401 if (allocation_length >= USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_ACTIVE_PROFILE_LENGTH)
402
403 /* Adjust allocation length to maximum allowed. */
404 allocation_length = USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_ACTIVE_PROFILE_LENGTH;
405
406 /* Copy the CSW into the transfer request memory. */
407 _ux_utility_memory_copy(transfer_request -> ux_slave_transfer_request_data_pointer,
408 usbx_device_class_storage_configuration_active_profile,
409 allocation_length); /* Use case of memcpy is verified. */
410 }
411 else
412 {
413
414 /* We get the whole profile. */
415 /* Can we send all the configuration profile ? If not, the host may demand the first part of the configuration to get the entire length.
416 In this case, return the length demanded by the host. */
417 if (allocation_length >= USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_PROFILE_LENGTH)
418
419 /* Adjust allocation length to maximum allowed. */
420 allocation_length = USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_PROFILE_LENGTH;
421
422 /* Copy the CSW into the transfer request memory. */
423 _ux_utility_memory_copy(transfer_request -> ux_slave_transfer_request_data_pointer,
424 usbx_device_class_storage_configuration_profile,
425 allocation_length); /* Use case of memcpy is verified. */
426
427 }
428
429 /* Now success. */
430 status = UX_SUCCESS;
431 }
432 else
433 {
434
435 /* The caller has demanded a specific feature. Scan our configuration profile. Jump over the beginning sections. */
436 profile_pointer = usbx_device_class_storage_configuration_profile + USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_HEADER_LENGTH +
437 USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_FEATURE_DESCRIPTOR_LENGTH;
438 profile_counter = USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_FEATURE_LENGTH;
439
440 /* Scan our configuration profile. */
441 while (profile_counter != 0)
442 {
443
444 /* Extract the feature from the configuration profile. */
445 feature = _ux_utility_short_get_big_endian(profile_pointer + USBX_DEVICE_CLASS_STORAGE_FEATURE_DESCRIPTOR_FEATURE_CODE);
446
447 /* Extract the feature length from the configuration profile. */
448 additional_length = (ULONG ) *(profile_pointer + USBX_DEVICE_CLASS_STORAGE_FEATURE_DESCRIPTOR_FEATURE_ADD_LENGTH);
449
450 /* Compare the Feature extracted with the one demanded. */
451 if (feature == starting_feature)
452 {
453
454 /* We found the feature, we check if the requester has enough space for us to return it. */
455 if (allocation_length >= (additional_length + USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_HEADER_LENGTH +
456 USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_FEATURE_HEADER_LENGTH))
457
458 /* Need to adjust the allocation length. */
459 allocation_length = additional_length + USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_HEADER_LENGTH +
460 USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_FEATURE_HEADER_LENGTH;
461
462 /* Copy the CSW into the transfer request memory. */
463 _ux_utility_memory_copy(transfer_request -> ux_slave_transfer_request_data_pointer,
464 profile_pointer,
465 allocation_length); /* Use case of memcpy is verified. */
466
467 /* Now success. */
468 status = UX_SUCCESS;
469
470 /* Get out of the loop. */
471 break;
472 }
473 else
474 {
475
476 /* We have not yet found the feature, keep parsing. */
477 if (profile_counter - additional_length - USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_FEATURE_HEADER_LENGTH <= 0)
478 {
479
480 /* We are either at the end of the profile or the profile is corrupted. */
481
482 /* And update the REQUEST_SENSE codes. */
483 storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_sense_status =
484 UX_DEVICE_CLASS_STORAGE_SENSE_STATUS(UX_SLAVE_CLASS_STORAGE_SENSE_KEY_ILLEGAL_REQUEST,0x26,0x02);
485
486 /* Now we set the CSW with failure. */
487 storage -> ux_slave_class_storage_csw_status = UX_SLAVE_CLASS_STORAGE_CSW_FAILED;
488
489 /* Set status to error. */
490 status = UX_ERROR;
491
492 /* Get out of the loop. */
493 break;
494
495 }
496 else
497 {
498
499 /* Update the profile pointer. */
500 profile_pointer += additional_length + USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_FEATURE_HEADER_LENGTH;
501
502 /* Update the length remaining to parse in profile. */
503 profile_counter -= additional_length + USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_FEATURE_HEADER_LENGTH;
504 }
505 }
506 }
507 }
508
509 /* Success, send data. */
510 if (status == UX_SUCCESS)
511 {
512
513 #if defined(UX_DEVICE_STANDALONE)
514
515 /* Next: Transfer (DATA). */
516 storage -> ux_device_class_storage_state = UX_DEVICE_CLASS_STORAGE_STATE_TRANS_START;
517 storage -> ux_device_class_storage_cmd_state = UX_DEVICE_CLASS_STORAGE_CMD_READ;
518
519 storage -> ux_device_class_storage_transfer = transfer_request;
520 storage -> ux_device_class_storage_device_length = allocation_length;
521 storage -> ux_device_class_storage_data_length = allocation_length;
522 storage -> ux_device_class_storage_data_count = 0;
523 UX_SLAVE_TRANSFER_STATE_RESET(storage -> ux_device_class_storage_transfer);
524 #else
525
526 /* Send a data payload with the read_capacity response buffer. */
527 _ux_device_stack_transfer_request(transfer_request,
528 allocation_length,
529 allocation_length);
530 #endif
531
532 }
533 else
534 {
535
536 /* Error, stall. */
537 #if !defined(UX_DEVICE_STANDALONE)
538 _ux_device_stack_endpoint_stall(endpoint_in);
539 #endif
540 }
541
542 /* Return completion status. */
543 return(status);
544 }
545
546