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