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 
33 #if UX_SLAVE_CLASS_STORAGE_BUFFER_SIZE < 20
34 #error UX_SLAVE_CLASS_STORAGE_BUFFER_SIZE too small, please check
35 #endif
36 
37 /**************************************************************************/
38 /*                                                                        */
39 /*  FUNCTION                                               RELEASE        */
40 /*                                                                        */
41 /*    _ux_device_class_storage_read_toc                   PORTABLE C      */
42 /*                                                           6.1.10       */
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 /*                                                                        */
89 /**************************************************************************/
_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)90 UINT  _ux_device_class_storage_read_toc(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun,
91                                             UX_SLAVE_ENDPOINT *endpoint_in,
92                                             UX_SLAVE_ENDPOINT *endpoint_out, UCHAR * cbwcb)
93 {
94 
95 UINT                    status;
96 UX_SLAVE_TRANSFER       *transfer_request;
97 ULONG                   allocation_length;
98 ULONG                   toc_length;
99 UCHAR                   *toc_buffer;
100 
101 
102     UX_PARAMETER_NOT_USED(lun);
103     UX_PARAMETER_NOT_USED(endpoint_out);
104 
105     /* If trace is enabled, insert this event into the trace buffer.  */
106     UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_STORAGE_READ_TOC, storage, lun, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0)
107 
108     /* Obtain the pointer to the transfer request.  */
109     transfer_request =  &endpoint_in -> ux_slave_endpoint_transfer_request;
110 
111     /* Obtain TOC buffer.  */
112     toc_buffer = transfer_request -> ux_slave_transfer_request_data_pointer;
113 
114     /* Reset this buffer.  */
115     _ux_utility_memory_set(toc_buffer,0,20); /* Use case of memset is verified. */
116 
117     /* Get the allocation length.  */
118     allocation_length =  _ux_utility_short_get_big_endian(cbwcb + UX_SLAVE_CLASS_STORAGE_READ_TOC_ALLOCATION_LENGTH);
119 
120     /* Insert the fist and last tack number.  */
121     toc_buffer[2] =  0x01;
122     toc_buffer[3] =  0x01;
123 
124     /* Set TOC length by default.  */
125     toc_length = 20;
126 
127     /* Insert the ADR and control values.  */
128     toc_buffer[5] =  0x14;
129 
130     /* Insert the TOC tack number.  */
131     toc_buffer[6] =  0x01;
132 
133     /* Check if the request is for the TOC or time stamp.  */
134     switch (*(cbwcb + UX_SLAVE_CLASS_STORAGE_READ_TOC_FORMAT))
135     {
136 
137         case  0x02 :
138 
139             /* Set the toc buffer length.  */
140             toc_length  = 20;
141 
142             /* Insert the TOC buffer length.  */
143             toc_buffer[1] =  0x12;
144 
145             /* Insert some time values.  */
146             toc_buffer[10] =  0x02;
147             toc_buffer[13] =  0x17;
148             toc_buffer[14] =  0xAA;
149             toc_buffer[18] =  0x04;
150             toc_buffer[19] =  0x1a;
151 
152             break;
153 
154         case 0x01 :
155 
156             /* Set the toc buffer length.  */
157             toc_length  = 19;
158 
159             /* Insert the TOC buffer length.  */
160             toc_buffer[1] =  0x12;
161 
162             toc_buffer[13] =  0x17;
163             toc_buffer[14] =  0xAA;
164             toc_buffer[19] =  0xb0;
165 
166             break;
167 
168         case 0x00 :
169 
170             /* Set the toc buffer length.  */
171             toc_length  = 20;
172 
173             /* Insert the TOC buffer length.  */
174             toc_buffer[1] =  0x12;
175 
176             /* Insert some time values.  */
177             toc_buffer[10] =  0x02;
178             toc_buffer[13] =  0x17;
179             toc_buffer[14] =  0xAA;
180             toc_buffer[18] =  0x04;
181             toc_buffer[19] =  0x1a;
182 
183             break;
184     }
185 
186     /* Check how much we can send back.  */
187     if (allocation_length > toc_length)
188 
189         /* We return less than demanded.  */
190         allocation_length = toc_length;
191 
192 #if defined(UX_DEVICE_STANDALONE)
193 
194     /* Next: Transfer (DATA).  */
195     storage -> ux_device_class_storage_state = UX_DEVICE_CLASS_STORAGE_STATE_TRANS_START;
196     storage -> ux_device_class_storage_cmd_state = UX_DEVICE_CLASS_STORAGE_CMD_READ;
197 
198     storage -> ux_device_class_storage_transfer = transfer_request;
199     storage -> ux_device_class_storage_device_length = allocation_length;
200     storage -> ux_device_class_storage_data_length = allocation_length;
201     storage -> ux_device_class_storage_data_count = 0;
202 
203 #else
204 
205     /* Send a data payload with the TOC response buffer.  */
206     _ux_device_stack_transfer_request(transfer_request, allocation_length, allocation_length);
207 #endif
208 
209     /* Now we set the CSW with success.  */
210     storage -> ux_slave_class_storage_csw_status = UX_SLAVE_CLASS_STORAGE_CSW_PASSED;
211     status = UX_SUCCESS;
212 
213     /* Return completion status.  */
214     return(status);
215 
216 }
217 
218