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 
32 #if UX_SLAVE_CLASS_STORAGE_BUFFER_SIZE < 20
33 /* #error UX_SLAVE_CLASS_STORAGE_BUFFER_SIZE too small, please check  */
34 /* Build option checked runtime by UX_ASSERT  */
35 #endif
36 
37 /**************************************************************************/
38 /*                                                                        */
39 /*  FUNCTION                                               RELEASE        */
40 /*                                                                        */
41 /*    _ux_device_class_storage_read_toc                   PORTABLE C      */
42 /*                                                           6.3.0        */
43 /*  AUTHOR                                                                */
44 /*                                                                        */
45 /*    Chaoqiong Xiao, Microsoft Corporation                               */
46 /*                                                                        */
47 /*  DESCRIPTION                                                           */
48 /*                                                                        */
49 /*    This function performs a READ_TOC SCSI command. This is only for    */
50 /*    supporting CD-ROM emulation and is hardwired to what Windows wants. */
51 /*                                                                        */
52 /*  INPUT                                                                 */
53 /*                                                                        */
54 /*    storage                               Pointer to storage class      */
55 /*    endpoint_in                           Pointer to IN endpoint        */
56 /*    endpoint_out                          Pointer to OUT endpoint       */
57 /*    cbwcb                                 Pointer to CBWCB              */
58 /*                                                                        */
59 /*  OUTPUT                                                                */
60 /*                                                                        */
61 /*    Completion Status                                                   */
62 /*                                                                        */
63 /*  CALLS                                                                 */
64 /*                                                                        */
65 /*    _ux_device_stack_transfer_request     Transfer request              */
66 /*    _ux_device_class_storage_csw_send     Send CSW                      */
67 /*    _ux_utility_memory_set                Set memory                    */
68 /*    _ux_utility_memory_copy               Copy memory                   */
69 /*    _ux_utility_short_get_big_endian      Get 16-bit big endian         */
70 /*                                                                        */
71 /*  CALLED BY                                                             */
72 /*                                                                        */
73 /*    Device Storage Class                                                */
74 /*                                                                        */
75 /*  RELEASE HISTORY                                                       */
76 /*                                                                        */
77 /*    DATE              NAME                      DESCRIPTION             */
78 /*                                                                        */
79 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
80 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
81 /*                                            optimized command logic,    */
82 /*                                            verified memset and memcpy  */
83 /*                                            cases,                      */
84 /*                                            resulting in version 6.1    */
85 /*  01-31-2022     Chaoqiong Xiao           Modified comment(s),          */
86 /*                                            added standalone support,   */
87 /*                                            resulting in version 6.1.10 */
88 /*  10-31-2023     Chaoqiong Xiao           Modified comment(s),          */
89 /*                                            checked compiling options   */
90 /*                                            by runtime UX_ASSERT,       */
91 /*                                            resulting in version 6.3.0  */
92 /*                                                                        */
93 /**************************************************************************/
_ux_device_class_storage_read_toc(UX_SLAVE_CLASS_STORAGE * storage,ULONG lun,UX_SLAVE_ENDPOINT * endpoint_in,UX_SLAVE_ENDPOINT * endpoint_out,UCHAR * cbwcb)94 UINT  _ux_device_class_storage_read_toc(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun,
95                                             UX_SLAVE_ENDPOINT *endpoint_in,
96                                             UX_SLAVE_ENDPOINT *endpoint_out, UCHAR * cbwcb)
97 {
98 
99 UINT                    status;
100 UX_SLAVE_TRANSFER       *transfer_request;
101 ULONG                   allocation_length;
102 ULONG                   toc_length;
103 UCHAR                   *toc_buffer;
104 
105 
106     UX_PARAMETER_NOT_USED(lun);
107     UX_PARAMETER_NOT_USED(endpoint_out);
108 
109     /* Build option check.  */
110     UX_ASSERT(UX_SLAVE_CLASS_STORAGE_BUFFER_SIZE >= 20);
111 
112     /* If trace is enabled, insert this event into the trace buffer.  */
113     UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_STORAGE_READ_TOC, storage, lun, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0)
114 
115     /* Obtain the pointer to the transfer request.  */
116     transfer_request =  &endpoint_in -> ux_slave_endpoint_transfer_request;
117 
118     /* Obtain TOC buffer.  */
119     toc_buffer = transfer_request -> ux_slave_transfer_request_data_pointer;
120 
121     /* Reset this buffer.  */
122     _ux_utility_memory_set(toc_buffer,0,20); /* Use case of memset is verified. */
123 
124     /* Get the allocation length.  */
125     allocation_length =  _ux_utility_short_get_big_endian(cbwcb + UX_SLAVE_CLASS_STORAGE_READ_TOC_ALLOCATION_LENGTH);
126 
127     /* Insert the fist and last tack number.  */
128     toc_buffer[2] =  0x01;
129     toc_buffer[3] =  0x01;
130 
131     /* Set TOC length by default.  */
132     toc_length = 20;
133 
134     /* Insert the ADR and control values.  */
135     toc_buffer[5] =  0x14;
136 
137     /* Insert the TOC tack number.  */
138     toc_buffer[6] =  0x01;
139 
140     /* Check if the request is for the TOC or time stamp.  */
141     switch (*(cbwcb + UX_SLAVE_CLASS_STORAGE_READ_TOC_FORMAT))
142     {
143 
144         case  0x02 :
145 
146             /* Set the toc buffer length.  */
147             toc_length  = 20;
148 
149             /* Insert the TOC buffer length.  */
150             toc_buffer[1] =  0x12;
151 
152             /* Insert some time values.  */
153             toc_buffer[10] =  0x02;
154             toc_buffer[13] =  0x17;
155             toc_buffer[14] =  0xAA;
156             toc_buffer[18] =  0x04;
157             toc_buffer[19] =  0x1a;
158 
159             break;
160 
161         case 0x01 :
162 
163             /* Set the toc buffer length.  */
164             toc_length  = 19;
165 
166             /* Insert the TOC buffer length.  */
167             toc_buffer[1] =  0x12;
168 
169             toc_buffer[13] =  0x17;
170             toc_buffer[14] =  0xAA;
171             toc_buffer[19] =  0xb0;
172 
173             break;
174 
175         case 0x00 :
176 
177             /* Set the toc buffer length.  */
178             toc_length  = 20;
179 
180             /* Insert the TOC buffer length.  */
181             toc_buffer[1] =  0x12;
182 
183             /* Insert some time values.  */
184             toc_buffer[10] =  0x02;
185             toc_buffer[13] =  0x17;
186             toc_buffer[14] =  0xAA;
187             toc_buffer[18] =  0x04;
188             toc_buffer[19] =  0x1a;
189 
190             break;
191     }
192 
193     /* Check how much we can send back.  */
194     if (allocation_length > toc_length)
195 
196         /* We return less than demanded.  */
197         allocation_length = toc_length;
198 
199 #if defined(UX_DEVICE_STANDALONE)
200 
201     /* Next: Transfer (DATA).  */
202     storage -> ux_device_class_storage_state = UX_DEVICE_CLASS_STORAGE_STATE_TRANS_START;
203     storage -> ux_device_class_storage_cmd_state = UX_DEVICE_CLASS_STORAGE_CMD_READ;
204 
205     storage -> ux_device_class_storage_transfer = transfer_request;
206     storage -> ux_device_class_storage_device_length = allocation_length;
207     storage -> ux_device_class_storage_data_length = allocation_length;
208     storage -> ux_device_class_storage_data_count = 0;
209 
210 #else
211 
212     /* Send a data payload with the TOC response buffer.  */
213     _ux_device_stack_transfer_request(transfer_request, allocation_length, allocation_length);
214 #endif
215 
216     /* Now we set the CSW with success.  */
217     storage -> ux_slave_class_storage_csw_status = UX_SLAVE_CLASS_STORAGE_CSW_PASSED;
218     status = UX_SUCCESS;
219 
220     /* Return completion status.  */
221     return(status);
222 
223 }
224 
225