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