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