1 /*
2  * Copyright (c) 2015, Freescale Semiconductor, Inc.
3  * Copyright 2016-2024 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  *
8  * POSIX getopt for Windows
9  * Code given out at the 1985 UNIFORUM conference in Dallas.
10  *
11  * From std-unix@ut-sally.UUCP (Moderator, John Quarterman) Sun Nov  3 14:34:15 1985
12  * Relay-Version: version B 2.10.3 4.3bsd-beta 6/6/85; site gatech.CSNET
13  * Posting-Version: version B 2.10.2 9/18/84; site ut-sally.UUCP
14  * Path: gatech!akgua!mhuxv!mhuxt!mhuxr!ulysses!allegra!mit-eddie!genrad!panda!talcott!harvard!seismo!ut-sally!std-unix
15  * From: std-unix@ut-sally.UUCP (Moderator, John Quarterman)
16  * Newsgroups: mod.std.unix
17  * Subject: public domain AT&T getopt source
18  * Message-ID: <3352@ut-sally.UUCP>
19  * Date: 3 Nov 85 19:34:15 GMT
20  * Date-Received: 4 Nov 85 12:25:09 GMT
21  * Organization: IEEE/P1003 Portable Operating System Environment Committee
22  * Lines: 91
23  * Approved: jsq@ut-sally.UUC
24  * Here's something you've all been waiting for:  the AT&T public domain
25  * source for getopt(3).  It is the code which was given out at the 1985
26  * UNIFORUM conference in Dallas.  I obtained it by electronic mail
27  * directly from AT&T.  The people there assure me that it is indeed
28  * in the public domain
29  * There is no manual page.  That is because the one they gave out at
30  * UNIFORUM was slightly different from the current System V Release 2
31  * manual page.  The difference apparently involved a note about the
32  * famous rules 5 and 6, recommending using white space between an option
33  * and its first argument, and not grouping options that have arguments.
34  * Getopt itself is currently lenient about both of these things White
35  * space is allowed, but not mandatory, and the last option in a group can
36  * have an argument.  That particular version of the man page evidently
37  * has no official existence, and my source at AT&T did not send a copy.
38  * The current SVR2 man page reflects the actual behavor of this getopt.
39  * However, I am not about to post a copy of anything licensed by AT&T.
40  */
41 
42 #include <assert.h>
43 #include <stdarg.h>
44 #include <stdlib.h>
45 #include <stdio.h>
46 
47 #include "fsl_common.h"
48 #include "fsl_str.h"
49 
50 #include "fsl_component_generic_list.h"
51 #include "fsl_component_serial_manager.h"
52 
53 #include "fsl_shell.h"
54 
55 /*
56  * The OSA_USED macro can only be defined when the OSA component is used.
57  * If the source code of the OSA component does not exist, the OSA_USED cannot be defined.
58  * OR, If OSA component is not added into project event the OSA source code exists, the OSA_USED
59  * also cannot be defined.
60  * The source code path of the OSA component is <MCUXpresso_SDK>/components/osa.
61  *
62  */
63 #if defined(OSA_USED)
64 #if (defined(SHELL_USE_COMMON_TASK) && (SHELL_USE_COMMON_TASK > 0U))
65 #include "fsl_component_common_task.h"
66 #else
67 #include "fsl_os_abstraction.h"
68 #endif
69 
70 #endif
71 
72 /*******************************************************************************
73  * Definitions
74  ******************************************************************************/
75 #if defined(OSA_USED)
76 #define SHELL_WRITEX SHELL_WriteSynchronization
77 #else
78 #define SHELL_WRITEX SHELL_Write
79 #endif
80 
81 /* Weak function. */
82 #if defined(__GNUC__)
83 #define __WEAK_FUNC __attribute__((weak))
84 #elif defined(__ICCARM__)
85 #define __WEAK_FUNC __weak
86 #elif defined(__CC_ARM) || defined(__ARMCC_VERSION)
87 #define __WEAK_FUNC __attribute__((weak))
88 #elif defined(__DSC__) || defined(__CW__)
89 #define __WEAK_FUNC __attribute__((weak))
90 #endif
91 
92 #if (!defined(GCOV_DO_COVERAGE) || (GCOV_DO_COVERAGE == 0))
93 #define SHELL_STATIC static
94 #else
95 #define SHELL_STATIC __WEAK_FUNC
96 #endif
97 
98 #if defined(OSA_USED)
99 #if (defined(USE_RTOS) && (USE_RTOS > 0U))
100 static OSA_MUTEX_HANDLE_DEFINE(s_shellMutex);
101 #define SHELL_MUTEX_CREATE()   (void)OSA_MutexCreate(s_shellMutex)
102 #define SHELL_ENTER_CRITICAL() (void)OSA_MutexLock(s_shellMutex, osaWaitForever_c)
103 #define SHELL_EXIT_CRITICAL()  (void)OSA_MutexUnlock(s_shellMutex)
104 #else
105 #define SHELL_MUTEX_CREATE()
106 #define SHELL_ENTER_CRITICAL()
107 #define SHELL_EXIT_CRITICAL()
108 #endif
109 #else
110 #ifdef SDK_OS_FREE_RTOS
111 #include "FreeRTOS.h"
112 #include "queue.h"
113 #include "semphr.h"
114 static QueueHandle_t s_shellMutex;
115 
116 #define SHELL_MUTEX_CREATE()   s_shellMutex = xSemaphoreCreateMutex()
117 #define SHELL_ENTER_CRITICAL() (void)xSemaphoreTakeRecursive(s_shellMutex, portMAX_DELAY)
118 #define SHELL_EXIT_CRITICAL()  (void)xSemaphoreGiveRecursive(s_shellMutex)
119 #else /* BM case*/
120 #define SHELL_MUTEX_CREATE()
121 #define SHELL_ENTER_CRITICAL()
122 #define SHELL_EXIT_CRITICAL()
123 #endif
124 #endif
125 
126 #define KEY_ESC (0x1BU)
127 #define KET_DEL (0x7FU)
128 
129 #define SHELL_EVENT_DATA_ARRIVED (1U << 0)
130 #define SHELL_EVENT_DATA_SENT    (1U << 1)
131 
132 #define SHELL_SPRINTF_BUFFER_SIZE (64U)
133 
134 /*! @brief A type for the handle special key. */
135 typedef enum _fun_key_status
136 {
137     kSHELL_Normal   = 0U, /*!< Normal key */
138     kSHELL_Special  = 1U, /*!< Special key */
139     kSHELL_Function = 2U, /*!< Function key */
140 } fun_key_status_t;
141 
142 /*! @brief Data structure for Shell environment. */
143 typedef struct _shell_context_handle
144 {
145     list_label_t commandContextListHead; /*!< Command shellContextHandle list queue head */
146     serial_handle_t serialHandle;        /*!< Serial manager handle */
147     uint8_t
148         serialWriteHandleBuffer[SERIAL_MANAGER_WRITE_HANDLE_SIZE];   /*!< The buffer for serial manager write handle */
149     serial_write_handle_t serialWriteHandle;                         /*!< The serial manager write handle */
150     uint8_t serialReadHandleBuffer[SERIAL_MANAGER_READ_HANDLE_SIZE]; /*!< The buffer for serial manager read handle */
151     serial_read_handle_t serialReadHandle;                           /*!< The serial manager read handle */
152     char *prompt;                                                    /*!< Prompt string */
153 #if (defined(SHELL_NON_BLOCKING_MODE) && (SHELL_NON_BLOCKING_MODE > 0U))
154 
155 #if defined(OSA_USED)
156 
157 #if (defined(SHELL_USE_COMMON_TASK) && (SHELL_USE_COMMON_TASK > 0U))
158     common_task_message_t commontaskMsg; /*!< Message for common task */
159 #else
160     uint8_t event[OSA_EVENT_HANDLE_SIZE]; /*!< Event instance */
161     uint8_t taskId[OSA_TASK_HANDLE_SIZE]; /*!< Task handle */
162 #endif
163 
164 #endif
165 
166 #endif
167     char line[SHELL_BUFFER_SIZE];                          /*!< Consult buffer */
168     char hist_buf[SHELL_HISTORY_COUNT][SHELL_BUFFER_SIZE]; /*!< History buffer*/
169     char printBuffer[SHELL_SPRINTF_BUFFER_SIZE];           /*!< Buffer for print */
170     uint32_t printLength;                                  /*!< All length has been printed */
171     uint16_t hist_current;                                 /*!< Current history command in hist buff*/
172     uint16_t hist_count;                                   /*!< Total history command in hist buff*/
173     enum _fun_key_status stat;                             /*!< Special key status */
174     uint8_t cmd_num;                                       /*!< Number of user commands */
175     uint8_t l_pos;                                         /*!< Total line position */
176     uint8_t c_pos;                                         /*!< Current line position */
177     volatile uint8_t notificationPost;                     /*!< The serial manager notification is post */
178     uint8_t exit;                                          /*!< Exit Flag*/
179     uint8_t printBusy : 1;                                 /*!< Print is busy */
180     uint8_t taskBusy : 1;                                  /*!< Task is busy */
181 } shell_context_handle_t;
182 
183 #if 0
184 #define SHELL_STRUCT_OFFSET(type, field) ((size_t) & (((type *)0)->field))
185 #define SHEEL_COMMAND_POINTER(node) \
186     ((shell_command_t *)(((uint32_t)(node)) - SHELL_STRUCT_OFFSET(shell_command_t, link)))
187 #else
188 #define SHEEL_COMMAND_POINTER(node) \
189     ((shell_command_t *)(((uint32_t)(node)) - (sizeof(shell_command_t) - sizeof(list_element_t))))
190 #endif
191 /*******************************************************************************
192  * Prototypes
193  ******************************************************************************/
194 static shell_status_t SHELL_HelpCommand(shell_handle_t shellHandle, int32_t argc, char **argv); /*!< help command */
195 
196 static shell_status_t SHELL_ExitCommand(shell_handle_t shellHandle, int32_t argc, char **argv); /*!< exit command */
197 
198 static int32_t SHELL_ParseLine(const char *cmd, uint32_t len, char *argv[]); /*!< parse line command */
199 
200 static int32_t SHELL_StringCompare(const char *str1, const char *str2, int32_t count); /*!< compare string command */
201 
202 static void SHELL_ProcessCommand(shell_context_handle_t *shellContextHandle, const char *cmd); /*!< process a command */
203 
204 static void SHELL_GetHistoryCommand(shell_context_handle_t *shellContextHandle,
205                                     uint8_t hist_pos); /*!< get commands history */
206 
207 static void SHELL_AutoComplete(shell_context_handle_t *shellContextHandle); /*!< auto complete command */
208 
209 static shell_status_t SHELL_GetChar(shell_context_handle_t *shellContextHandle,
210                                     uint8_t *ch); /*!< get a char from communication interface */
211 
212 #if (defined(SHELL_NON_BLOCKING_MODE) && (SHELL_NON_BLOCKING_MODE > 0U))
213 SHELL_STATIC void SHELL_Task(void *param); /*!<  Shell task*/
214 #endif
215 
216 /*******************************************************************************
217  * Variables
218  ******************************************************************************/
219 
220 static SHELL_COMMAND_DEFINE(help, "\r\n\"help\": List all the registered commands\r\n", SHELL_HelpCommand, 0);
221 static SHELL_COMMAND_DEFINE(exit, "\r\n\"exit\": Exit program\r\n", SHELL_ExitCommand, 0);
222 
223 static char s_paramBuffer[SHELL_BUFFER_SIZE];
224 
225 #if (defined(SHELL_NON_BLOCKING_MODE) && (SHELL_NON_BLOCKING_MODE > 0U))
226 #if defined(OSA_USED)
227 #if (defined(SHELL_USE_COMMON_TASK) && (SHELL_USE_COMMON_TASK > 0U))
228 #else
229 /*
230  * \brief Defines the serial manager task's stack
231  */
232 static OSA_TASK_DEFINE(SHELL_Task, SHELL_TASK_PRIORITY, 1, SHELL_TASK_STACK_SIZE, false);
233 #endif
234 #endif /* OSA_USED */
235 #endif /* SHELL_NON_BLOCKING_MODE */
236 /*******************************************************************************
237  * Code
238  ******************************************************************************/
239 
240 #if (defined(SHELL_NON_BLOCKING_MODE) && (SHELL_NON_BLOCKING_MODE > 0U))
SHELL_SerialManagerRxCallback(void * callbackParam,serial_manager_callback_message_t * message,serial_manager_status_t status)241 SHELL_STATIC void SHELL_SerialManagerRxCallback(void *callbackParam,
242                                                 serial_manager_callback_message_t *message,
243                                                 serial_manager_status_t status)
244 {
245     shell_context_handle_t *shellHandle;
246 
247     assert(callbackParam);
248     assert(message);
249 
250     shellHandle = (shell_context_handle_t *)callbackParam;
251 
252     if (0U == shellHandle->notificationPost)
253     {
254         shellHandle->notificationPost = 1U;
255 #if defined(OSA_USED)
256 
257 #if (defined(SHELL_USE_COMMON_TASK) && (SHELL_USE_COMMON_TASK > 0U))
258         shellHandle->commontaskMsg.callback      = SHELL_Task;
259         shellHandle->commontaskMsg.callbackParam = shellHandle;
260         (void)COMMON_TASK_post_message(&shellHandle->commontaskMsg);
261 #else
262         (void)OSA_EventSet((osa_event_handle_t)shellHandle->event, SHELL_EVENT_DATA_ARRIVED);
263 #endif
264 
265 #else
266         SHELL_Task(shellHandle);
267 #endif
268     }
269 }
270 #endif
271 
SHELL_WriteBuffer(char * buffer,int32_t * indicator,char val,int len)272 static void SHELL_WriteBuffer(char *buffer, int32_t *indicator, char val, int len)
273 {
274     shell_context_handle_t *shellContextHandle;
275     int i              = 0;
276     shellContextHandle = (shell_context_handle_t *)(void *)buffer;
277 
278     for (i = 0; i < len; i++)
279     {
280         if ((*indicator + 1) >= (int32_t)SHELL_SPRINTF_BUFFER_SIZE)
281         {
282 #if (!defined(SDK_DEBUGCONSOLE_UART) && (defined(SDK_DEBUGCONSOLE) && (SDK_DEBUGCONSOLE != 1)))
283             if (NULL == shellContextHandle->serialHandle)
284             {
285                 for (uint32_t index = 0; index < ((uint32_t)*indicator); index++)
286                 {
287                     (void)putchar(shellContextHandle->printBuffer[index]);
288                 }
289             }
290             else
291 #endif
292             {
293                 (void)SerialManager_WriteBlocking(shellContextHandle->serialWriteHandle,
294                                                   (uint8_t *)shellContextHandle->printBuffer, (uint32_t)*indicator);
295             }
296 
297             shellContextHandle->printLength += (uint32_t)*indicator;
298             *indicator = 0;
299         }
300 
301         shellContextHandle->printBuffer[*indicator] = val;
302         (*indicator)++;
303     }
304 }
305 
SHELL_Sprintf(void * buffer,const char * formatString,va_list ap)306 static int SHELL_Sprintf(void *buffer, const char *formatString, va_list ap)
307 {
308     shell_context_handle_t *shellContextHandle;
309     uint32_t length;
310     shellContextHandle = (shell_context_handle_t *)buffer;
311 
312     length = (uint32_t)StrFormatPrintf(formatString, ap, (char *)buffer, SHELL_WriteBuffer);
313     shellContextHandle->printLength += length;
314     return (int32_t)length;
315 }
316 
SHELL_hisOperation(uint8_t ch,shell_context_handle_t * shellContextHandle)317 static void SHELL_hisOperation(uint8_t ch, shell_context_handle_t *shellContextHandle)
318 {
319     switch ((char)ch)
320     {
321         /* History operation here */
322         case 'A': /* Up key */
323             SHELL_GetHistoryCommand(shellContextHandle, (uint8_t)shellContextHandle->hist_current);
324             if (shellContextHandle->hist_current < (shellContextHandle->hist_count - 1U))
325             {
326                 shellContextHandle->hist_current++;
327             }
328             break;
329         case 'B': /* Down key */
330             SHELL_GetHistoryCommand(shellContextHandle, (uint8_t)shellContextHandle->hist_current);
331             if (shellContextHandle->hist_current > 0U)
332             {
333                 shellContextHandle->hist_current--;
334             }
335             break;
336         case 'D': /* Left key */
337             if ((bool)shellContextHandle->c_pos)
338             {
339                 (void)SHELL_WRITEX(shellContextHandle, "\b", 1);
340                 shellContextHandle->c_pos--;
341             }
342             break;
343         case 'C': /* Right key */
344             if (shellContextHandle->c_pos < shellContextHandle->l_pos)
345             {
346                 (void)SHELL_WRITEX(shellContextHandle, &shellContextHandle->line[shellContextHandle->c_pos], 1);
347                 shellContextHandle->c_pos++;
348             }
349             break;
350         default:
351             /* MISRA C-2012 Rule 16.4 */
352             break;
353     }
354 }
355 
SHELL_SerialManagerHandle(shell_context_handle_t * shellContextHandle)356 static void SHELL_SerialManagerHandle(shell_context_handle_t *shellContextHandle)
357 {
358     if (shellContextHandle->serialReadHandle != NULL)
359     {
360         (void)SerialManager_CloseReadHandle(shellContextHandle->serialReadHandle);
361         shellContextHandle->serialReadHandle = NULL;
362     }
363     if (shellContextHandle->serialWriteHandle != NULL)
364     {
365         (void)SerialManager_CloseWriteHandle(shellContextHandle->serialWriteHandle);
366         shellContextHandle->serialWriteHandle = NULL;
367     }
368 }
369 
370 #if SHELL_AUTO_COMPLETE
371 /* Move the cursor to the beginning of line */
SHELL_MoveCursorToBeginningLine(shell_context_handle_t * shellContextHandle)372 static void SHELL_MoveCursorToBeginningLine(shell_context_handle_t *shellContextHandle)
373 {
374     uint32_t i;
375     for (i = 0; i < (uint32_t)shellContextHandle->c_pos; i++)
376     {
377         (void)SHELL_WRITEX(shellContextHandle, "\b", 1);
378     }
379     /* Do auto complete */
380     SHELL_AutoComplete(shellContextHandle);
381     /* Move position to end */
382     shellContextHandle->l_pos = (uint8_t)strlen(shellContextHandle->line);
383     shellContextHandle->c_pos = shellContextHandle->l_pos;
384 }
385 #endif
386 
387 /* There must be at last one char */
SHELL_HandleBackspaceKey(shell_context_handle_t * shellContextHandle)388 static void SHELL_HandleBackspaceKey(shell_context_handle_t *shellContextHandle)
389 {
390     shellContextHandle->l_pos--;
391     shellContextHandle->c_pos--;
392 
393     if (shellContextHandle->l_pos > shellContextHandle->c_pos)
394     {
395         (void)memmove(&shellContextHandle->line[shellContextHandle->c_pos],
396                       &shellContextHandle->line[shellContextHandle->c_pos + 1U],
397                       (uint32_t)shellContextHandle->l_pos - (uint32_t)shellContextHandle->c_pos);
398         shellContextHandle->line[shellContextHandle->l_pos] = '\0';
399         (void)SHELL_WRITEX(shellContextHandle, "\b", 1);
400         (void)SHELL_WRITEX(shellContextHandle, &shellContextHandle->line[shellContextHandle->c_pos],
401                            strlen(&shellContextHandle->line[shellContextHandle->c_pos]));
402         (void)SHELL_WRITEX(shellContextHandle, "  \b", 3);
403 
404         /* Reset position */
405         uint32_t i;
406         for (i = (uint32_t)shellContextHandle->c_pos; i <= (uint32_t)shellContextHandle->l_pos; i++)
407         {
408             (void)SHELL_WRITEX(shellContextHandle, "\b", 1);
409         }
410     }
411     else /* Normal backspace operation */
412     {
413         (void)SHELL_WRITEX(shellContextHandle, "\b \b", 3);
414         shellContextHandle->line[shellContextHandle->l_pos] = '\0';
415     }
416 }
417 /* Normal character */
SHELL_HandleNormalChar(shell_context_handle_t * shellContextHandle,uint8_t ch)418 static void SHELL_HandleNormalChar(shell_context_handle_t *shellContextHandle, uint8_t ch)
419 {
420     if (shellContextHandle->c_pos < shellContextHandle->l_pos)
421     {
422         uint32_t i;
423         (void)memmove(&shellContextHandle->line[shellContextHandle->c_pos + 1U],
424                       &shellContextHandle->line[shellContextHandle->c_pos],
425                       (uint32_t)shellContextHandle->l_pos - (uint32_t)shellContextHandle->c_pos);
426         shellContextHandle->line[shellContextHandle->c_pos] = (char)ch;
427         (void)SHELL_WRITEX(shellContextHandle, &shellContextHandle->line[shellContextHandle->c_pos],
428                            strlen(&shellContextHandle->line[shellContextHandle->c_pos]));
429 
430         for (i = (uint32_t)shellContextHandle->c_pos; i < (uint32_t)shellContextHandle->l_pos; i++)
431         {
432             (void)SHELL_WRITEX(shellContextHandle, "\b", 1);
433         }
434     }
435     else
436     {
437         shellContextHandle->line[shellContextHandle->l_pos] = (char)ch;
438         (void)SHELL_WRITEX(shellContextHandle, &shellContextHandle->line[shellContextHandle->l_pos], 1);
439     }
440 }
441 
442 /* Case of Input too long */
SHELL_HandleInputTooLong(shell_context_handle_t * shellContextHandle)443 static void SHELL_HandleInputTooLong(shell_context_handle_t *shellContextHandle)
444 {
445     if (shellContextHandle->l_pos >= (SHELL_BUFFER_SIZE - 1U))
446     {
447         shellContextHandle->l_pos = 0U;
448     }
449 }
450 
451 #if (defined(SHELL_NON_BLOCKING_MODE) && (SHELL_NON_BLOCKING_MODE > 0U))
SHELL_Task(void * param)452 SHELL_STATIC void SHELL_Task(void *param)
453 #else
454 void SHELL_Task(shell_handle_t shellHandle)
455 #endif
456 {
457 #if (defined(SHELL_NON_BLOCKING_MODE) && (SHELL_NON_BLOCKING_MODE > 0U))
458     shell_context_handle_t *shellContextHandle = (shell_context_handle_t *)param;
459 #else
460     shell_context_handle_t *shellContextHandle = (shell_context_handle_t *)shellHandle;
461 #endif
462     uint8_t ch;
463 
464     if (NULL != shellContextHandle)
465     {
466         uint32_t osaCurrentSr = 0U;
467 
468         osaCurrentSr                         = DisableGlobalIRQ();
469         shellContextHandle->notificationPost = 0U;
470         if (shellContextHandle->taskBusy > 0U)
471         {
472             EnableGlobalIRQ(osaCurrentSr);
473             return;
474         }
475         shellContextHandle->taskBusy = 1U;
476         EnableGlobalIRQ(osaCurrentSr);
477 #if (defined(SHELL_NON_BLOCKING_MODE) && (SHELL_NON_BLOCKING_MODE > 0U))
478 
479 #if defined(OSA_USED)
480 
481 #if (defined(SHELL_USE_COMMON_TASK) && (SHELL_USE_COMMON_TASK > 0U))
482 #else
483         osa_event_flags_t ev = 0;
484 
485         do
486         {
487             if (KOSA_StatusSuccess == OSA_EventWait((osa_event_handle_t)shellContextHandle->event, osaEventFlagsAll_c,
488                                                     0U, osaWaitForever_c, &ev))
489             {
490                 if (0U != (ev & SHELL_EVENT_DATA_ARRIVED))
491 #endif
492 
493 #endif
494 
495 #endif
496         {
497             shellContextHandle->notificationPost = 0U;
498             do
499             {
500                 if ((bool)shellContextHandle->exit)
501                 {
502                     SHELL_SerialManagerHandle(shellContextHandle);
503                     break;
504                 }
505                 if (kStatus_SHELL_Success != (shell_status_t)SHELL_GetChar(shellContextHandle, &ch))
506                 {
507                     /* If error occurred when getting a char, exit the task and waiting the new data arriving. */
508                     break;
509                 }
510 
511                 /* Special key */
512                 if (ch == KEY_ESC)
513                 {
514                     shellContextHandle->stat = kSHELL_Special;
515                     continue;
516                 }
517                 else if (shellContextHandle->stat == kSHELL_Special)
518                 {
519                     /* Function key */
520                     if ((char)ch == '[')
521                     {
522                         shellContextHandle->stat = kSHELL_Function;
523                         continue;
524                     }
525                     shellContextHandle->stat = kSHELL_Normal;
526                 }
527                 else if (shellContextHandle->stat == kSHELL_Function)
528                 {
529                     shellContextHandle->stat = kSHELL_Normal;
530                     SHELL_hisOperation(ch, shellContextHandle);
531                     continue;
532                 }
533                 /* Handle tab key */
534                 else if ((char)ch == '\t')
535                 {
536 #if SHELL_AUTO_COMPLETE
537 
538                     SHELL_MoveCursorToBeginningLine(shellContextHandle);
539 #endif
540                     continue;
541                 }
542                 /* Handle backspace key */
543                 else if ((ch == KET_DEL) || ((char)ch == '\b'))
544                 {
545                     /* There must be at last one char */
546                     if ((shellContextHandle->c_pos == 0U) || (shellContextHandle->l_pos == 0U))
547                     {
548                         continue;
549                     }
550                     SHELL_HandleBackspaceKey(shellContextHandle);
551                     continue;
552                 }
553                 else
554                 {
555                     /* MISRA C-2012 Rule 15.7 */
556                 }
557 
558                 /* Input too long */
559                 SHELL_HandleInputTooLong(shellContextHandle);
560 
561                 /* Handle end of line, break */
562                 if (((char)ch == '\r') || ((char)ch == '\n'))
563                 {
564                     static char endoflinechar = '\0';
565 
566                     if (((uint8_t)endoflinechar != 0U) && ((uint8_t)endoflinechar != ch))
567                     {
568                         continue;
569                     }
570                     else
571                     {
572                         endoflinechar = (char)ch;
573                         /* Print new line. */
574                         (void)SHELL_WRITEX(shellContextHandle, "\r\n", 2U);
575                         /* If command line is not NULL, will start process it. */
576                         if (0U != strlen(shellContextHandle->line))
577                         {
578                             SHELL_ProcessCommand(shellContextHandle, shellContextHandle->line);
579                         }
580                         /* Print prompt. */
581                         (void)SHELL_WRITEX(shellContextHandle, shellContextHandle->prompt,
582                                            strlen(shellContextHandle->prompt));
583                         /* Reset all params */
584                         shellContextHandle->c_pos = shellContextHandle->l_pos = 0;
585                         shellContextHandle->hist_current                      = 0;
586                         (void)memset(shellContextHandle->line, 0, sizeof(shellContextHandle->line));
587                         continue;
588                     }
589                 }
590 
591                 /* Normal character */
592                 SHELL_HandleNormalChar(shellContextHandle, ch);
593 
594                 ch = 0;
595                 shellContextHandle->l_pos++;
596                 shellContextHandle->c_pos++;
597             } while (0U == shellContextHandle->exit);
598         }
599 #if (defined(SHELL_NON_BLOCKING_MODE) && (SHELL_NON_BLOCKING_MODE > 0U))
600 
601 #if defined(OSA_USED)
602 
603 #if (defined(SHELL_USE_COMMON_TASK) && (SHELL_USE_COMMON_TASK > 0U))
604 #else
605             }
606         } while (1U == gUseRtos_c); /* USE_RTOS = 0 for BareMetal and 1 for OS */
607 #endif
608 
609 #endif
610 
611 #endif
612         osaCurrentSr                 = DisableGlobalIRQ();
613         shellContextHandle->taskBusy = 0U;
614         EnableGlobalIRQ(osaCurrentSr);
615     }
616 }
617 
SHELL_HelpCommand(shell_handle_t shellHandle,int32_t argc,char ** argv)618 static shell_status_t SHELL_HelpCommand(shell_handle_t shellHandle, int32_t argc, char **argv)
619 {
620     shell_context_handle_t *shellContextHandle = (shell_context_handle_t *)shellHandle;
621     shell_command_t *shellCommandContextHandle;
622     list_element_handle_t p = LIST_GetHead(&shellContextHandle->commandContextListHead);
623 
624     while (p != NULL)
625     {
626         shellCommandContextHandle = SHEEL_COMMAND_POINTER(p);
627         if ((shellCommandContextHandle->pcHelpString != NULL) && (bool)strlen(shellCommandContextHandle->pcHelpString))
628         {
629             (void)SHELL_WRITEX(shellContextHandle, shellCommandContextHandle->pcHelpString,
630                                strlen(shellCommandContextHandle->pcHelpString));
631         }
632 
633         p = LIST_GetNext(p);
634     }
635     return kStatus_SHELL_Success;
636 }
637 
SHELL_ExitCommand(shell_handle_t shellHandle,int32_t argc,char ** argv)638 static shell_status_t SHELL_ExitCommand(shell_handle_t shellHandle, int32_t argc, char **argv)
639 {
640     shell_context_handle_t *shellContextHandle = (shell_context_handle_t *)shellHandle;
641     /* Skip warning */
642     (void)SHELL_WRITEX(shellContextHandle, "\r\nSHELL exited\r\n", strlen("\r\nSHELL exited\r\n"));
643     shellContextHandle->exit = (uint8_t) true;
644     return kStatus_SHELL_Success;
645 }
646 
SHELL_ProcessCommand(shell_context_handle_t * shellContextHandle,const char * cmd)647 static void SHELL_ProcessCommand(shell_context_handle_t *shellContextHandle, const char *cmd)
648 {
649     shell_command_t *tmpCommand = NULL;
650     const char *tmpCommandString;
651     int32_t argc;
652     char *argv[SHELL_BUFFER_SIZE] = {0};
653     list_element_handle_t p;
654     uint8_t flag = 1;
655     uint8_t tmpCommandLen;
656     uint8_t tmpLen;
657     uint8_t i = 0;
658 
659     tmpLen = (uint8_t)strlen(cmd);
660     if (tmpLen >= SHELL_BUFFER_SIZE - 1U)
661     {
662         (void)SHELL_Printf(shellContextHandle,
663                            "Command line length should not more than SHELL_BUFFER_SIZE, please input command less "
664                            "(SHELL_BUFFER_SIZE - 1) characters again!\r\n");
665         return;
666     }
667     else
668     {
669         argc = SHELL_ParseLine(cmd, tmpLen, argv);
670     }
671 
672     if ((argc > 0))
673     {
674         p = LIST_GetHead(&shellContextHandle->commandContextListHead);
675         while (p != NULL)
676         {
677             tmpCommand       = SHEEL_COMMAND_POINTER(p);
678             tmpCommandString = tmpCommand->pcCommand;
679             tmpCommandLen    = (uint8_t)strlen(tmpCommandString);
680             /* Compare with space or end of string */
681             if ((cmd[tmpCommandLen] == ' ') || (cmd[tmpCommandLen] == (char)0x00))
682             {
683                 if (SHELL_StringCompare(tmpCommandString, argv[0], (int32_t)tmpCommandLen) == 0)
684                 {
685                     /* support commands with optional number of parameters */
686                     if (tmpCommand->cExpectedNumberOfParameters == (uint8_t)SHELL_IGNORE_PARAMETER_COUNT)
687                     {
688                         flag = 0;
689                     }
690                     else if ((tmpCommand->cExpectedNumberOfParameters == 0U) && (argc == 1))
691                     {
692                         flag = 0;
693                     }
694                     else if (tmpCommand->cExpectedNumberOfParameters > 0U)
695                     {
696                         if ((argc - 1) == (int32_t)tmpCommand->cExpectedNumberOfParameters)
697                         {
698                             flag = 0;
699                         }
700                     }
701                     else
702                     {
703                         flag = 1;
704                     }
705                     break;
706                 }
707             }
708             p = LIST_GetNext(p);
709         }
710         if (NULL == p)
711         {
712             tmpCommand = NULL;
713         }
714     }
715 
716     if ((tmpCommand != NULL) && (flag == 1U))
717     {
718         (void)SHELL_Write(
719             shellContextHandle,
720             "\r\nIncorrect command parameter(s).  Enter \"help\" to view a list of available commands.\r\n\r\n",
721             strlen(
722                 "\r\nIncorrect command parameter(s).  Enter \"help\" to view a list of available commands.\r\n\r\n"));
723     }
724     else if (tmpCommand != NULL)
725     {
726         tmpLen = (uint8_t)strlen(cmd);
727         /* Compare with last command. Push back to history buffer if different */
728         if (tmpLen != (uint8_t)SHELL_StringCompare(cmd, shellContextHandle->hist_buf[0], (int32_t)strlen(cmd)))
729         {
730             for (i = SHELL_HISTORY_COUNT - 1U; i > 0U; i--)
731             {
732                 (void)memset(shellContextHandle->hist_buf[i], (int)'\0', SHELL_BUFFER_SIZE);
733                 tmpLen = (uint8_t)strlen(shellContextHandle->hist_buf[i - 1U]);
734                 (void)memcpy(shellContextHandle->hist_buf[i], shellContextHandle->hist_buf[i - 1U], tmpLen);
735             }
736             (void)memset(shellContextHandle->hist_buf[0], (int)'\0', SHELL_BUFFER_SIZE);
737             tmpLen = (uint8_t)strlen(cmd);
738             (void)memcpy(shellContextHandle->hist_buf[0], cmd, tmpLen);
739             if (shellContextHandle->hist_count < SHELL_HISTORY_COUNT)
740             {
741                 shellContextHandle->hist_count++;
742             }
743         }
744         if (kStatus_SHELL_RetUsage == tmpCommand->pFuncCallBack(shellContextHandle, argc, argv))
745         {
746             if (NULL != tmpCommand->pcHelpString)
747             {
748                 (void)SHELL_WRITEX(shellContextHandle, tmpCommand->pcHelpString, strlen(tmpCommand->pcHelpString));
749             }
750             else
751             {
752                 (void)SHELL_HelpCommand(shellContextHandle, 0, NULL);
753             }
754         }
755     }
756     else
757     {
758         (void)SHELL_Write(
759             shellContextHandle,
760             "\r\nCommand not recognized.  Enter 'help' to view a list of available commands.\r\n\r\n",
761             strlen("\r\nCommand not recognized.  Enter 'help' to view a list of available commands.\r\n\r\n"));
762     }
763 }
764 
SHELL_GetHistoryCommand(shell_context_handle_t * shellContextHandle,uint8_t hist_pos)765 static void SHELL_GetHistoryCommand(shell_context_handle_t *shellContextHandle, uint8_t hist_pos)
766 {
767     uint32_t i;
768     uint32_t tmp;
769 
770     if (shellContextHandle->hist_buf[0][0] == '\0')
771     {
772         shellContextHandle->hist_current = 0;
773         return;
774     }
775 
776 #if 0 /*hist_pos is passed from hist_current. And hist_current is only changed in case 'A'/'B',as hist_count is 3 \
777          most, it can't be more than 3  */
778     if (hist_pos >= SHELL_HISTORY_COUNT)
779     {
780         hist_pos = SHELL_HISTORY_COUNT - 1U;
781     }
782 #endif
783 
784     tmp = strlen(shellContextHandle->line);
785     /* Clear current if have */
786     if (tmp > 0U)
787     {
788         (void)memset(shellContextHandle->line, (int)'\0', tmp);
789         for (i = 0U; i < tmp; i++)
790         {
791             (void)SHELL_WRITEX(shellContextHandle, "\b \b", 3);
792         }
793     }
794 
795     shellContextHandle->l_pos = (uint8_t)strlen(shellContextHandle->hist_buf[hist_pos]);
796     shellContextHandle->c_pos = shellContextHandle->l_pos;
797     (void)memcpy(shellContextHandle->line, shellContextHandle->hist_buf[hist_pos], shellContextHandle->l_pos);
798     (void)SHELL_WRITEX(shellContextHandle, shellContextHandle->hist_buf[hist_pos],
799                        strlen(shellContextHandle->hist_buf[hist_pos]));
800 }
801 
SHELL_AutoComplete(shell_context_handle_t * shellContextHandle)802 static void SHELL_AutoComplete(shell_context_handle_t *shellContextHandle)
803 {
804     int32_t minLen;
805     list_element_handle_t p;
806     shell_command_t *tmpCommand = NULL;
807     const char *namePtr;
808     const char *cmdName;
809 
810     minLen  = (int32_t)SHELL_BUFFER_SIZE;
811     namePtr = NULL;
812 
813     /* Empty tab, list all commands */
814     if (shellContextHandle->line[0] == '\0')
815     {
816         (void)SHELL_HelpCommand(shellContextHandle, 0, NULL);
817         return;
818     }
819 
820     (void)SHELL_WRITEX(shellContextHandle, "\r\n", 2);
821 
822     /* Do auto complete */
823     p = LIST_GetHead(&shellContextHandle->commandContextListHead);
824     while (p != NULL)
825     {
826         tmpCommand = SHEEL_COMMAND_POINTER(p);
827         cmdName    = tmpCommand->pcCommand;
828         if (SHELL_StringCompare(shellContextHandle->line, cmdName, (int32_t)strlen(shellContextHandle->line)) == 0)
829         {
830             /* Show possible matches */
831             (void)SHELL_Printf(shellContextHandle, "%s    ", cmdName);
832             if (minLen > ((int32_t)strlen(cmdName)))
833             {
834                 namePtr = cmdName;
835                 minLen  = (int32_t)strlen(namePtr);
836             }
837         }
838         p = LIST_GetNext(p);
839     }
840     /* Auto complete string */
841     if (namePtr != NULL)
842     {
843         (void)memcpy(shellContextHandle->line, namePtr, (uint32_t)minLen);
844     }
845     SHELL_PrintPrompt(shellContextHandle);
846     (void)SHELL_WRITEX(shellContextHandle, shellContextHandle->line, strlen(shellContextHandle->line));
847     return;
848 }
849 
SHELL_StringCompare(const char * str1,const char * str2,int32_t count)850 static int32_t SHELL_StringCompare(const char *str1, const char *str2, int32_t count)
851 {
852     while ((bool)(count--))
853     {
854         if (*str1++ != *str2++)
855         {
856             return (int32_t)(*(str1 - 1) - *(str2 - 1));
857         }
858     }
859     return 0;
860 }
861 
SHELL_ParseLine(const char * cmd,uint32_t len,char * argv[])862 static int32_t SHELL_ParseLine(const char *cmd, uint32_t len, char *argv[])
863 {
864     uint32_t argc;
865     char *p;
866     uint32_t position;
867 
868     /* Init params */
869     (void)memset(s_paramBuffer, (int)'\0', len + 1U);
870     (void)memcpy(s_paramBuffer, cmd, len);
871 
872     p        = s_paramBuffer;
873     position = 0;
874     argc     = 0;
875 
876     while (position < len)
877     {
878         /* Skip all blanks */
879         while ((position < len) && ((char)(*p) == ' '))
880         {
881             *p = '\0';
882             p++;
883             position++;
884         }
885 
886         if (position >= len)
887         {
888             break;
889         }
890 
891         /* Process begin of a string */
892         if (*p == '"')
893         {
894             p++;
895             position++;
896             argv[argc] = p;
897             argc++;
898             /* Skip this string */
899             while ((*p != '"') && (position < len))
900             {
901                 p++;
902                 position++;
903             }
904             /* Skip '"' */
905             *p = '\0';
906             p++;
907             position++;
908         }
909         else /* Normal char */
910         {
911             argv[argc] = p;
912             argc++;
913             while (((char)*p != ' ') && (position < len))
914             {
915                 p++;
916                 position++;
917             }
918         }
919     }
920     return (int32_t)argc;
921 }
922 
SHELL_GetChar(shell_context_handle_t * shellContextHandle,uint8_t * ch)923 static shell_status_t SHELL_GetChar(shell_context_handle_t *shellContextHandle, uint8_t *ch)
924 {
925     shell_status_t status;
926 
927 #if (!defined(SDK_DEBUGCONSOLE_UART) && (defined(SDK_DEBUGCONSOLE) && (SDK_DEBUGCONSOLE != 1)))
928     if (NULL == shellContextHandle->serialHandle)
929     {
930         int ret;
931         ret = getchar();
932         if (ret > 0)
933         {
934             *ch    = (uint8_t)ret;
935             status = kStatus_SHELL_Success;
936         }
937         else
938         {
939             status = kStatus_SHELL_Error;
940         }
941     }
942     else
943 #endif
944     {
945 #if (defined(SHELL_NON_BLOCKING_MODE) && (SHELL_NON_BLOCKING_MODE > 0U))
946         uint32_t length = 0;
947 
948         (void)SerialManager_TryRead(shellContextHandle->serialReadHandle, ch, 1, &length);
949 
950         if (length > 0U)
951         {
952             status = kStatus_SHELL_Success;
953         }
954         else
955         {
956             status = kStatus_SHELL_Error;
957         }
958 #else
959         status = (shell_status_t)SerialManager_ReadBlocking(shellContextHandle->serialReadHandle, ch, 1);
960 #endif
961     }
962 
963     return status;
964 }
965 
SHELL_Init(shell_handle_t shellHandle,serial_handle_t serialHandle,char * prompt)966 shell_status_t SHELL_Init(shell_handle_t shellHandle, serial_handle_t serialHandle, char *prompt)
967 {
968     shell_context_handle_t *shellContextHandle;
969     serial_manager_status_t status = kStatus_SerialManager_Error;
970     (void)status;
971 
972     assert(shellHandle);
973 #if !(!defined(SDK_DEBUGCONSOLE_UART) && (defined(SDK_DEBUGCONSOLE) && (SDK_DEBUGCONSOLE != 1)))
974     assert(serialHandle);
975 #endif
976     assert(prompt);
977     assert(SHELL_HANDLE_SIZE >= sizeof(shell_context_handle_t));
978 
979     shellContextHandle = (shell_context_handle_t *)shellHandle;
980 
981     /* memory set for shellHandle */
982     (void)memset(shellHandle, 0, SHELL_HANDLE_SIZE);
983 
984 #if (!defined(SDK_DEBUGCONSOLE_UART) && (defined(SDK_DEBUGCONSOLE) && (SDK_DEBUGCONSOLE != 1)))
985     if (NULL == serialHandle)
986     {
987     }
988     else
989 #endif
990     {
991 #if (defined(SHELL_NON_BLOCKING_MODE) && (SHELL_NON_BLOCKING_MODE > 0U))
992 
993 #if defined(OSA_USED)
994 
995 #if (defined(SHELL_USE_COMMON_TASK) && (SHELL_USE_COMMON_TASK > 0U))
996         (void)COMMON_TASK_init();
997 #else
998         if (KOSA_StatusSuccess != OSA_EventCreate((osa_event_handle_t)shellContextHandle->event, 1U))
999         {
1000             return kStatus_SHELL_Error;
1001         }
1002 
1003         if (KOSA_StatusSuccess !=
1004             OSA_TaskCreate((osa_task_handle_t)shellContextHandle->taskId, OSA_TASK(SHELL_Task), shellContextHandle))
1005         {
1006             return kStatus_SHELL_Error;
1007         }
1008 #endif
1009 
1010 #endif
1011 
1012 #endif
1013     }
1014 
1015     shellContextHandle->prompt       = prompt;
1016     shellContextHandle->serialHandle = serialHandle;
1017 
1018 #if (!defined(SDK_DEBUGCONSOLE_UART) && (defined(SDK_DEBUGCONSOLE) && (SDK_DEBUGCONSOLE != 1)))
1019     if (NULL == serialHandle)
1020     {
1021     }
1022     else
1023 #endif
1024     {
1025         shellContextHandle->serialWriteHandle = (serial_write_handle_t)&shellContextHandle->serialWriteHandleBuffer[0];
1026         status = SerialManager_OpenWriteHandle(shellContextHandle->serialHandle, shellContextHandle->serialWriteHandle);
1027         assert(kStatus_SerialManager_Success == status);
1028 
1029         shellContextHandle->serialReadHandle = (serial_read_handle_t)&shellContextHandle->serialReadHandleBuffer[0];
1030         status = SerialManager_OpenReadHandle(shellContextHandle->serialHandle, shellContextHandle->serialReadHandle);
1031         assert(kStatus_SerialManager_Success == status);
1032 
1033 #if (defined(SHELL_NON_BLOCKING_MODE) && (SHELL_NON_BLOCKING_MODE > 0U))
1034         status = SerialManager_InstallRxCallback(shellContextHandle->serialReadHandle, SHELL_SerialManagerRxCallback,
1035                                                  shellContextHandle);
1036         assert(kStatus_SerialManager_Success == status);
1037 #endif
1038         (void)status;
1039     }
1040 
1041     (void)SHELL_RegisterCommand(shellContextHandle, SHELL_COMMAND(help));
1042     (void)SHELL_RegisterCommand(shellContextHandle, SHELL_COMMAND(exit));
1043     SHELL_MUTEX_CREATE();
1044 #if (defined(SHELL_PRINT_COPYRIGHT) && (SHELL_PRINT_COPYRIGHT > 0U))
1045     (void)SHELL_Write(shellContextHandle, "\r\nCopyright  2024  NXP\r\n", strlen("\r\nCopyright  2024  NXP\r\n"));
1046 #endif
1047     SHELL_PrintPrompt(shellContextHandle);
1048 
1049     return kStatus_SHELL_Success;
1050 }
1051 
SHELL_RegisterCommand(shell_handle_t shellHandle,shell_command_t * shellCommand)1052 shell_status_t SHELL_RegisterCommand(shell_handle_t shellHandle, shell_command_t *shellCommand)
1053 {
1054     shell_context_handle_t *shellContextHandle = (shell_context_handle_t *)shellHandle;
1055     assert(shellHandle);
1056     assert(shellCommand);
1057 
1058     /* memory set for shellHandle */
1059     (void)memset(&shellCommand->link, 0, sizeof(shellCommand->link));
1060 
1061     (void)LIST_AddTail(&shellContextHandle->commandContextListHead, &shellCommand->link);
1062 
1063     return kStatus_SHELL_Success;
1064 }
1065 
SHELL_UnregisterCommand(shell_command_t * shellCommand)1066 shell_status_t SHELL_UnregisterCommand(shell_command_t *shellCommand)
1067 {
1068     assert(shellCommand);
1069 
1070     (void)LIST_RemoveElement(&shellCommand->link);
1071 
1072     /* memory set for shellHandle */
1073     (void)memset(&shellCommand->link, 0, sizeof(shellCommand->link));
1074 
1075     return kStatus_SHELL_Success;
1076 }
1077 
SHELL_Write(shell_handle_t shellHandle,const char * buffer,uint32_t length)1078 shell_status_t SHELL_Write(shell_handle_t shellHandle, const char *buffer, uint32_t length)
1079 {
1080     shell_context_handle_t *shellContextHandle;
1081     uint32_t primask;
1082     shell_status_t status;
1083 
1084     assert(shellHandle);
1085     assert(buffer);
1086 
1087     if (!(bool)length)
1088     {
1089         return kStatus_SHELL_Success;
1090     }
1091 
1092     shellContextHandle = (shell_context_handle_t *)shellHandle;
1093 
1094     primask = DisableGlobalIRQ();
1095     if ((bool)shellContextHandle->printBusy)
1096     {
1097         EnableGlobalIRQ(primask);
1098         return kStatus_SHELL_Error;
1099     }
1100     shellContextHandle->printBusy = 1U;
1101     EnableGlobalIRQ(primask);
1102 #if (!defined(SDK_DEBUGCONSOLE_UART) && (defined(SDK_DEBUGCONSOLE) && (SDK_DEBUGCONSOLE != 1)))
1103     if (NULL == shellContextHandle->serialHandle)
1104     {
1105         status = kStatus_SHELL_Success;
1106         for (uint32_t index = 0; index < length; index++)
1107         {
1108             (void)putchar(buffer[index]);
1109         }
1110     }
1111     else
1112 #endif
1113     {
1114         status = (shell_status_t)SerialManager_WriteBlocking(shellContextHandle->serialWriteHandle, (uint8_t *)buffer,
1115                                                              length);
1116     }
1117 
1118     shellContextHandle->printBusy = 0U;
1119 
1120     return status;
1121 }
1122 
SHELL_Printf(shell_handle_t shellHandle,const char * formatString,...)1123 int SHELL_Printf(shell_handle_t shellHandle, const char *formatString, ...)
1124 {
1125     shell_context_handle_t *shellContextHandle;
1126     uint32_t length;
1127     uint32_t primask;
1128     va_list ap;
1129 
1130     assert(shellHandle);
1131     assert(formatString);
1132 
1133     shellContextHandle = (shell_context_handle_t *)shellHandle;
1134 
1135     primask = DisableGlobalIRQ();
1136     if ((bool)shellContextHandle->printBusy)
1137     {
1138         EnableGlobalIRQ(primask);
1139         return -1;
1140     }
1141     shellContextHandle->printBusy = 1U;
1142     EnableGlobalIRQ(primask);
1143 
1144     va_start(ap, formatString);
1145 
1146     shellContextHandle->printLength = 0U;
1147     length                          = (uint32_t)SHELL_Sprintf(shellHandle, formatString, ap);
1148 #if (!defined(SDK_DEBUGCONSOLE_UART) && (defined(SDK_DEBUGCONSOLE) && (SDK_DEBUGCONSOLE != 1)))
1149     if (NULL == shellContextHandle->serialHandle)
1150     {
1151         for (uint32_t index = 0; index < length; index++)
1152         {
1153             (void)putchar(shellContextHandle->printBuffer[index]);
1154         }
1155     }
1156     else
1157 #endif
1158     {
1159         (void)SerialManager_WriteBlocking(shellContextHandle->serialWriteHandle,
1160                                           (uint8_t *)shellContextHandle->printBuffer, length);
1161     }
1162     va_end(ap);
1163 
1164     shellContextHandle->printBusy = 0U;
1165     return (int32_t)shellContextHandle->printLength;
1166 }
1167 
SHELL_WriteSynchronization(shell_handle_t shellHandle,const char * buffer,uint32_t length)1168 shell_status_t SHELL_WriteSynchronization(shell_handle_t shellHandle, const char *buffer, uint32_t length)
1169 {
1170     shell_status_t status;
1171 
1172     assert(SHELL_checkRunningInIsr() == false);
1173 
1174     SHELL_ENTER_CRITICAL();
1175     status = SHELL_Write(shellHandle, buffer, length);
1176 
1177     SHELL_EXIT_CRITICAL();
1178 
1179     return status;
1180 }
1181 
SHELL_PrintfSynchronization(shell_handle_t shellHandle,const char * formatString,...)1182 int SHELL_PrintfSynchronization(shell_handle_t shellHandle, const char *formatString, ...)
1183 {
1184     shell_status_t status;
1185     shell_context_handle_t *shellContextHandle;
1186     va_list ap;
1187     uint32_t length;
1188 
1189     assert(SHELL_checkRunningInIsr() == false);
1190 
1191     shellContextHandle = (shell_context_handle_t *)shellHandle;
1192 
1193     SHELL_ENTER_CRITICAL();
1194     va_start(ap, formatString);
1195     length = (uint32_t)SHELL_Sprintf(shellHandle, formatString, ap);
1196 
1197     status = SHELL_Write(shellHandle, (const char *)shellContextHandle->printBuffer, length);
1198     va_end(ap);
1199     SHELL_EXIT_CRITICAL();
1200 
1201     return (status == kStatus_SHELL_Success) ? (int)length : 0;
1202 }
SHELL_ChangePrompt(shell_handle_t shellHandle,char * prompt)1203 void SHELL_ChangePrompt(shell_handle_t shellHandle, char *prompt)
1204 {
1205     shell_context_handle_t *shellContextHandle;
1206     assert(shellHandle);
1207     assert(prompt);
1208 
1209     shellContextHandle = (shell_context_handle_t *)shellHandle;
1210 
1211     shellContextHandle->prompt = prompt;
1212     SHELL_PrintPrompt(shellContextHandle);
1213 }
1214 
SHELL_PrintPrompt(shell_handle_t shellHandle)1215 void SHELL_PrintPrompt(shell_handle_t shellHandle)
1216 {
1217     shell_context_handle_t *shellContextHandle;
1218     assert(shellHandle);
1219 
1220     shellContextHandle = (shell_context_handle_t *)shellHandle;
1221 
1222     (void)SHELL_Write(shellContextHandle, "\r\n", 2U);
1223     (void)SHELL_Write(shellContextHandle, shellContextHandle->prompt, strlen(shellContextHandle->prompt));
1224 }
1225