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 /**   Utility                                                             */
18 /**                                                                       */
19 /**************************************************************************/
20 /**************************************************************************/
21 
22 /* Include necessary system files.  */
23 
24 #define UX_SOURCE_CODE
25 
26 #include "ux_api.h"
27 
28 
29 #ifdef UX_ENABLE_DEBUG_LOG
30 
31 /**************************************************************************/
32 /*                                                                        */
33 /*  FUNCTION                                               RELEASE        */
34 /*                                                                        */
35 /*    _ux_utility_debug_log                               PORTABLE C      */
36 /*                                                           6.1          */
37 /*  AUTHOR                                                                */
38 /*                                                                        */
39 /*    Chaoqiong Xiao, Microsoft Corporation                               */
40 /*                                                                        */
41 /*  DESCRIPTION                                                           */
42 /*                                                                        */
43 /*    This function logs a debug msg in a circular queue. The queue       */
44 /*    must be initialized during the init of USBX.                        */
45 /*                                                                        */
46 /*                                                                        */
47 /*  INPUT                                                                 */
48 /*                                                                        */
49 /*   debug_location                         C string to locate the debug, */
50 /*                                          for example source file name. */
51 /*   debug_message                          C string of message           */
52 /*   debug_code                             Debug code                    */
53 /*   debug_parameter_1                      First parameter               */
54 /*   debug_parameter_2                      Second parameter              */
55 /*                                                                        */
56 /*                                                                        */
57 /*  OUTPUT                                                                */
58 /*                                                                        */
59 /*    None                                                                */
60 /*                                                                        */
61 /*  CALLS                                                                 */
62 /*                                                                        */
63 /*    _ux_utility_string_length_check       Check C string and return     */
64 /*                                          its length if null-terminated */
65 /*    _tx_time_get                          Return system clock time      */
66 /*                                                                        */
67 /*  CALLED BY                                                             */
68 /*                                                                        */
69 /*    Application                                                         */
70 /*                                                                        */
71 /*  RELEASE HISTORY                                                       */
72 /*                                                                        */
73 /*    DATE              NAME                      DESCRIPTION             */
74 /*                                                                        */
75 /*  05-19-2020     Chaoqiong Xiao           Initial Version 6.0           */
76 /*  09-30-2020     Chaoqiong Xiao           Modified comment(s),          */
77 /*                                            verified memset and memcpy  */
78 /*                                            cases, used UX prefix to    */
79 /*                                            refer to TX symbols instead */
80 /*                                            of using them directly,     */
81 /*                                            resulting in version 6.1    */
82 /*                                                                        */
83 /**************************************************************************/
_ux_utility_debug_log(UCHAR * debug_location,UCHAR * debug_message,ULONG debug_code,ULONG debug_parameter_1,ULONG debug_parameter_2)84 VOID  _ux_utility_debug_log(UCHAR *debug_location, UCHAR *debug_message, ULONG debug_code,
85                             ULONG debug_parameter_1, ULONG debug_parameter_2)
86 {
87 
88 UINT    debug_location_string_length;
89 UINT    debug_message_string_length;
90 ULONG   total_debug_message_length;
91 ULONG   parameter_length;
92 ULONG   parameter_shift;
93 UCHAR   parameter_hexa;
94 ULONG   local_parameter_value;
95 ULONG   current_time;
96 UX_INTERRUPT_SAVE_AREA
97 
98     /* Is USBX system completely initialized ?  */
99     if (_ux_system -> ux_system_debug_log_size == 0)
100 
101         /* Not yet.  */
102         return;
103 
104     /* Entering critical area. Disable interrupts.  */
105     UX_DISABLE
106 
107     /* Store the debug value as the last debug value recorded.  */
108     _ux_system -> ux_system_debug_code = debug_code;
109 
110     /* Increment the debug value code count.  */
111     _ux_system -> ux_system_debug_count++;
112 
113     /* Calculate the string length.  */
114     debug_location_string_length = UX_DEBUG_LOG_SIZE;
115     _ux_utility_string_length_check(source, &debug_location_string_length, UX_DEBUG_LOG_SIZE);
116     debug_message_string_length = UX_DEBUG_LOG_SIZE;
117     _ux_utility_string_length_check(source, &debug_message_string_length, UX_DEBUG_LOG_SIZE);
118 
119     /* Calculate the length of the entire message string.  1 fixed string, then 1 hexa
120        decimal, then 2 strings then 2 hexa decimal numbers in the format 0x00000000
121        separated by commas and . at the end, zero terminated.  */
122     total_debug_message_length = debug_location_string_length + debug_message_string_length + 10 + 10 + 10 + 10 + 5;
123 
124     /* Can we accommodate this debug value message at the current location ?  */
125     if (total_debug_message_length >= _ux_system -> ux_system_debug_log_size)
126         return;
127     if (_ux_system -> ux_system_debug_log_head +  total_debug_message_length >
128         ux_system -> ux_system_debug_log_buffer + _ux_system -> ux_system_debug_log_size)
129     {
130 
131         /* The debug value log to insert goes beyond the end of the log buffer, rewind to the beginning.  */
132         _ux_system -> ux_system_debug_log_head = _ux_system -> ux_system_debug_log_buffer;
133     }
134 
135     /* Copy the time strings and parameters in the log buffer.  */
136     _ux_utility_memory_copy(_ux_system -> ux_system_debug_log_head, "At time : ", 10); /* Use case of memcpy is verified. */
137     _ux_system -> ux_system_debug_log_head += 10;
138 
139     /* Get the time value from TX.  */
140     current_time = _tx_time_get();
141 
142     /* Reset the value of the length.*/
143     parameter_length = 0;
144 
145     /* Init the shift value.  */
146     parameter_shift = 32 - 4;
147 
148     /* We parse the hexa value parameter and build the hexa value one byte at a type.  */
149     while(parameter_length < 8)
150     {
151 
152         /* Shift the 4 bit value we are interested in.  We keep the lowest nibble.  */
153         local_parameter_value = (current_time >> parameter_shift) & 0x0f;
154 
155         /* See if this value is from 0-9 or A to F.  */
156         if (local_parameter_value <= 9)
157 
158             /* We have a digit.  */
159             parameter_hexa = (UCHAR) (local_parameter_value + '0');
160 
161         else
162 
163             /* We have  'A' to 'F' value.  */
164             parameter_hexa = (UCHAR) (local_parameter_value - 10 + 'A');
165 
166         /* Store the converted hexa value.  */
167         *_ux_system -> ux_system_debug_log_head = parameter_hexa;
168 
169         /* Next position.  */
170         _ux_system -> ux_system_debug_log_head++;
171 
172         /* Update length.  */
173         parameter_length++;
174 
175         /* Continue shifting by one nibble.  */
176         parameter_shift = parameter_shift - 4;
177     }
178 
179     /* Add the comma after the time.  */
180     *_ux_system -> ux_system_debug_log_head = ',';
181     _ux_system -> ux_system_debug_log_head++;
182 
183     /* Copy the strings and parameters in the log buffer.  */
184     _ux_utility_memory_copy(_ux_system -> ux_system_debug_log_head, debug_location, debug_location_string_length); /* Use case of memcpy is verified. */
185     _ux_system -> ux_system_debug_log_head += debug_location_string_length;
186     *_ux_system -> ux_system_debug_log_head = ',';
187     _ux_system -> ux_system_debug_log_head++;
188     _ux_utility_memory_copy(_ux_system -> ux_system_debug_log_head, debug_message, debug_message_string_length); /* Use case of memcpy is verified. */
189     _ux_system -> ux_system_debug_log_head += debug_message_string_length;
190     *_ux_system -> ux_system_debug_log_head = ',';
191     _ux_system -> ux_system_debug_log_head++;
192 
193     /* Create the hexa string for parameter 1.  */
194     *_ux_system -> ux_system_debug_log_head = '0';
195     _ux_system -> ux_system_debug_log_head++;
196     *_ux_system -> ux_system_debug_log_head = 'x';
197     _ux_system -> ux_system_debug_log_head++;
198 
199     /* Reset the value of the length.*/
200     parameter_length = 0;
201 
202     /* Init the shift value.  */
203     parameter_shift = 32 - 4;
204 
205     /* We parse the hexa value parameter and build the hexa value one byte at a type.  */
206     while(parameter_length < 8)
207     {
208 
209         /* Shift the 4 bit value we are interested in.  We keep the lowest nibble.  */
210         local_parameter_value = (debug_parameter_1 >> parameter_shift) & 0x0f;
211 
212         /* See if this value is from 0-9 or A to F.  */
213         if (local_parameter_value <= 9)
214 
215             /* We have a digit.  */
216             parameter_hexa = (UCHAR) (local_parameter_value + '0');
217 
218         else
219 
220             /* We have  'A' to 'F' value.  */
221             parameter_hexa = (UCHAR) (local_parameter_value - 10 + 'A');
222 
223         /* Store the converted hexa value.  */
224         *_ux_system -> ux_system_debug_log_head = parameter_hexa;
225 
226         /* Next position.  */
227         _ux_system -> ux_system_debug_log_head++;
228 
229         /* Update length.  */
230         parameter_length++;
231 
232         /* Continue shifting by one nibble.  */
233         parameter_shift = parameter_shift - 4;
234     }
235 
236     /* Add the comma between the 2 hexa values.  */
237     *_ux_system -> ux_system_debug_log_head = ',';
238     _ux_system -> ux_system_debug_log_head++;
239 
240     /* Create the hexa string for parameter 2.  */
241     *_ux_system -> ux_system_debug_log_head = '0';
242     _ux_system -> ux_system_debug_log_head++;
243     *_ux_system -> ux_system_debug_log_head = 'x';
244     _ux_system -> ux_system_debug_log_head++;
245 
246     /* Reset the value of the length.*/
247     parameter_length = 0;
248 
249     /* Init the shift value.  */
250     parameter_shift = 32 - 4;
251 
252     /* We parse the hexa value parameter and build the hexa value one byte at a type.  */
253     while(parameter_length < 8)
254     {
255 
256         /* Shift the 4 bit value we are interested in.  We keep the lowest nibble.  */
257         local_parameter_value = (debug_parameter_2 >> parameter_shift) & 0x0f;
258 
259         /* See if this value is from 0-9 or A to F.  */
260         if (local_parameter_value <= 9)
261 
262             /* We have a digit.  */
263             parameter_hexa = (UCHAR) (local_parameter_value + '0');
264 
265         else
266 
267             /* We have  'A' to 'F' value.  */
268             parameter_hexa = (UCHAR) (local_parameter_value - 10 + 'A');
269 
270         /* Store the converted hexa value.  */
271         *_ux_system -> ux_system_debug_log_head = parameter_hexa;
272 
273         /* Next position.  */
274         _ux_system -> ux_system_debug_log_head++;
275 
276         /* Update length.  */
277         parameter_length++;
278 
279         /* Continue shifting by one nibble.  */
280         parameter_shift = parameter_shift - 4;
281     }
282 
283     /* Add the termination dot at the end.   */
284     *_ux_system -> ux_system_debug_log_head = '.';
285     _ux_system -> ux_system_debug_log_head++;
286 
287     /* Add the CR/LF end of the string.  */
288     *_ux_system -> ux_system_debug_log_head = 0x0d;
289     _ux_system -> ux_system_debug_log_head++;
290     *_ux_system -> ux_system_debug_log_head = 0x0a;
291     _ux_system -> ux_system_debug_log_head++;
292 
293     /* Add the zero end of the string.  */
294     *_ux_system -> ux_system_debug_log_head = 0x00;
295     _ux_system -> ux_system_debug_log_head++;
296 
297     /* The log string is put into the log buffer.  It can stay here until
298        a break into debugger by the developer or be passed to a callback registered
299        by the application.  */
300     if (_ux_system -> ux_system_debug_callback_function != UX_NULL)
301     {
302 
303         /* The callback function is defined, call it.  */
304         _ux_system -> ux_system_debug_callback_function(_ux_system -> ux_system_debug_log_tail, debug_code);
305 
306         /* Update the tail.  */
307         _ux_system -> ux_system_debug_log_tail += total_debug_message_length;
308 
309     }
310 
311     /* Restore interrupts.  */
312     UX_RESTORE
313 
314     /* We are done here. No return codes.  */
315     return;
316 }
317 
318 #endif
319