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 /* 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 #if (defined(SHELL_NON_BLOCKING_MODE) && (SHELL_NON_BLOCKING_MODE > 0U))
SHELL_Task(void * param)356 SHELL_STATIC void SHELL_Task(void *param)
357 #else
358 void SHELL_Task(shell_handle_t shellHandle)
359 #endif
360 {
361 #if (defined(SHELL_NON_BLOCKING_MODE) && (SHELL_NON_BLOCKING_MODE > 0U))
362 shell_context_handle_t *shellContextHandle = (shell_context_handle_t *)param;
363 #else
364 shell_context_handle_t *shellContextHandle = (shell_context_handle_t *)shellHandle;
365 #endif
366 uint8_t ch;
367
368 if (NULL != shellContextHandle)
369 {
370 uint32_t osaCurrentSr = 0U;
371
372 osaCurrentSr = DisableGlobalIRQ();
373 shellContextHandle->notificationPost = 0U;
374 if (shellContextHandle->taskBusy > 0U)
375 {
376 EnableGlobalIRQ(osaCurrentSr);
377 return;
378 }
379 shellContextHandle->taskBusy = 1U;
380 EnableGlobalIRQ(osaCurrentSr);
381 #if (defined(SHELL_NON_BLOCKING_MODE) && (SHELL_NON_BLOCKING_MODE > 0U))
382
383 #if defined(OSA_USED)
384
385 #if (defined(SHELL_USE_COMMON_TASK) && (SHELL_USE_COMMON_TASK > 0U))
386 #else
387 osa_event_flags_t ev = 0;
388
389 do
390 {
391 if (KOSA_StatusSuccess == OSA_EventWait((osa_event_handle_t)shellContextHandle->event, osaEventFlagsAll_c,
392 0U, osaWaitForever_c, &ev))
393 {
394 if (0U != (ev & SHELL_EVENT_DATA_ARRIVED))
395 #endif
396
397 #endif
398
399 #endif
400 {
401 shellContextHandle->notificationPost = 0U;
402 do
403 {
404 if ((bool)shellContextHandle->exit)
405 {
406 if (shellContextHandle->serialReadHandle != NULL)
407 {
408 (void)SerialManager_CloseReadHandle(shellContextHandle->serialReadHandle);
409 shellContextHandle->serialReadHandle = NULL;
410 }
411 if (shellContextHandle->serialWriteHandle != NULL)
412 {
413 (void)SerialManager_CloseWriteHandle(shellContextHandle->serialWriteHandle);
414 shellContextHandle->serialWriteHandle = NULL;
415 }
416 break;
417 }
418 if (kStatus_SHELL_Success != (shell_status_t)SHELL_GetChar(shellContextHandle, &ch))
419 {
420 /* If error occurred when getting a char, exit the task and waiting the new data arriving. */
421 break;
422 }
423
424 /* Special key */
425 if (ch == KEY_ESC)
426 {
427 shellContextHandle->stat = kSHELL_Special;
428 continue;
429 }
430 else if (shellContextHandle->stat == kSHELL_Special)
431 {
432 /* Function key */
433 if ((char)ch == '[')
434 {
435 shellContextHandle->stat = kSHELL_Function;
436 continue;
437 }
438 shellContextHandle->stat = kSHELL_Normal;
439 }
440 else if (shellContextHandle->stat == kSHELL_Function)
441 {
442 shellContextHandle->stat = kSHELL_Normal;
443 SHELL_hisOperation(ch, shellContextHandle);
444 continue;
445 }
446 /* Handle tab key */
447 else if ((char)ch == '\t')
448 {
449 #if SHELL_AUTO_COMPLETE
450 /* Move the cursor to the beginning of line */
451 uint32_t i;
452 for (i = 0; i < (uint32_t)shellContextHandle->c_pos; i++)
453 {
454 (void)SHELL_WRITEX(shellContextHandle, "\b", 1);
455 }
456 /* Do auto complete */
457 SHELL_AutoComplete(shellContextHandle);
458 /* Move position to end */
459 shellContextHandle->l_pos = (uint8_t)strlen(shellContextHandle->line);
460 shellContextHandle->c_pos = shellContextHandle->l_pos;
461 #endif
462 continue;
463 }
464 /* Handle backspace key */
465 else if ((ch == KET_DEL) || ((char)ch == '\b'))
466 {
467 /* There must be at last one char */
468 if (shellContextHandle->c_pos == 0U)
469 {
470 continue;
471 }
472
473 shellContextHandle->l_pos--;
474 shellContextHandle->c_pos--;
475
476 if (shellContextHandle->l_pos > shellContextHandle->c_pos)
477 {
478 (void)memmove(&shellContextHandle->line[shellContextHandle->c_pos],
479 &shellContextHandle->line[shellContextHandle->c_pos + 1U],
480 (uint32_t)shellContextHandle->l_pos - (uint32_t)shellContextHandle->c_pos);
481 shellContextHandle->line[shellContextHandle->l_pos] = '\0';
482 (void)SHELL_WRITEX(shellContextHandle, "\b", 1);
483 (void)SHELL_WRITEX(shellContextHandle, &shellContextHandle->line[shellContextHandle->c_pos],
484 strlen(&shellContextHandle->line[shellContextHandle->c_pos]));
485 (void)SHELL_WRITEX(shellContextHandle, " \b", 3);
486
487 /* Reset position */
488 uint32_t i;
489 for (i = (uint32_t)shellContextHandle->c_pos; i <= (uint32_t)shellContextHandle->l_pos; i++)
490 {
491 (void)SHELL_WRITEX(shellContextHandle, "\b", 1);
492 }
493 }
494 else /* Normal backspace operation */
495 {
496 (void)SHELL_WRITEX(shellContextHandle, "\b \b", 3);
497 shellContextHandle->line[shellContextHandle->l_pos] = '\0';
498 }
499 continue;
500 }
501 else
502 {
503 /* MISRA C-2012 Rule 15.7 */
504 }
505
506 /* Input too long */
507 if (shellContextHandle->l_pos >= (SHELL_BUFFER_SIZE - 1U))
508 {
509 shellContextHandle->l_pos = 0U;
510 }
511
512 /* Handle end of line, break */
513 if (((char)ch == '\r') || ((char)ch == '\n'))
514 {
515 static char endoflinechar = '\0';
516
517 if (((uint8_t)endoflinechar != 0U) && ((uint8_t)endoflinechar != ch))
518 {
519 continue;
520 }
521 else
522 {
523 endoflinechar = (char)ch;
524 /* Print new line. */
525 (void)SHELL_WRITEX(shellContextHandle, "\r\n", 2U);
526 /* If command line is not NULL, will start process it. */
527 if (0U != strlen(shellContextHandle->line))
528 {
529 SHELL_ProcessCommand(shellContextHandle, shellContextHandle->line);
530 }
531 /* Print prompt. */
532 (void)SHELL_WRITEX(shellContextHandle, shellContextHandle->prompt,
533 strlen(shellContextHandle->prompt));
534 /* Reset all params */
535 shellContextHandle->c_pos = shellContextHandle->l_pos = 0;
536 shellContextHandle->hist_current = 0;
537 (void)memset(shellContextHandle->line, 0, sizeof(shellContextHandle->line));
538 continue;
539 }
540 }
541
542 /* Normal character */
543 if (shellContextHandle->c_pos < shellContextHandle->l_pos)
544 {
545 (void)memmove(&shellContextHandle->line[shellContextHandle->c_pos + 1U],
546 &shellContextHandle->line[shellContextHandle->c_pos],
547 (uint32_t)shellContextHandle->l_pos - (uint32_t)shellContextHandle->c_pos);
548 shellContextHandle->line[shellContextHandle->c_pos] = (char)ch;
549 (void)SHELL_WRITEX(shellContextHandle, &shellContextHandle->line[shellContextHandle->c_pos],
550 strlen(&shellContextHandle->line[shellContextHandle->c_pos]));
551 /* Move the cursor to new position */
552 uint32_t i;
553 for (i = (uint32_t)shellContextHandle->c_pos; i < (uint32_t)shellContextHandle->l_pos; i++)
554 {
555 (void)SHELL_WRITEX(shellContextHandle, "\b", 1);
556 }
557 }
558 else
559 {
560 shellContextHandle->line[shellContextHandle->l_pos] = (char)ch;
561 (void)SHELL_WRITEX(shellContextHandle, &shellContextHandle->line[shellContextHandle->l_pos], 1);
562 }
563
564 ch = 0;
565 shellContextHandle->l_pos++;
566 shellContextHandle->c_pos++;
567 } while (0U == shellContextHandle->exit);
568 }
569 #if (defined(SHELL_NON_BLOCKING_MODE) && (SHELL_NON_BLOCKING_MODE > 0U))
570
571 #if defined(OSA_USED)
572
573 #if (defined(SHELL_USE_COMMON_TASK) && (SHELL_USE_COMMON_TASK > 0U))
574 #else
575 }
576 } while (1U == gUseRtos_c); /* USE_RTOS = 0 for BareMetal and 1 for OS */
577 #endif
578
579 #endif
580
581 #endif
582 osaCurrentSr = DisableGlobalIRQ();
583 shellContextHandle->taskBusy = 0U;
584 EnableGlobalIRQ(osaCurrentSr);
585 }
586 }
587
SHELL_HelpCommand(shell_handle_t shellHandle,int32_t argc,char ** argv)588 static shell_status_t SHELL_HelpCommand(shell_handle_t shellHandle, int32_t argc, char **argv)
589 {
590 shell_context_handle_t *shellContextHandle = (shell_context_handle_t *)shellHandle;
591 shell_command_t *shellCommandContextHandle;
592 list_element_handle_t p = LIST_GetHead(&shellContextHandle->commandContextListHead);
593
594 while (p != NULL)
595 {
596 shellCommandContextHandle = SHEEL_COMMAND_POINTER(p);
597 if ((shellCommandContextHandle->pcHelpString != NULL) && (bool)strlen(shellCommandContextHandle->pcHelpString))
598 {
599 (void)SHELL_WRITEX(shellContextHandle, shellCommandContextHandle->pcHelpString,
600 strlen(shellCommandContextHandle->pcHelpString));
601 }
602
603 p = LIST_GetNext(p);
604 }
605 return kStatus_SHELL_Success;
606 }
607
SHELL_ExitCommand(shell_handle_t shellHandle,int32_t argc,char ** argv)608 static shell_status_t SHELL_ExitCommand(shell_handle_t shellHandle, int32_t argc, char **argv)
609 {
610 shell_context_handle_t *shellContextHandle = (shell_context_handle_t *)shellHandle;
611 /* Skip warning */
612 (void)SHELL_WRITEX(shellContextHandle, "\r\nSHELL exited\r\n", strlen("\r\nSHELL exited\r\n"));
613 shellContextHandle->exit = (uint8_t) true;
614 return kStatus_SHELL_Success;
615 }
616
SHELL_ProcessCommand(shell_context_handle_t * shellContextHandle,const char * cmd)617 static void SHELL_ProcessCommand(shell_context_handle_t *shellContextHandle, const char *cmd)
618 {
619 shell_command_t *tmpCommand = NULL;
620 const char *tmpCommandString;
621 int32_t argc;
622 char *argv[SHELL_BUFFER_SIZE] = {0};
623 list_element_handle_t p;
624 uint8_t flag = 1;
625 uint8_t tmpCommandLen;
626 uint8_t tmpLen;
627 uint8_t i = 0;
628
629 tmpLen = (uint8_t)strlen(cmd);
630 if (tmpLen >= SHELL_BUFFER_SIZE - 1U)
631 {
632 (void)SHELL_Printf(shellContextHandle,
633 "Command line length should not more than SHELL_BUFFER_SIZE, please input command less "
634 "(SHELL_BUFFER_SIZE - 1) characters again!\r\n");
635 return;
636 }
637 else
638 {
639 argc = SHELL_ParseLine(cmd, tmpLen, argv);
640 }
641
642 if ((argc > 0))
643 {
644 p = LIST_GetHead(&shellContextHandle->commandContextListHead);
645 while (p != NULL)
646 {
647 tmpCommand = SHEEL_COMMAND_POINTER(p);
648 tmpCommandString = tmpCommand->pcCommand;
649 tmpCommandLen = (uint8_t)strlen(tmpCommandString);
650 /* Compare with space or end of string */
651 if ((cmd[tmpCommandLen] == ' ') || (cmd[tmpCommandLen] == (char)0x00))
652 {
653 if (SHELL_StringCompare(tmpCommandString, argv[0], (int32_t)tmpCommandLen) == 0)
654 {
655 /* support commands with optional number of parameters */
656 if (tmpCommand->cExpectedNumberOfParameters == (uint8_t)SHELL_IGNORE_PARAMETER_COUNT)
657 {
658 flag = 0;
659 }
660 else if ((tmpCommand->cExpectedNumberOfParameters == 0U) && (argc == 1))
661 {
662 flag = 0;
663 }
664 else if (tmpCommand->cExpectedNumberOfParameters > 0U)
665 {
666 if ((argc - 1) == (int32_t)tmpCommand->cExpectedNumberOfParameters)
667 {
668 flag = 0;
669 }
670 }
671 else
672 {
673 flag = 1;
674 }
675 break;
676 }
677 }
678 p = LIST_GetNext(p);
679 }
680 if (NULL == p)
681 {
682 tmpCommand = NULL;
683 }
684 }
685
686 if ((tmpCommand != NULL) && (flag == 1U))
687 {
688 (void)SHELL_Write(
689 shellContextHandle,
690 "\r\nIncorrect command parameter(s). Enter \"help\" to view a list of available commands.\r\n\r\n",
691 strlen(
692 "\r\nIncorrect command parameter(s). Enter \"help\" to view a list of available commands.\r\n\r\n"));
693 }
694 else if (tmpCommand != NULL)
695 {
696 tmpLen = (uint8_t)strlen(cmd);
697 /* Compare with last command. Push back to history buffer if different */
698 if (tmpLen != (uint8_t)SHELL_StringCompare(cmd, shellContextHandle->hist_buf[0], (int32_t)strlen(cmd)))
699 {
700 for (i = SHELL_HISTORY_COUNT - 1U; i > 0U; i--)
701 {
702 (void)memset(shellContextHandle->hist_buf[i], (int)'\0', SHELL_BUFFER_SIZE);
703 tmpLen = (uint8_t)strlen(shellContextHandle->hist_buf[i - 1U]);
704 (void)memcpy(shellContextHandle->hist_buf[i], shellContextHandle->hist_buf[i - 1U], tmpLen);
705 }
706 (void)memset(shellContextHandle->hist_buf[0], (int)'\0', SHELL_BUFFER_SIZE);
707 tmpLen = (uint8_t)strlen(cmd);
708 (void)memcpy(shellContextHandle->hist_buf[0], cmd, tmpLen);
709 if (shellContextHandle->hist_count < SHELL_HISTORY_COUNT)
710 {
711 shellContextHandle->hist_count++;
712 }
713 }
714 if (kStatus_SHELL_RetUsage == tmpCommand->pFuncCallBack(shellContextHandle, argc, argv))
715 {
716 if (NULL != tmpCommand->pcHelpString)
717 {
718 (void)SHELL_WRITEX(shellContextHandle, tmpCommand->pcHelpString, strlen(tmpCommand->pcHelpString));
719 }
720 else
721 {
722 (void)SHELL_HelpCommand(shellContextHandle, 0, NULL);
723 }
724 }
725 }
726 else
727 {
728 (void)SHELL_Write(
729 shellContextHandle,
730 "\r\nCommand not recognized. Enter 'help' to view a list of available commands.\r\n\r\n",
731 strlen("\r\nCommand not recognized. Enter 'help' to view a list of available commands.\r\n\r\n"));
732 }
733 }
734
SHELL_GetHistoryCommand(shell_context_handle_t * shellContextHandle,uint8_t hist_pos)735 static void SHELL_GetHistoryCommand(shell_context_handle_t *shellContextHandle, uint8_t hist_pos)
736 {
737 uint32_t i;
738 uint32_t tmp;
739
740 if (shellContextHandle->hist_buf[0][0] == '\0')
741 {
742 shellContextHandle->hist_current = 0;
743 return;
744 }
745
746 #if 0 /*hist_pos is passed from hist_current. And hist_current is only changed in case 'A'/'B',as hist_count is 3 \
747 most, it can't be more than 3 */
748 if (hist_pos >= SHELL_HISTORY_COUNT)
749 {
750 hist_pos = SHELL_HISTORY_COUNT - 1U;
751 }
752 #endif
753
754 tmp = strlen(shellContextHandle->line);
755 /* Clear current if have */
756 if (tmp > 0U)
757 {
758 (void)memset(shellContextHandle->line, (int)'\0', tmp);
759 for (i = 0U; i < tmp; i++)
760 {
761 (void)SHELL_WRITEX(shellContextHandle, "\b \b", 3);
762 }
763 }
764
765 shellContextHandle->l_pos = (uint8_t)strlen(shellContextHandle->hist_buf[hist_pos]);
766 shellContextHandle->c_pos = shellContextHandle->l_pos;
767 (void)memcpy(shellContextHandle->line, shellContextHandle->hist_buf[hist_pos], shellContextHandle->l_pos);
768 (void)SHELL_WRITEX(shellContextHandle, shellContextHandle->hist_buf[hist_pos],
769 strlen(shellContextHandle->hist_buf[hist_pos]));
770 }
771
SHELL_AutoComplete(shell_context_handle_t * shellContextHandle)772 static void SHELL_AutoComplete(shell_context_handle_t *shellContextHandle)
773 {
774 int32_t minLen;
775 list_element_handle_t p;
776 shell_command_t *tmpCommand = NULL;
777 const char *namePtr;
778 const char *cmdName;
779
780 minLen = (int32_t)SHELL_BUFFER_SIZE;
781 namePtr = NULL;
782
783 /* Empty tab, list all commands */
784 if (shellContextHandle->line[0] == '\0')
785 {
786 (void)SHELL_HelpCommand(shellContextHandle, 0, NULL);
787 return;
788 }
789
790 (void)SHELL_WRITEX(shellContextHandle, "\r\n", 2);
791
792 /* Do auto complete */
793 p = LIST_GetHead(&shellContextHandle->commandContextListHead);
794 while (p != NULL)
795 {
796 tmpCommand = SHEEL_COMMAND_POINTER(p);
797 cmdName = tmpCommand->pcCommand;
798 if (SHELL_StringCompare(shellContextHandle->line, cmdName, (int32_t)strlen(shellContextHandle->line)) == 0)
799 {
800 /* Show possible matches */
801 (void)SHELL_Printf(shellContextHandle, "%s ", cmdName);
802 if (minLen > ((int32_t)strlen(cmdName)))
803 {
804 namePtr = cmdName;
805 minLen = (int32_t)strlen(namePtr);
806 }
807 }
808 p = LIST_GetNext(p);
809 }
810 /* Auto complete string */
811 if (namePtr != NULL)
812 {
813 (void)memcpy(shellContextHandle->line, namePtr, (uint32_t)minLen);
814 }
815 SHELL_PrintPrompt(shellContextHandle);
816 (void)SHELL_WRITEX(shellContextHandle, shellContextHandle->line, strlen(shellContextHandle->line));
817 return;
818 }
819
SHELL_StringCompare(const char * str1,const char * str2,int32_t count)820 static int32_t SHELL_StringCompare(const char *str1, const char *str2, int32_t count)
821 {
822 while ((bool)(count--))
823 {
824 if (*str1++ != *str2++)
825 {
826 return (int32_t)(*(str1 - 1) - *(str2 - 1));
827 }
828 }
829 return 0;
830 }
831
SHELL_ParseLine(const char * cmd,uint32_t len,char * argv[])832 static int32_t SHELL_ParseLine(const char *cmd, uint32_t len, char *argv[])
833 {
834 uint32_t argc;
835 char *p;
836 uint32_t position;
837
838 /* Init params */
839 (void)memset(s_paramBuffer, (int)'\0', len + 1U);
840 (void)memcpy(s_paramBuffer, cmd, len);
841
842 p = s_paramBuffer;
843 position = 0;
844 argc = 0;
845
846 while (position < len)
847 {
848 /* Skip all blanks */
849 while ((position < len) && ((char)(*p) == ' '))
850 {
851 *p = '\0';
852 p++;
853 position++;
854 }
855
856 if (position >= len)
857 {
858 break;
859 }
860
861 /* Process begin of a string */
862 if (*p == '"')
863 {
864 p++;
865 position++;
866 argv[argc] = p;
867 argc++;
868 /* Skip this string */
869 while ((*p != '"') && (position < len))
870 {
871 p++;
872 position++;
873 }
874 /* Skip '"' */
875 *p = '\0';
876 p++;
877 position++;
878 }
879 else /* Normal char */
880 {
881 argv[argc] = p;
882 argc++;
883 while (((char)*p != ' ') && (position < len))
884 {
885 p++;
886 position++;
887 }
888 }
889 }
890 return (int32_t)argc;
891 }
892
SHELL_GetChar(shell_context_handle_t * shellContextHandle,uint8_t * ch)893 static shell_status_t SHELL_GetChar(shell_context_handle_t *shellContextHandle, uint8_t *ch)
894 {
895 shell_status_t status;
896
897 #if (!defined(SDK_DEBUGCONSOLE_UART) && (defined(SDK_DEBUGCONSOLE) && (SDK_DEBUGCONSOLE != 1)))
898 if (NULL == shellContextHandle->serialHandle)
899 {
900 int ret;
901 ret = getchar();
902 if (ret > 0)
903 {
904 *ch = (uint8_t)ret;
905 status = kStatus_SHELL_Success;
906 }
907 else
908 {
909 status = kStatus_SHELL_Error;
910 }
911 }
912 else
913 #endif
914 {
915 #if (defined(SHELL_NON_BLOCKING_MODE) && (SHELL_NON_BLOCKING_MODE > 0U))
916 uint32_t length = 0;
917
918 (void)SerialManager_TryRead(shellContextHandle->serialReadHandle, ch, 1, &length);
919
920 if (length > 0U)
921 {
922 status = kStatus_SHELL_Success;
923 }
924 else
925 {
926 status = kStatus_SHELL_Error;
927 }
928 #else
929 status = (shell_status_t)SerialManager_ReadBlocking(shellContextHandle->serialReadHandle, ch, 1);
930 #endif
931 }
932
933 return status;
934 }
935
SHELL_Init(shell_handle_t shellHandle,serial_handle_t serialHandle,char * prompt)936 shell_status_t SHELL_Init(shell_handle_t shellHandle, serial_handle_t serialHandle, char *prompt)
937 {
938 shell_context_handle_t *shellContextHandle;
939 serial_manager_status_t status = kStatus_SerialManager_Error;
940 (void)status;
941
942 assert(shellHandle);
943 #if !(!defined(SDK_DEBUGCONSOLE_UART) && (defined(SDK_DEBUGCONSOLE) && (SDK_DEBUGCONSOLE != 1)))
944 assert(serialHandle);
945 #endif
946 assert(prompt);
947 assert(SHELL_HANDLE_SIZE >= sizeof(shell_context_handle_t));
948
949 shellContextHandle = (shell_context_handle_t *)shellHandle;
950
951 /* memory set for shellHandle */
952 (void)memset(shellHandle, 0, SHELL_HANDLE_SIZE);
953
954 #if (!defined(SDK_DEBUGCONSOLE_UART) && (defined(SDK_DEBUGCONSOLE) && (SDK_DEBUGCONSOLE != 1)))
955 if (NULL == serialHandle)
956 {
957 }
958 else
959 #endif
960 {
961 #if (defined(SHELL_NON_BLOCKING_MODE) && (SHELL_NON_BLOCKING_MODE > 0U))
962
963 #if defined(OSA_USED)
964
965 #if (defined(SHELL_USE_COMMON_TASK) && (SHELL_USE_COMMON_TASK > 0U))
966 (void)COMMON_TASK_init();
967 #else
968 if (KOSA_StatusSuccess != OSA_EventCreate((osa_event_handle_t)shellContextHandle->event, 1U))
969 {
970 return kStatus_SHELL_Error;
971 }
972
973 if (KOSA_StatusSuccess !=
974 OSA_TaskCreate((osa_task_handle_t)shellContextHandle->taskId, OSA_TASK(SHELL_Task), shellContextHandle))
975 {
976 return kStatus_SHELL_Error;
977 }
978 #endif
979
980 #endif
981
982 #endif
983 }
984
985 shellContextHandle->prompt = prompt;
986 shellContextHandle->serialHandle = serialHandle;
987
988 #if (!defined(SDK_DEBUGCONSOLE_UART) && (defined(SDK_DEBUGCONSOLE) && (SDK_DEBUGCONSOLE != 1)))
989 if (NULL == serialHandle)
990 {
991 }
992 else
993 #endif
994 {
995 shellContextHandle->serialWriteHandle = (serial_write_handle_t)&shellContextHandle->serialWriteHandleBuffer[0];
996 status = SerialManager_OpenWriteHandle(shellContextHandle->serialHandle, shellContextHandle->serialWriteHandle);
997 assert(kStatus_SerialManager_Success == status);
998
999 shellContextHandle->serialReadHandle = (serial_read_handle_t)&shellContextHandle->serialReadHandleBuffer[0];
1000 status = SerialManager_OpenReadHandle(shellContextHandle->serialHandle, shellContextHandle->serialReadHandle);
1001 assert(kStatus_SerialManager_Success == status);
1002
1003 #if (defined(SHELL_NON_BLOCKING_MODE) && (SHELL_NON_BLOCKING_MODE > 0U))
1004 status = SerialManager_InstallRxCallback(shellContextHandle->serialReadHandle, SHELL_SerialManagerRxCallback,
1005 shellContextHandle);
1006 assert(kStatus_SerialManager_Success == status);
1007 #endif
1008 (void)status;
1009 }
1010
1011 (void)SHELL_RegisterCommand(shellContextHandle, SHELL_COMMAND(help));
1012 (void)SHELL_RegisterCommand(shellContextHandle, SHELL_COMMAND(exit));
1013 SHELL_MUTEX_CREATE();
1014 (void)SHELL_Write(shellContextHandle, "\r\nCopyright 2022 NXP\r\n", strlen("\r\nCopyright 2022 NXP\r\n"));
1015 SHELL_PrintPrompt(shellContextHandle);
1016
1017 return kStatus_SHELL_Success;
1018 }
1019
SHELL_RegisterCommand(shell_handle_t shellHandle,shell_command_t * shellCommand)1020 shell_status_t SHELL_RegisterCommand(shell_handle_t shellHandle, shell_command_t *shellCommand)
1021 {
1022 shell_context_handle_t *shellContextHandle = (shell_context_handle_t *)shellHandle;
1023 assert(shellHandle);
1024 assert(shellCommand);
1025
1026 /* memory set for shellHandle */
1027 (void)memset(&shellCommand->link, 0, sizeof(shellCommand->link));
1028
1029 (void)LIST_AddTail(&shellContextHandle->commandContextListHead, &shellCommand->link);
1030
1031 return kStatus_SHELL_Success;
1032 }
1033
SHELL_UnregisterCommand(shell_command_t * shellCommand)1034 shell_status_t SHELL_UnregisterCommand(shell_command_t *shellCommand)
1035 {
1036 assert(shellCommand);
1037
1038 (void)LIST_RemoveElement(&shellCommand->link);
1039
1040 /* memory set for shellHandle */
1041 (void)memset(&shellCommand->link, 0, sizeof(shellCommand->link));
1042
1043 return kStatus_SHELL_Success;
1044 }
1045
SHELL_Write(shell_handle_t shellHandle,const char * buffer,uint32_t length)1046 shell_status_t SHELL_Write(shell_handle_t shellHandle, const char *buffer, uint32_t length)
1047 {
1048 shell_context_handle_t *shellContextHandle;
1049 uint32_t primask;
1050 shell_status_t status;
1051
1052 assert(shellHandle);
1053 assert(buffer);
1054
1055 if (!(bool)length)
1056 {
1057 return kStatus_SHELL_Success;
1058 }
1059
1060 shellContextHandle = (shell_context_handle_t *)shellHandle;
1061
1062 primask = DisableGlobalIRQ();
1063 if ((bool)shellContextHandle->printBusy)
1064 {
1065 EnableGlobalIRQ(primask);
1066 return kStatus_SHELL_Error;
1067 }
1068 shellContextHandle->printBusy = 1U;
1069 EnableGlobalIRQ(primask);
1070 #if (!defined(SDK_DEBUGCONSOLE_UART) && (defined(SDK_DEBUGCONSOLE) && (SDK_DEBUGCONSOLE != 1)))
1071 if (NULL == shellContextHandle->serialHandle)
1072 {
1073 status = kStatus_SHELL_Success;
1074 for (uint32_t index = 0; index < length; index++)
1075 {
1076 (void)putchar(buffer[index]);
1077 }
1078 }
1079 else
1080 #endif
1081 {
1082 status = (shell_status_t)SerialManager_WriteBlocking(shellContextHandle->serialWriteHandle, (uint8_t *)buffer,
1083 length);
1084 }
1085
1086 shellContextHandle->printBusy = 0U;
1087
1088 return status;
1089 }
1090
SHELL_Printf(shell_handle_t shellHandle,const char * formatString,...)1091 int SHELL_Printf(shell_handle_t shellHandle, const char *formatString, ...)
1092 {
1093 shell_context_handle_t *shellContextHandle;
1094 uint32_t length;
1095 uint32_t primask;
1096 va_list ap;
1097
1098 assert(shellHandle);
1099 assert(formatString);
1100
1101 shellContextHandle = (shell_context_handle_t *)shellHandle;
1102
1103 primask = DisableGlobalIRQ();
1104 if ((bool)shellContextHandle->printBusy)
1105 {
1106 EnableGlobalIRQ(primask);
1107 return -1;
1108 }
1109 shellContextHandle->printBusy = 1U;
1110 EnableGlobalIRQ(primask);
1111
1112 va_start(ap, formatString);
1113
1114 shellContextHandle->printLength = 0U;
1115 length = (uint32_t)SHELL_Sprintf(shellHandle, formatString, ap);
1116 #if (!defined(SDK_DEBUGCONSOLE_UART) && (defined(SDK_DEBUGCONSOLE) && (SDK_DEBUGCONSOLE != 1)))
1117 if (NULL == shellContextHandle->serialHandle)
1118 {
1119 for (uint32_t index = 0; index < length; index++)
1120 {
1121 (void)putchar(shellContextHandle->printBuffer[index]);
1122 }
1123 }
1124 else
1125 #endif
1126 {
1127 (void)SerialManager_WriteBlocking(shellContextHandle->serialWriteHandle,
1128 (uint8_t *)shellContextHandle->printBuffer, length);
1129 }
1130 va_end(ap);
1131
1132 shellContextHandle->printBusy = 0U;
1133 return (int32_t)shellContextHandle->printLength;
1134 }
1135
SHELL_WriteSynchronization(shell_handle_t shellHandle,const char * buffer,uint32_t length)1136 shell_status_t SHELL_WriteSynchronization(shell_handle_t shellHandle, const char *buffer, uint32_t length)
1137 {
1138 shell_status_t status;
1139
1140 assert(SHELL_checkRunningInIsr() == false);
1141
1142 SHELL_ENTER_CRITICAL();
1143 status = SHELL_Write(shellHandle, buffer, length);
1144
1145 SHELL_EXIT_CRITICAL();
1146
1147 return status;
1148 }
1149
SHELL_PrintfSynchronization(shell_handle_t shellHandle,const char * formatString,...)1150 int SHELL_PrintfSynchronization(shell_handle_t shellHandle, const char *formatString, ...)
1151 {
1152 shell_status_t status;
1153 shell_context_handle_t *shellContextHandle;
1154 va_list ap;
1155 uint32_t length;
1156
1157 assert(SHELL_checkRunningInIsr() == false);
1158
1159 shellContextHandle = (shell_context_handle_t *)shellHandle;
1160
1161 SHELL_ENTER_CRITICAL();
1162 va_start(ap, formatString);
1163 length = (uint32_t)SHELL_Sprintf(shellHandle, formatString, ap);
1164
1165 status = SHELL_Write(shellHandle, (const char *)shellContextHandle->printBuffer, length);
1166 va_end(ap);
1167 SHELL_EXIT_CRITICAL();
1168
1169 return (status == kStatus_SHELL_Success) ? (int)length : 0;
1170 }
SHELL_ChangePrompt(shell_handle_t shellHandle,char * prompt)1171 void SHELL_ChangePrompt(shell_handle_t shellHandle, char *prompt)
1172 {
1173 shell_context_handle_t *shellContextHandle;
1174 assert(shellHandle);
1175 assert(prompt);
1176
1177 shellContextHandle = (shell_context_handle_t *)shellHandle;
1178
1179 shellContextHandle->prompt = prompt;
1180 SHELL_PrintPrompt(shellContextHandle);
1181 }
1182
SHELL_PrintPrompt(shell_handle_t shellHandle)1183 void SHELL_PrintPrompt(shell_handle_t shellHandle)
1184 {
1185 shell_context_handle_t *shellContextHandle;
1186 assert(shellHandle);
1187
1188 shellContextHandle = (shell_context_handle_t *)shellHandle;
1189
1190 (void)SHELL_Write(shellContextHandle, "\r\n", 2U);
1191 (void)SHELL_Write(shellContextHandle, shellContextHandle->prompt, strlen(shellContextHandle->prompt));
1192 }
1193