]> begriffs open source - cmsis-driver-validation/blob - Tools/USART_Server/Source/USART_Server.c
Update GitHub Actions runner to ubuntu-22.04 (#18)
[cmsis-driver-validation] / Tools / USART_Server / Source / USART_Server.c
1 /*
2  * Copyright (c) 2020-2022 Arm Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Licensed under the Apache License, Version 2.0 (the License); you may
7  * not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an AS IS BASIS, WITHOUT
14  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  * -----------------------------------------------------------------------------
19  *
20  * Project:     USART Server
21  * Title:       USART Server application
22  *
23  * -----------------------------------------------------------------------------
24  */
25
26
27 #include <stdint.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <stdio.h>
31
32 #include "USART_Server_Config.h"
33 #include "USART_Server_HW.h"
34 #include "USART_Server.h"
35
36 #include "cmsis_os2.h"
37 #include "cmsis_compiler.h"
38 #include "cmsis_vio.h"
39
40 #include "Driver_USART.h"               // ::CMSIS Driver:USART
41
42 #ifndef  USART_SERVER_DEBUG
43 #define  USART_SERVER_DEBUG             0
44 #endif
45
46 // Fixed USART Server settings (not available through USART_Server_Config.h)
47 #define  USART_SERVER_BAUDRATE          115200  // Baudrate
48 #define  USART_SERVER_DATA_BITS         8       // 8 data bits
49 #define  USART_SERVER_PARITY            0       // None
50 #define  USART_SERVER_STOP_BITS         0       // 1 stop bit
51 #define  USART_SERVER_FLOW_CONTROL      0       // None
52
53 #define  USART_RECEIVE_EVENTS_MASK     (ARM_USART_EVENT_RECEIVE_COMPLETE  | \
54                                         ARM_USART_EVENT_RX_OVERFLOW       | \
55                                         ARM_USART_EVENT_RX_BREAK          | \
56                                         ARM_USART_EVENT_RX_FRAMING_ERROR  | \
57                                         ARM_USART_EVENT_RX_PARITY_ERROR)
58 #define  USART_TRANSFER_EVENTS_MASK    (ARM_USART_EVENT_TRANSFER_COMPLETE | \
59                                         ARM_USART_EVENT_TX_UNDERFLOW      | \
60                                         ARM_USART_EVENT_RX_OVERFLOW)
61
62 #define  DATA_BITS_TO_BYTES(data_bits)      ((((data_bits) > 8) ? (2U) : (1U)))
63 #define  BYTES_TO_ITEMS(bytes,data_bits)    ((bytes + DATA_BITS_TO_BYTES(data_bits) - 1U) / DATA_BITS_TO_BYTES(data_bits))
64
65 /* Access to Driver_USART# */
66 #define  USART_Driver_Aux(n)            Driver_USART##n
67 #define  USART_Driver_Name(n)           USART_Driver_Aux(n)
68 extern   ARM_DRIVER_USART               USART_Driver_Name(USART_SERVER_DRV_NUM);
69 #define  drvUSART                     (&USART_Driver_Name(USART_SERVER_DRV_NUM))
70
71 typedef struct {                        // USART Interface settings structure
72   uint32_t mode;
73   uint32_t data_bits;
74   uint32_t parity;
75   uint32_t stop_bits;
76   uint32_t flow_control;
77   uint32_t cpol;
78   uint32_t cpha;
79   uint32_t irda_pulse;
80   uint32_t smartcard_clock;
81   uint32_t smartcard_guard_time;
82   uint32_t baudrate;
83 } USART_COM_CONFIG_t;
84
85 // Structure containing command string and pointer to command handling function
86 typedef struct {
87   const char     *command;
88         int32_t (*Command_Func) (const char *command);
89 } USART_CMD_DESC_t;
90
91 // Local functions
92
93 // Main thread (reception and execution of command)
94 __NO_RETURN \
95 static void     USART_Server_Thread      (void *argument);
96
97 // USART Interface communication functions
98 static void     USART_Com_Event          (uint32_t event);
99 static int32_t  USART_Com_Initialize     (void);
100 static int32_t  USART_Com_Uninitialize   (void);
101 static int32_t  USART_Com_PowerOn        (void);
102 static int32_t  USART_Com_PowerOff       (void);
103 static int32_t  USART_Com_Configure      (const USART_COM_CONFIG_t *config);
104 static int32_t  USART_Com_Receive        (                      void *data_in, uint32_t num, uint32_t timeout);
105 static int32_t  USART_Com_Send           (const void *data_out,                uint32_t num, uint32_t timeout);
106 static int32_t  USART_Com_Transfer       (const void *data_out, void *data_in, uint32_t num, uint32_t timeout);
107 static int32_t  USART_Com_Break          (uint32_t val);
108 static int32_t  USART_Com_SetModemControl(ARM_USART_MODEM_CONTROL control);
109 static int32_t  USART_Com_Abort          (void);
110 static uint32_t USART_Com_GetCnt         (void);
111 static uint32_t USART_Com_GetMdm         (void);
112
113 // Command handling functions
114 static int32_t  USART_Cmd_GetVer         (const char *cmd);
115 static int32_t  USART_Cmd_GetCap         (const char *cmd);
116 static int32_t  USART_Cmd_SetBuf         (const char *cmd);
117 static int32_t  USART_Cmd_GetBuf         (const char *cmd);
118 static int32_t  USART_Cmd_SetCom         (const char *cmd);
119 static int32_t  USART_Cmd_Xfer           (const char *cmd);
120 static int32_t  USART_Cmd_GetCnt         (const char *cmd);
121 static int32_t  USART_Cmd_SetBrk         (const char *cmd);
122 static int32_t  USART_Cmd_GetBrk         (const char *cmd);
123 static int32_t  USART_Cmd_SetMdm         (const char *cmd);
124 static int32_t  USART_Cmd_GetMdm         (const char *cmd);
125
126 // Local variables
127 static const uint32_t usart_baudrates[] = {
128   9600U, 19200U, 38400U, 57600U, 115200U, 230400U, 460800U, 921600U
129 };
130
131 static const char *str_mode[] = {
132   "Unknown",
133   "Async",
134   "Singl-wire",
135   "IrDA"
136 };
137
138 // Command specification (command string, command handling function)
139 static const USART_CMD_DESC_t usart_cmd_desc[] = {
140  { "GET VER" , USART_Cmd_GetVer },
141  { "GET CAP" , USART_Cmd_GetCap },
142  { "SET BUF" , USART_Cmd_SetBuf },
143  { "GET BUF" , USART_Cmd_GetBuf },
144  { "SET COM" , USART_Cmd_SetCom },
145  { "XFER"    , USART_Cmd_Xfer   },
146  { "GET CNT" , USART_Cmd_GetCnt },
147  { "SET BRK" , USART_Cmd_SetBrk },
148  { "GET BRK" , USART_Cmd_GetBrk },
149  { "SET MDM" , USART_Cmd_SetMdm },
150  { "GET MDM" , USART_Cmd_GetMdm }
151 };
152
153 static       osThreadId_t       usart_server_thread_id    =   NULL;
154 static       osThreadAttr_t     thread_attr = {
155   .name       = "USART_Server_Thread",
156   .stack_size = 512U
157 };
158
159 static ARM_USART_CAPABILITIES   drv_cap;
160
161 static       uint8_t            usart_server_state        =   USART_SERVER_STATE_RECEPTION;
162 static       uint32_t           usart_cmd_timeout         =   USART_SERVER_CMD_TIMEOUT;
163 static       uint32_t           usart_xfer_timeout        =   USART_SERVER_CMD_TIMEOUT;
164 static       uint32_t           usart_xfer_cnt            =   0U;
165 static       uint32_t           usart_xfer_buf_size       =   USART_SERVER_BUF_SIZE;
166 static const USART_COM_CONFIG_t usart_com_config_default  = {(USART_SERVER_MODE         << ARM_USART_CONTROL_Pos)      & ARM_USART_CONTROL_Msk, 
167 #if (USART_SERVER_DATA_BITS == 8U)
168                                                               ARM_USART_DATA_BITS_8,
169 #else
170                                                              (USART_SERVER_DATA_BITS    << ARM_USART_DATA_BITS_Pos)    & ARM_USART_DATA_BITS_Msk, 
171 #endif
172                                                              (USART_SERVER_PARITY       << ARM_USART_PARITY_Pos)       & ARM_USART_PARITY_Msk, 
173                                                              (USART_SERVER_STOP_BITS    << ARM_USART_STOP_BITS_Pos)    & ARM_USART_STOP_BITS_Msk, 
174                                                              (USART_SERVER_FLOW_CONTROL << ARM_USART_FLOW_CONTROL_Pos) & ARM_USART_FLOW_CONTROL_Msk, 
175                                                               ARM_USART_CPOL0, 
176                                                               ARM_USART_CPHA0, 
177                                                               0U, 
178                                                               0U, 
179                                                               0U, 
180                                                               USART_SERVER_BAUDRATE
181                                                             };
182 static       USART_COM_CONFIG_t usart_com_config_xfer;
183 static       uint8_t            usart_bytes_per_item        = 1U;
184 static       uint8_t            usart_cmd_buf_rx[32]        __ALIGNED(4);
185 static       uint8_t            usart_cmd_buf_tx[32]        __ALIGNED(4);
186 static       uint8_t           *ptr_usart_xfer_buf_rx       = NULL;
187 static       uint8_t           *ptr_usart_xfer_buf_tx       = NULL;
188 static       void              *ptr_usart_xfer_buf_rx_alloc = NULL;
189 static       void              *ptr_usart_xfer_buf_tx_alloc = NULL;
190
191 static       uint32_t           break_status                = 0U;
192 static       uint32_t           dcd_ri_mask                 = 3U;
193
194 // Global functions
195
196 // Default empty implementation if external functions are not provided, 
197 // otherwise overridden by externally provided functions
198 __WEAK void USART_Server_Pins_Initialize   (void) { dcd_ri_mask = 0U; }
199 __WEAK void USART_Server_Pins_Uninitialize (void) {}
200 __WEAK void USART_Server_Pin_DCD_SetState  (uint32_t state) {}
201 __WEAK void USART_Server_Pin_RI_SetState   (uint32_t state) {}
202
203 /**
204   \fn            int32_t USART_Server_Start (void)
205   \brief         Initialize, power up, configure USART interface and start USART Server thread.
206   \return        execution status
207                    - EXIT_SUCCESS: Operation successful
208                    - EXIT_FAILURE: Operation failed
209 */
210 int32_t USART_Server_Start (void) {
211   int32_t  ret;
212   uint32_t mode, mode_disp;
213
214   mode = USART_SERVER_MODE;
215   switch (mode) {
216     case 1:
217       mode_disp = 1;
218       break;
219     case 4:
220       mode_disp = 2;
221       break;
222     case 5:
223       mode_disp = 3;
224       break;
225     default:
226       mode_disp = 0U;
227       break;
228   }
229
230   vioInit();
231   (void)vioPrint(vioLevelHeading, "USART Server v%s\r\nMode: %s", USART_SERVER_VER, str_mode[mode_disp]);
232
233   // Initialize local variables
234   usart_server_state   = USART_SERVER_STATE_RECEPTION;
235   usart_cmd_timeout    = USART_SERVER_CMD_TIMEOUT;
236   usart_xfer_timeout   = USART_SERVER_CMD_TIMEOUT;
237   usart_xfer_cnt       = 0U;
238   usart_xfer_buf_size  = USART_SERVER_BUF_SIZE;
239   usart_bytes_per_item = DATA_BITS_TO_BYTES(USART_SERVER_DATA_BITS);
240   memset(usart_cmd_buf_rx,  0, sizeof(usart_cmd_buf_rx));
241   memset(usart_cmd_buf_tx,  0, sizeof(usart_cmd_buf_tx));
242   memcpy(&usart_com_config_xfer, &usart_com_config_default, sizeof(USART_COM_CONFIG_t));
243
244   // Allocate buffers for data transmission and reception
245   // (maximum size is incremented by 4 bytes to ensure that buffer can be aligned to 4 bytes)
246
247   ptr_usart_xfer_buf_rx_alloc = malloc(USART_SERVER_BUF_SIZE + 4U);
248   if (((uint32_t)ptr_usart_xfer_buf_rx_alloc & 3U) != 0U) {
249     // If allocated memory is not 4 byte aligned, use next 4 byte aligned address for ptr_tx_buf
250     ptr_usart_xfer_buf_rx = (uint8_t *)((((uint32_t)ptr_usart_xfer_buf_rx_alloc) + 3U) & (~3U));
251   } else {
252     // If allocated memory is 4 byte aligned, use it directly
253     ptr_usart_xfer_buf_rx = (uint8_t *)ptr_usart_xfer_buf_rx_alloc;
254   }
255   ptr_usart_xfer_buf_tx_alloc = malloc(USART_SERVER_BUF_SIZE + 4U);
256   if (((uint32_t)ptr_usart_xfer_buf_tx_alloc & 3U) != 0U) {
257     // If allocated memory is not 4 byte aligned, use next 4 byte aligned address for ptr_tx_buf
258     ptr_usart_xfer_buf_tx = (uint8_t *)((((uint32_t)ptr_usart_xfer_buf_tx_alloc) + 3U) & (~3U));
259   } else {
260     // If allocated memory is 4 byte aligned, use it directly
261     ptr_usart_xfer_buf_tx = (uint8_t *)ptr_usart_xfer_buf_tx_alloc;
262   }
263
264   if ((ptr_usart_xfer_buf_rx != NULL) || (ptr_usart_xfer_buf_tx != NULL)) {
265     memset(ptr_usart_xfer_buf_rx, 0, USART_SERVER_BUF_SIZE);
266     memset(ptr_usart_xfer_buf_rx, 0, USART_SERVER_BUF_SIZE);
267     ret = EXIT_SUCCESS;
268   } else {
269     ret = EXIT_FAILURE;
270   }
271
272   // Get driver capabilities
273   drv_cap = drvUSART->GetCapabilities();
274
275   if (ret == EXIT_SUCCESS) {
276     ret = USART_Com_Initialize();
277   }
278
279   if (ret == EXIT_SUCCESS) {
280     ret = USART_Com_PowerOn();
281   }
282
283   if (ret == EXIT_SUCCESS) {
284     ret = USART_Com_Configure(&usart_com_config_default);
285   }
286
287   USART_Server_Pins_Initialize();
288
289   if ((ret == EXIT_SUCCESS) && (usart_server_thread_id == NULL)) {
290     // Create USART_Server_Thread thread
291     usart_server_thread_id = osThreadNew(USART_Server_Thread, NULL, &thread_attr);
292     if (usart_server_thread_id == NULL) {
293       ret = EXIT_FAILURE;
294     }
295   }
296
297   if (ret != EXIT_SUCCESS) {
298     vioPrint(vioLevelError, "Server Start failed!");
299   }
300
301   return ret;
302 }
303
304 /**
305   \fn            int32_t USART_Server_Stop (void)
306   \brief         Terminate USART Server thread, power down and uninitialize USART interface.
307   \return        execution status
308                    - EXIT_SUCCESS: Operation successful
309                    - EXIT_FAILURE: Operation failed
310 */
311 int32_t USART_Server_Stop (void) {
312    int32_t ret;
313   uint32_t i;
314
315   ret = EXIT_FAILURE;
316
317   if (usart_server_thread_id != NULL) {
318     usart_server_state = USART_SERVER_STATE_TERMINATE;
319     for (i = 0U; i < 10U; i++) {
320       if (osThreadGetState(usart_server_thread_id) == osThreadTerminated) {
321         usart_server_thread_id = NULL;
322         ret = EXIT_SUCCESS;
323         break;
324       }
325       (void)osDelay(100U);
326     }
327   }
328
329   USART_Server_Pins_Uninitialize();
330
331   if (ret == EXIT_SUCCESS) {
332     ret = USART_Com_PowerOff();
333   }
334
335   if (ret == EXIT_SUCCESS) {
336     ret = USART_Com_Uninitialize();
337   }
338
339   if (ptr_usart_xfer_buf_rx_alloc != NULL) {
340     free(ptr_usart_xfer_buf_rx_alloc);
341     ptr_usart_xfer_buf_rx       = NULL;
342     ptr_usart_xfer_buf_rx_alloc = NULL;
343   }
344   if (ptr_usart_xfer_buf_tx_alloc != NULL) {
345     free(ptr_usart_xfer_buf_tx_alloc);
346     ptr_usart_xfer_buf_tx       = NULL;
347     ptr_usart_xfer_buf_tx_alloc = NULL;
348   }
349
350   if (ret != EXIT_SUCCESS) {
351     vioPrint(vioLevelError, "Server Stop failed! ");
352   }
353
354   return ret;
355 }
356
357
358 // Local functions
359
360 /**
361   \fn            static void USART_Server_Thread (void *argument)
362   \brief         USART Server thread function.
363   \detail        This is a thread function that waits to receive a command from USART Client 
364                  (Driver Validation suite), and after command is received it is executed 
365                  and the process starts again by waiting to receive next command.
366   \param[in]     argument       Not used
367   \return        none
368 */
369 static void USART_Server_Thread (void *argument) {
370   uint8_t i;
371
372   (void)argument;
373
374   for (;;) {
375     switch (usart_server_state) {
376
377       case USART_SERVER_STATE_RECEPTION:  // Receive a command
378         if (USART_Com_Receive(usart_cmd_buf_rx, BYTES_TO_ITEMS(sizeof(usart_cmd_buf_rx),USART_SERVER_DATA_BITS), osWaitForever) == EXIT_SUCCESS) {
379           usart_server_state = USART_SERVER_STATE_EXECUTION;
380         }
381         // If 32 byte command was not received restart the reception of 32 byte command
382         break;
383
384       case USART_SERVER_STATE_EXECUTION:  // Execute a command
385         // Find the command and call handling function
386         for (i = 0U; i < (sizeof(usart_cmd_desc) / sizeof(USART_CMD_DESC_t)); i++) {
387           if (memcmp(usart_cmd_buf_rx, usart_cmd_desc[i].command, strlen(usart_cmd_desc[i].command)) == 0) {
388             (void)usart_cmd_desc[i].Command_Func((const char *)usart_cmd_buf_rx);
389             break;
390           }
391         }
392         vioPrint(vioLevelMessage, "%.20s                    ", usart_cmd_buf_rx);
393         usart_server_state = USART_SERVER_STATE_RECEPTION;
394         break;
395
396       case USART_SERVER_STATE_TERMINATE:  // Self-terminate the thread
397       default:                            // Should never happen, processed as terminate request
398         vioPrint(vioLevelError, "Server stopped!     ");
399         (void)USART_Com_Abort();
400         (void)osThreadTerminate(osThreadGetId());
401         break;
402     }
403   }
404 }
405
406 /**
407   \fn            static void USART_Com_Event (uint32_t event)
408   \brief         USART communication event callback (called from USART driver from IRQ context).
409   \detail        This function dispatches event (flag) to USART Server thread.
410   \param[in]     event       USART event
411                    - ARM_USART_EVENT_SEND_COMPLETE
412                    - ARM_USART_EVENT_RECEIVE_COMPLETE
413                    - ARM_USART_EVENT_TRANSFER_COMPLETE
414                    - ARM_USART_EVENT_TX_COMPLETE
415                    - ARM_USART_EVENT_TX_UNDERFLOW
416                    - ARM_USART_EVENT_RX_OVERFLOW
417                    - ARM_USART_EVENT_RX_TIMEOUT
418                    - ARM_USART_EVENT_RX_BREAK
419                    - ARM_USART_EVENT_RX_FRAMING_ERROR
420                    - ARM_USART_EVENT_RX_PARITY_ERROR
421                    - ARM_USART_EVENT_CTS
422                    - ARM_USART_EVENT_DSR
423                    - ARM_USART_EVENT_DCD
424                    - ARM_USART_EVENT_RI
425   \return        none
426 */
427 static void USART_Com_Event (uint32_t event) {
428
429   if ((event & ARM_USART_EVENT_RX_BREAK) != 0U) {
430     break_status |= 1U;
431   }
432
433   if (usart_server_thread_id != NULL) {
434     (void)osThreadFlagsSet(usart_server_thread_id, event);
435   }
436 }
437
438 /**
439   \fn            static int32_t USART_Com_Initialize (void)
440   \brief         Initialize USART interface.
441   \return        execution status
442                    - EXIT_SUCCESS: Operation successful
443                    - EXIT_FAILURE: Operation failed
444 */
445 static int32_t USART_Com_Initialize (void) {
446   int32_t ret;
447
448   ret = EXIT_FAILURE;
449
450   if (drvUSART->Initialize(USART_Com_Event) == ARM_DRIVER_OK) {
451     ret = EXIT_SUCCESS;
452   }
453
454   return ret;
455 }
456
457 /**
458   \fn            static int32_t USART_Com_Uninitialize (void)
459   \brief         Uninitialize USART interface.
460   \return        execution status
461                    - EXIT_SUCCESS: Operation successful
462                    - EXIT_FAILURE: Operation failed
463 */
464 static int32_t USART_Com_Uninitialize (void) {
465   int32_t ret;
466
467   ret = EXIT_FAILURE;
468
469   if (drvUSART->Uninitialize() == ARM_DRIVER_OK) {
470     ret = EXIT_SUCCESS;
471   }
472
473   return ret;
474 }
475
476 /**
477   \fn            static int32_t USART_Com_PowerOn (void)
478   \brief         Power-up USART interface.
479   \return        execution status
480                    - EXIT_SUCCESS: Operation successful
481                    - EXIT_FAILURE: Operation failed
482 */
483 static int32_t USART_Com_PowerOn (void) {
484   int32_t ret;
485
486   ret = EXIT_FAILURE;
487
488   if (drvUSART->PowerControl(ARM_POWER_FULL) == ARM_DRIVER_OK) {
489     ret = EXIT_SUCCESS;
490   }
491
492   return ret;
493 }
494
495 /**
496   \fn            static int32_t USART_Com_PowerOff (void)
497   \brief         Power-down USART interface.
498   \return        execution status
499                    - EXIT_SUCCESS: Operation successful
500                    - EXIT_FAILURE: Operation failed
501 */
502 static int32_t USART_Com_PowerOff (void) {
503   int32_t ret;
504
505   ret = EXIT_FAILURE;
506
507   if (drvUSART->PowerControl(ARM_POWER_OFF) == ARM_DRIVER_OK) {
508     ret = EXIT_SUCCESS;
509   }
510
511   return ret;
512 }
513
514 /**
515   \fn            static int32_t USART_Com_Configure (const USART_COM_CONFIG_t *config)
516   \brief         Configure USART interface.
517   \param[in]     config      Pointer to structure containing USART interface configuration settings
518   \return        execution status
519                    - EXIT_SUCCESS: Operation successful
520                    - EXIT_FAILURE: Operation failed
521 */
522 static int32_t USART_Com_Configure (const USART_COM_CONFIG_t *config) {
523   int32_t ret;
524
525   ret = EXIT_FAILURE;
526
527   if (drvUSART->Control(config->mode                |
528                         config->data_bits           |
529                         config->parity              |
530                         config->stop_bits           |
531                         config->flow_control        |
532                         config->cpol                |
533                         config->cpha                |
534                         config->irda_pulse          |
535                         config->smartcard_clock     |
536                         config->smartcard_guard_time,
537                         config->baudrate            ) == ARM_DRIVER_OK) {
538     usart_bytes_per_item = 1U;
539     if (config->data_bits == ARM_USART_DATA_BITS_9) {
540       usart_bytes_per_item = 2U;
541     }
542     ret = EXIT_SUCCESS;
543   }
544   if (ret == EXIT_SUCCESS) {
545     if (drvUSART->Control(ARM_USART_CONTROL_RX, 1U) == ARM_DRIVER_OK) {
546       ret = EXIT_SUCCESS;
547     }
548   }
549   if (ret == EXIT_SUCCESS) {
550     if (drvUSART->Control(ARM_USART_CONTROL_TX, 1U) == ARM_DRIVER_OK) {
551       ret = EXIT_SUCCESS;
552     }
553   }
554
555   return ret;
556 }
557
558 /**
559   \fn            static int32_t USART_Com_Receive (void *data_in, uint32_t num, uint32_t timeout)
560   \brief         Receive data (command) over USART interface.
561   \param[out]    data_in     Pointer to memory where data will be received
562   \param[in]     num         Number of data items to be received
563   \param[in]     timeout     Timeout for reception (in ms)
564   \return        execution status
565                    - EXIT_SUCCESS: Operation successful
566                    - EXIT_FAILURE: Operation failed
567 */
568 static int32_t USART_Com_Receive (void *data_in, uint32_t num, uint32_t timeout) {
569    int32_t ret;
570   uint32_t flags;
571
572   ret = EXIT_FAILURE;
573
574   if (usart_server_thread_id != NULL) {
575     memset(data_in, (int32_t)'?', usart_bytes_per_item * num);
576     vioSetSignal (vioLED0, vioLEDon);
577     osThreadFlagsClear(0x7FFFFFFFU);
578     if (drvUSART->Control(ARM_USART_CONTROL_RX, 1U) == ARM_DRIVER_OK) {
579       if (drvUSART->Receive(data_in, num) == ARM_DRIVER_OK) {
580         if (timeout == osWaitForever) {   // Reception of next command
581           for (;;) {
582             flags = osThreadFlagsWait(USART_RECEIVE_EVENTS_MASK, osFlagsWaitAny, 1U);
583             if ((flags & 0x80000000U) != 0U) {    // If timeout
584               if (drvUSART->GetRxCount() != 0U) {
585                 // If something was received, wait and try to receive complete command
586                 flags = osThreadFlagsWait(USART_RECEIVE_EVENTS_MASK, osFlagsWaitAny, USART_SERVER_CMD_TIMEOUT);
587                 if ((flags & (0x80000000U | ARM_USART_EVENT_RECEIVE_COMPLETE)) == ARM_USART_EVENT_RECEIVE_COMPLETE) {
588                   // If completed event was signaled
589                   ret = EXIT_SUCCESS;
590                   break;
591                 } else {
592                   // In all other cases exit with failed status
593                   break;
594                 }
595               }
596             }
597           }
598         } else {                          // Reception during XFER
599           flags = osThreadFlagsWait(ARM_USART_EVENT_RECEIVE_COMPLETE, osFlagsWaitAny, timeout);
600           if ((flags & (0x80000000U | ARM_USART_EVENT_RECEIVE_COMPLETE)) == ARM_USART_EVENT_RECEIVE_COMPLETE) {
601             // If completed event was signaled
602             ret = EXIT_SUCCESS;
603           }
604         }
605         if (ret != EXIT_SUCCESS) {
606           // If receive was activated but failed to receive expected data then abort the reception
607           (void)drvUSART->Control(ARM_USART_ABORT_RECEIVE, 0U);
608         }
609       }
610       (void)drvUSART->Control(ARM_USART_CONTROL_RX, 0U);
611     }
612     vioSetSignal (vioLED0, vioLEDoff);
613   }
614
615   return ret;
616 }
617
618 /**
619   \fn            static int32_t USART_Com_Send (const void *data_out, uint32_t num, uint32_t timeout)
620   \brief         Send data (response) over USART interface.
621   \param[out]    data_out       Pointer to memory containing data to be sent
622   \param[in]     num            Number of data items to be sent
623   \param[in]     timeout        Timeout for send (in ms)
624   \return        execution status
625                    - EXIT_SUCCESS: Operation successful
626                    - EXIT_FAILURE: Operation failed
627 */
628 static int32_t USART_Com_Send (const void *data_out, uint32_t num, uint32_t timeout) {
629   uint32_t flags;
630    int32_t ret;
631   uint8_t  tcnt;
632
633   ret = EXIT_FAILURE;
634
635   if (usart_server_thread_id != NULL) {
636     vioSetSignal (vioLED1, vioLEDon);
637     osThreadFlagsClear(0x7FFFFFFFU);
638     if (drvUSART->Control(ARM_USART_CONTROL_TX, 1U) == ARM_DRIVER_OK) {
639       if (drvUSART->Send(data_out, num) == ARM_DRIVER_OK) {
640         if (drv_cap.event_tx_complete != 0U) {
641           // If ARM_USART_EVENT_TX_COMPLETE is supported, wait for it
642           flags = osThreadFlagsWait(ARM_USART_EVENT_TX_COMPLETE, osFlagsWaitAny, timeout);
643           if ((flags & (0x80000000U | ARM_USART_EVENT_TX_COMPLETE)) == ARM_USART_EVENT_TX_COMPLETE) {
644             // If completed event was signaled
645             ret = EXIT_SUCCESS;
646           }
647         } else {
648           // Otherwise wait for ARM_USART_EVENT_SEND_COMPLETE flag
649           flags = osThreadFlagsWait(ARM_USART_EVENT_SEND_COMPLETE, osFlagsWaitAny, timeout);
650           if ((flags & (0x80000000U | ARM_USART_EVENT_SEND_COMPLETE)) == ARM_USART_EVENT_SEND_COMPLETE) {
651             // Wait for data to be transmitted on the Tx wire, up to 10 ms.
652             // Send complete signals when data was consumed by FIFO not when it was actually 
653             // sent on the wire.
654             for (tcnt = 0U; tcnt < 10U; tcnt ++) {
655               if (drvUSART->GetStatus().tx_busy == 0U) {
656                 ret = EXIT_SUCCESS;
657                 break;
658               }
659               (void)osDelay(1U);
660             }
661           }
662         }
663         if (ret != EXIT_SUCCESS) {
664           // If send was activated but failed to send all of the expected data then abort the send
665           (void)drvUSART->Control(ARM_USART_ABORT_SEND, 0U);
666         }
667       }
668       (void)drvUSART->Control(ARM_USART_CONTROL_TX, 0U);
669     }
670     vioSetSignal (vioLED1, vioLEDoff);
671   }
672
673   return ret;
674 }
675
676 /**
677   \fn            static int32_t USART_Com_Transfer (const void *data_out, void *data_in, uint32_t num, uint32_t timeout)
678   \brief         Transfer (send/receive) data over USART interface.
679   \param[in]     data_out       Pointer to memory containing data to be sent
680   \param[out]    data_in        Pointer to memory where data will be received
681   \param[in]     num            Number of data items to be transferred
682   \param[in]     timeout        Timeout for transfer (in ms)
683   \return        execution status
684                    - EXIT_SUCCESS: Operation successful
685                    - EXIT_FAILURE: Operation failed
686 */
687 static int32_t USART_Com_Transfer (const void *data_out, void *data_in, uint32_t num, uint32_t timeout) {
688   uint32_t flags;
689    int32_t ret;
690
691   ret = EXIT_FAILURE;
692
693   if (usart_server_thread_id != NULL) {
694     vioSetSignal (vioLED2, vioLEDon);
695     osThreadFlagsClear(0x7FFFFFFFU);
696     if (drvUSART->Transfer(data_out, data_in, num) == ARM_DRIVER_OK) {
697       flags = osThreadFlagsWait(USART_TRANSFER_EVENTS_MASK, osFlagsWaitAny, timeout);
698       usart_xfer_cnt = drvUSART->GetTxCount();
699       vioSetSignal (vioLED2, vioLEDoff);
700       if ((flags & (0x80000000U | ARM_USART_EVENT_TRANSFER_COMPLETE)) == ARM_USART_EVENT_TRANSFER_COMPLETE) {
701         // If completed event was signaled
702         ret = EXIT_SUCCESS;
703       } else {
704         // If error or timeout
705         (void)drvUSART->Control(ARM_USART_ABORT_TRANSFER, 0U);
706       }
707     }
708   }
709
710   return ret;
711 }
712
713 /**
714   \fn            static int32_t USART_Com_Break (uint32_t val)
715   \brief         Control USART Break signaling.
716   \return        execution status
717                    - EXIT_SUCCESS: Operation successful
718                    - EXIT_FAILURE: Operation failed
719 */
720 static int32_t USART_Com_Break (uint32_t val) {
721   int32_t ret;
722
723   ret = EXIT_FAILURE;
724
725   if (drvUSART->Control(ARM_USART_CONTROL_BREAK, val) == ARM_DRIVER_OK) {
726     ret = EXIT_SUCCESS;
727   }
728
729   return ret;
730 }
731
732 /**
733   \fn            static int32_t USART_Com_SetModemControl (ARM_USART_MODEM_CONTROL control)
734   \brief         Set USART Modem Control line state.
735   \return        execution status
736                    - EXIT_SUCCESS: Operation successful
737                    - EXIT_FAILURE: Operation failed
738 */
739 static int32_t USART_Com_SetModemControl (ARM_USART_MODEM_CONTROL control) {
740   int32_t ret;
741
742   ret = EXIT_FAILURE;
743
744   if (drvUSART->SetModemControl(control) == ARM_DRIVER_OK) {
745     ret = EXIT_SUCCESS;
746   }
747
748   return ret;
749 }
750
751 /**
752   \fn            static int32_t USART_Com_Abort (void)
753   \brief         Abort current transfer on USART interface.
754   \return        execution status
755                    - EXIT_SUCCESS: Operation successful
756                    - EXIT_FAILURE: Operation failed
757 */
758 static int32_t USART_Com_Abort (void) {
759   int32_t ret;
760
761   ret = EXIT_FAILURE;
762
763   if (drvUSART->Control(ARM_USART_ABORT_TRANSFER, 0U) == ARM_DRIVER_OK) {
764     ret = EXIT_SUCCESS;
765   }
766
767   return ret;
768 }
769
770 /**
771   \fn            static uint32_t USART_Com_GetCnt (void)
772   \brief         Get number of data items transferred over USART interface in last transfer.
773   \return        number of data items transferred
774 */
775 static uint32_t USART_Com_GetCnt (void) {
776   return usart_xfer_cnt;
777 }
778
779
780 // Command handling functions
781
782 /**
783   \fn            static int32_t USART_Cmd_GetVer (const char *cmd)
784   \brief         Handle command "GET VER".
785   \detail        Return USART Server version over USART interface (16 bytes).
786   \param[in]     cmd            Pointer to null-terminated command string
787   \return        execution status
788                    - EXIT_SUCCESS: Operation successful
789                    - EXIT_FAILURE: Operation failed
790 */
791 static int32_t USART_Cmd_GetVer (const char *cmd) {
792
793   (void)cmd;
794
795   memset(usart_cmd_buf_tx, 0, 16);
796   memcpy(usart_cmd_buf_tx, USART_SERVER_VER, sizeof(USART_SERVER_VER));
797
798   (void)osDelay(10U);                   // Give client time to start the reception
799
800   return (USART_Com_Send(usart_cmd_buf_tx, BYTES_TO_ITEMS(16U, USART_SERVER_DATA_BITS), usart_cmd_timeout));
801 }
802
803 /**
804   \fn            static int32_t USART_Cmd_GetCap (const char *cmd)
805   \brief         Handle command "GET CAP".
806   \detail        Return USART Server capabilities over USART interface (32 bytes).
807   \param[in]     cmd            Pointer to null-terminated command string
808   \return        execution status
809                    - EXIT_SUCCESS: Operation successful
810                    - EXIT_FAILURE: Operation failed
811 */
812 static int32_t USART_Cmd_GetCap (const char *cmd) {
813   int32_t  ret;
814   uint32_t mode_mask, data_bits_mask, parity_mask, stop_bits_mask;
815   uint32_t flow_control_mask, modem_lines_mask, min_baudrate, max_baudrate;
816   uint32_t br, def_br;
817    int8_t  i;
818
819   // Disable Rx and Tx during capabilities detection
820   drvUSART->Control(ARM_USART_CONTROL_RX, 0U);
821   drvUSART->Control(ARM_USART_CONTROL_TX, 0U);
822
823   (void)cmd;
824
825   ret = EXIT_FAILURE;
826
827   def_br = usart_com_config_default.baudrate;
828
829   // Determine supported minimum baudrate
830   // Find minimum baudrate setting at which Control function succeeds
831   for (i = 0; i < (sizeof(usart_baudrates) / sizeof(uint32_t)); i++) {
832     if (drvUSART->Control(ARM_USART_MODE_ASYNCHRONOUS, usart_baudrates[i]) == ARM_DRIVER_OK) {
833       break;
834     }
835   }
836   if (i == (sizeof(usart_baudrates) / sizeof(uint32_t))) {
837     i -= 1;
838   }
839   min_baudrate = usart_baudrates[i];
840
841   // Determine supported maximum baudrate
842   // Find maximum baudrate setting at which Control function succeeds
843   for (i = ((sizeof(usart_baudrates) / sizeof(uint32_t))) - 1; i >= 0U; i--) {
844     if (drvUSART->Control(ARM_USART_MODE_ASYNCHRONOUS, usart_baudrates[i]) == ARM_DRIVER_OK) {
845       break;
846     }
847   }
848   if (i < 0) {
849     i = 0;
850   }
851   max_baudrate = usart_baudrates[i];
852
853   // Check baudrate values which are power of 10 for maximum supported baudrate
854   br = 100000000U;
855   do {
856     if (drvUSART->Control(ARM_USART_MODE_ASYNCHRONOUS, br) == ARM_DRIVER_OK) {
857       break;
858     }
859     if (drvUSART->Control(ARM_USART_MODE_ASYNCHRONOUS, br / 2U) == ARM_DRIVER_OK) {
860       br /= 2U;
861       break;
862     }
863     if (drvUSART->Control(ARM_USART_MODE_ASYNCHRONOUS, br / 5U) == ARM_DRIVER_OK) {
864       br /= 5U;
865       break;
866     }
867     br /= 10U;
868     if (drvUSART->Control(ARM_USART_MODE_ASYNCHRONOUS, br) == ARM_DRIVER_OK) {
869       break;
870     }
871   } while (br > 10000U);
872   if (br > max_baudrate) {
873     max_baudrate = br;
874   }
875
876   // Determine supported modes
877   mode_mask = 0U;
878   if (drv_cap.asynchronous != 0U) {
879     mode_mask |= 1U;
880   }
881   if (drv_cap.synchronous_master != 0U) {
882     mode_mask |= 1U << 1;
883   }
884   if (drv_cap.synchronous_slave != 0U) {
885     mode_mask |= 1U << 2;
886   }
887   if (drv_cap.single_wire != 0U) {
888     mode_mask |= 1U << 3;
889   }
890   if (drv_cap.irda != 0U) {
891     mode_mask |= 1U << 4;
892   }
893   if (drv_cap.smart_card != 0U) {
894     mode_mask |= 1U << 5;
895   }
896
897   // Determine supported data bits
898   data_bits_mask = 0U;
899   if (drvUSART->Control(ARM_USART_MODE_ASYNCHRONOUS | ARM_USART_DATA_BITS_5, def_br) == ARM_DRIVER_OK) {
900     data_bits_mask |= 1U;
901   }
902   if (drvUSART->Control(ARM_USART_MODE_ASYNCHRONOUS | ARM_USART_DATA_BITS_6, def_br) == ARM_DRIVER_OK) {
903     data_bits_mask |= 1U << 1;
904   }
905   if (drvUSART->Control(ARM_USART_MODE_ASYNCHRONOUS | ARM_USART_DATA_BITS_7, def_br) == ARM_DRIVER_OK) {
906     data_bits_mask |= 1U << 2;
907   }
908   if (drvUSART->Control(ARM_USART_MODE_ASYNCHRONOUS | ARM_USART_DATA_BITS_8, def_br) == ARM_DRIVER_OK) {
909     data_bits_mask |= 1U << 3;
910   }
911   if (drvUSART->Control(ARM_USART_MODE_ASYNCHRONOUS | ARM_USART_DATA_BITS_9, def_br) == ARM_DRIVER_OK) {
912     data_bits_mask |= 1U << 4;
913   }
914
915   // Determine supported parity options
916   parity_mask = 0U;
917   if (drvUSART->Control(ARM_USART_MODE_ASYNCHRONOUS | ARM_USART_PARITY_NONE, def_br) == ARM_DRIVER_OK) {
918     parity_mask |= 1U;
919   }
920   if (drvUSART->Control(ARM_USART_MODE_ASYNCHRONOUS | ARM_USART_PARITY_EVEN, def_br) == ARM_DRIVER_OK) {
921     parity_mask |= 1U << 1;
922   }
923   if (drvUSART->Control(ARM_USART_MODE_ASYNCHRONOUS | ARM_USART_PARITY_ODD,  def_br) == ARM_DRIVER_OK) {
924     parity_mask |= 1U << 2;
925   }
926
927   // Determine supported stop bits
928   stop_bits_mask = 0U;
929   if (drvUSART->Control(ARM_USART_MODE_ASYNCHRONOUS | ARM_USART_STOP_BITS_1,   def_br) == ARM_DRIVER_OK) {
930     stop_bits_mask |= 1U;
931   }
932   if (drvUSART->Control(ARM_USART_MODE_ASYNCHRONOUS | ARM_USART_STOP_BITS_2,   def_br) == ARM_DRIVER_OK) {
933     stop_bits_mask |= 1U << 1;
934   }
935   if (drvUSART->Control(ARM_USART_MODE_ASYNCHRONOUS | ARM_USART_STOP_BITS_1_5, def_br) == ARM_DRIVER_OK) {
936     stop_bits_mask |= 1U << 2;
937   }
938   if (drvUSART->Control(ARM_USART_MODE_ASYNCHRONOUS | ARM_USART_STOP_BITS_0_5, def_br) == ARM_DRIVER_OK) {
939     stop_bits_mask |= 1U << 3;
940   }
941
942   // Determine supported flow control options
943   flow_control_mask = 1U;       // No flow control is always supported
944   if ((drv_cap.cts != 0U) && (drv_cap.flow_control_cts != 0U)) {
945     flow_control_mask |= 1U << 1;
946   }
947   if (drv_cap.rts != 0U) {
948     flow_control_mask |= 1U << 2;
949   }
950   if ((drv_cap.rts != 0U) && (drv_cap.cts != 0U) && (drv_cap.flow_control_cts != 0U)) {
951     flow_control_mask |= 1U << 3;
952   }
953
954   // Determine available modem lines
955   modem_lines_mask = 0U;
956   if (drv_cap.rts != 0U) {
957     modem_lines_mask |= 1U;
958   }
959   if (drv_cap.cts != 0U) {
960     modem_lines_mask |= 1U << 1;
961   }
962   if (drv_cap.dtr != 0U) {
963     modem_lines_mask |= 1U << 2;
964   }
965   if (drv_cap.dsr != 0U) {
966     modem_lines_mask |= 1U << 3;
967   }
968   if ((dcd_ri_mask & 1U) != 0U) {
969     modem_lines_mask |= 1U << 4;
970   }
971   if ((dcd_ri_mask & 2U) != 0U) {
972     modem_lines_mask |= 1U << 5;
973   }
974
975   // Revert communication settings to default because they were changed during auto-detection of capabilities
976   (void)USART_Com_Configure(&usart_com_config_default);
977
978   (void)osDelay(25U);                   // Give client time to start the reception
979
980   memset(usart_cmd_buf_tx, 0, 32);
981   if (snprintf((char *)usart_cmd_buf_tx, 32, "%02X,%02X,%01X,%01X,%01X,%01X,%i,%i", 
982                 mode_mask, 
983                 data_bits_mask, 
984                 parity_mask, 
985                 stop_bits_mask, 
986                 flow_control_mask, 
987                 modem_lines_mask, 
988                 min_baudrate, 
989                 max_baudrate) <= 32) {
990     ret = USART_Com_Send(usart_cmd_buf_tx, BYTES_TO_ITEMS(32U, USART_SERVER_DATA_BITS), usart_cmd_timeout);
991   }
992
993   return ret;
994 }
995
996 /**
997   \fn            static int32_t USART_Cmd_SetBuf (const char *cmd)
998   \brief         Handle command "SET BUF RX/TX,len[,pattern]".
999   \detail        Initialize content of the buffer in the following way:
1000                   - fill whole buffer with 'pattern' value if it is specified, and 'len' is 0
1001                   - fill whole buffer with 0 if 'pattern' is not provided and 'len' is 0
1002                   - load 'len' bytes from start of the buffer with content 
1003                     received in IN data phase
1004   \param[in]     cmd            Pointer to null-terminated command string
1005   \return        execution status
1006                    - EXIT_SUCCESS: Operation successful
1007                    - EXIT_FAILURE: Operation failed
1008 */
1009 static int32_t USART_Cmd_SetBuf (const char *cmd) {
1010   const char     *ptr_str;
1011         uint8_t  *ptr_buf;
1012         uint32_t  val, len;
1013         uint8_t   pattern;
1014          int32_t  ret;
1015
1016   ret     = EXIT_SUCCESS;
1017   ptr_str = NULL;
1018   ptr_buf = NULL;
1019   val     = 0U;
1020   len     = 0U;
1021   pattern = 0U;
1022
1023   // Parse 'RX' or 'TX' selection
1024   if        (strstr(cmd, "RX") != NULL) {
1025     ptr_buf = ptr_usart_xfer_buf_rx;
1026   } else if (strstr(cmd, "TX") != NULL) {
1027     ptr_buf = ptr_usart_xfer_buf_tx;
1028   } else {
1029     ret = EXIT_FAILURE;
1030   }
1031
1032   if (ret == EXIT_SUCCESS) {
1033     // Parse 'len'
1034     ptr_str = strstr(cmd, ",");         // Find ','
1035     if (ptr_str != NULL) {              // If ',' was found
1036       ptr_str++;                        // Skip ','
1037       while (*ptr_str == ' ') {         // Skip whitespaces after ','
1038         ptr_str++;
1039       }
1040       if (sscanf(ptr_str, "%u", &val) == 1) {
1041         if (val <= usart_xfer_buf_size) {
1042           len = val;
1043         } else {
1044           ret = EXIT_FAILURE;
1045         }
1046       } else {
1047         ret = EXIT_FAILURE;
1048       }
1049     } else {
1050       ret = EXIT_FAILURE;
1051     }
1052   }
1053
1054   if ((ret == EXIT_SUCCESS) && (ptr_str != NULL)) {
1055     // Parse optional 'pattern'
1056     ptr_str = strstr(ptr_str, ",");     // Find ','
1057     if (ptr_str != NULL) {              // If ',' was found
1058       ptr_str++;                        // Skip ','
1059       while (*ptr_str == ' ') {         // Skip whitespaces after ','
1060         ptr_str++;
1061       }
1062       if (sscanf(ptr_str, "%x", &val) == 1) {
1063         pattern = (uint8_t)val;
1064       } else {
1065         ret = EXIT_FAILURE;
1066       }
1067     }
1068   }
1069
1070   if ((ret == EXIT_SUCCESS) && (ptr_buf != NULL)) {
1071     // Fill the whole buffer with 'pattern', if 'pattern' was not specified 
1072     // in the command then the whole buffer will be filled with 0
1073     memset(ptr_buf, (int32_t)pattern, usart_xfer_buf_size);
1074   }
1075
1076   if ((ret == EXIT_SUCCESS) && (ptr_buf != NULL) && (len != 0U)) {
1077     // Load 'len' bytes from start of buffer with content received in IN data phase
1078     ret = USART_Com_Receive(ptr_buf, BYTES_TO_ITEMS(len, USART_SERVER_DATA_BITS), usart_cmd_timeout);
1079   }
1080
1081   return ret;
1082 }
1083
1084 /**
1085   \fn            static int32_t USART_Cmd_GetBuf (const char *cmd)
1086   \brief         Handle command "GET BUF RX/TX,len".
1087   \detail        Send content of buffer over USART interface.
1088   \param[in]     cmd            Pointer to null-terminated command string
1089   \return        execution status
1090                    - EXIT_SUCCESS: Operation successful
1091                    - EXIT_FAILURE: Operation failed
1092 */
1093 static int32_t USART_Cmd_GetBuf (const char *cmd) {
1094   const char     *ptr_str;
1095   const uint8_t  *ptr_buf;
1096         uint32_t  val, len;
1097          int32_t  ret;
1098
1099   ret      = EXIT_SUCCESS;
1100   ptr_str  = NULL;
1101   ptr_buf  = NULL;
1102   val      = 0U;
1103   len      = 0U;
1104
1105   // Parse 'RX' or 'TX' selection
1106   if        (strstr(cmd, "RX") != NULL) {
1107     ptr_buf = ptr_usart_xfer_buf_rx;
1108   } else if (strstr(cmd, "TX") != NULL) {
1109     ptr_buf = ptr_usart_xfer_buf_tx;
1110   } else {
1111     ret = EXIT_FAILURE;
1112   }
1113
1114   if (ret == EXIT_SUCCESS) {
1115     // Parse 'len'
1116     ptr_str = strstr(cmd, ",");         // Find ','
1117     if (ptr_str != NULL) {              // If ',' was found
1118       ptr_str++;                        // Skip ','
1119       while (*ptr_str == ' ') {         // Skip whitespaces after ','
1120         ptr_str++;
1121       }
1122       if (sscanf(ptr_str, "%u", &val) == 1) {
1123         if ((val > 0U) && (val <= usart_xfer_buf_size)) {
1124           len = val;
1125         } else {
1126           ret = EXIT_FAILURE;
1127         }
1128       } else {
1129         ret = EXIT_FAILURE;
1130       }
1131     } else {
1132       ret = EXIT_FAILURE;
1133     }
1134   }
1135
1136   (void)osDelay(10U);                   // Give client time to start the reception
1137
1138   if ((ret == EXIT_SUCCESS) && (ptr_buf != NULL) && (len != 0U)) {
1139     ret = USART_Com_Send(ptr_buf, BYTES_TO_ITEMS(len, USART_SERVER_DATA_BITS), usart_cmd_timeout);
1140   }
1141
1142   return ret;
1143 }
1144
1145 /**
1146   \fn            static int32_t USART_Cmd_SetCom (const char *cmd)
1147   \brief         Handle command "SET COM mode,data_bits,parity,stop_bits,flow_ctrl,cpol,cpha,baudrate".
1148   \detail        Set communication configuration settings used for transfers (XFER commands).
1149   \param[in]     cmd            Pointer to null-terminated command string
1150   \return        execution status
1151                    - EXIT_SUCCESS: Operation successful
1152                    - EXIT_FAILURE: Operation failed
1153 */
1154 static int32_t USART_Cmd_SetCom (const char *cmd) {
1155   const char    *ptr_str;
1156         uint32_t val;
1157          int32_t ret;
1158
1159   ret = EXIT_SUCCESS;
1160   val = 0U;
1161
1162   ptr_str = &cmd[7];                    // Skip "SET COM"
1163   while (*ptr_str == ' ') {             // Skip whitespaces
1164     ptr_str++;
1165   }
1166
1167   // Parse 'mode'
1168   if (sscanf(ptr_str, "%u", &val) == 1) {
1169     switch (val) {
1170       case 1U:                          // Asynchronous mode
1171         usart_com_config_xfer.mode = ARM_USART_MODE_ASYNCHRONOUS;
1172         break;
1173       case 2U:                          // Synchronous Master mode
1174         usart_com_config_xfer.mode = ARM_USART_MODE_SYNCHRONOUS_MASTER;
1175         break;
1176       case 3U:                          // Synchronous Slave mode
1177         usart_com_config_xfer.mode = ARM_USART_MODE_SYNCHRONOUS_SLAVE;
1178         break;
1179       case 4U:                          // Single Wire mode
1180         usart_com_config_xfer.mode = ARM_USART_MODE_SINGLE_WIRE;
1181         break;
1182       case 5U:                          // IrDA mode
1183         usart_com_config_xfer.mode = ARM_USART_MODE_IRDA;
1184         break;
1185       case 6U:                          // Smart Card mode
1186         usart_com_config_xfer.mode = ARM_USART_MODE_SMART_CARD;
1187         break;
1188       default:
1189         ret = EXIT_FAILURE;
1190         break;
1191     }
1192   } else {
1193     ret = EXIT_FAILURE;
1194   }
1195
1196   if ((ret == EXIT_SUCCESS) && (ptr_str != NULL)) {
1197     // Parse 'data_bits'
1198     ptr_str = strstr(ptr_str, ",");     // Find ','
1199     if (ptr_str != NULL) {              // If ',' was found
1200       ptr_str++;                        // Skip ','
1201       while (*ptr_str == ' ') {         // Skip whitespaces after ','
1202         ptr_str++;
1203       }
1204       if (sscanf(ptr_str, "%u", &val) == 1) {
1205         switch (val) {
1206           case 5U:                      // 5 data bits
1207             usart_com_config_xfer.data_bits = ARM_USART_DATA_BITS_5;
1208             break;
1209           case 6U:                      // 6 data bits
1210             usart_com_config_xfer.data_bits = ARM_USART_DATA_BITS_6;
1211             break;
1212           case 7U:                      // 7 data bits
1213             usart_com_config_xfer.data_bits = ARM_USART_DATA_BITS_7;
1214             break;
1215           case 8U:                      // 8 data bits
1216             usart_com_config_xfer.data_bits = ARM_USART_DATA_BITS_8;
1217             break;
1218           case 9U:                      // 9 data bits
1219             usart_com_config_xfer.data_bits = ARM_USART_DATA_BITS_9;
1220             break;
1221           default:
1222             ret = EXIT_FAILURE;
1223             break;
1224         }
1225       } else {
1226         ret = EXIT_FAILURE;
1227       }
1228     }
1229   }
1230
1231   if ((ret == EXIT_SUCCESS) && (ptr_str != NULL)) {
1232     // Parse 'parity'
1233     ptr_str = strstr(ptr_str, ",");     // Find ','
1234     if (ptr_str != NULL) {              // If ',' was found
1235       ptr_str++;                        // Skip ','
1236       while (*ptr_str == ' ') {         // Skip whitespaces after ','
1237         ptr_str++;
1238       }
1239       if (sscanf(ptr_str, "%u", &val) == 1) {
1240         switch (val) {
1241           case 0U:                      // No parity
1242             usart_com_config_xfer.parity = ARM_USART_PARITY_NONE;
1243             break;
1244           case 1U:                      // Even parity
1245             usart_com_config_xfer.parity = ARM_USART_PARITY_EVEN;
1246             break;
1247           case 2U:                      // Odd parity
1248             usart_com_config_xfer.parity = ARM_USART_PARITY_ODD;
1249             break;
1250           default:
1251             ret = EXIT_FAILURE;
1252             break;
1253         }
1254       } else {
1255         ret = EXIT_FAILURE;
1256       }
1257     }
1258   }
1259
1260   if ((ret == EXIT_SUCCESS) && (ptr_str != NULL)) {
1261     // Parse 'stop_bits'
1262     ptr_str = strstr(ptr_str, ",");     // Find ','
1263     if (ptr_str != NULL) {              // If ',' was found
1264       ptr_str++;                        // Skip ','
1265       while (*ptr_str == ' ') {         // Skip whitespaces after ','
1266         ptr_str++;
1267       }
1268       if (sscanf(ptr_str, "%u", &val) == 1) {
1269         switch (val) {
1270           case 0U:                      // 1 stop bit
1271             usart_com_config_xfer.stop_bits = ARM_USART_STOP_BITS_1;
1272             break;
1273           case 1U:                      // 2 stop bits
1274             usart_com_config_xfer.stop_bits = ARM_USART_STOP_BITS_2;
1275             break;
1276           case 2U:                      // 1.5 stop bits
1277             usart_com_config_xfer.stop_bits = ARM_USART_STOP_BITS_1_5;
1278             break;
1279           case 3U:                      // 0.5 stop bits
1280             usart_com_config_xfer.stop_bits = ARM_USART_STOP_BITS_0_5;
1281             break;
1282           default:
1283             ret = EXIT_FAILURE;
1284             break;
1285         }
1286       } else {
1287         ret = EXIT_FAILURE;
1288       }
1289     }
1290   }
1291
1292   if ((ret == EXIT_SUCCESS) && (ptr_str != NULL)) {
1293     // Parse 'flow_ctrl'
1294     ptr_str = strstr(ptr_str, ",");     // Find ','
1295     if (ptr_str != NULL) {              // If ',' was found
1296       ptr_str++;                        // Skip ','
1297       while (*ptr_str == ' ') {         // Skip whitespaces after ','
1298         ptr_str++;
1299       }
1300       if (sscanf(ptr_str, "%u", &val) == 1) {
1301         switch (val) {
1302           case 0U:                      // No flow control
1303             usart_com_config_xfer.flow_control = ARM_USART_FLOW_CONTROL_NONE;
1304             break;
1305           case 1U:                      // RTS
1306             usart_com_config_xfer.flow_control = ARM_USART_FLOW_CONTROL_RTS;
1307             break;
1308           case 2U:                      // CTS
1309             usart_com_config_xfer.flow_control = ARM_USART_FLOW_CONTROL_CTS;
1310             break;
1311           case 3U:                      // RTS/CTS
1312             usart_com_config_xfer.flow_control = ARM_USART_FLOW_CONTROL_RTS_CTS;
1313             break;
1314           default:
1315             ret = EXIT_FAILURE;
1316             break;
1317         }
1318       } else {
1319         ret = EXIT_FAILURE;
1320       }
1321     }
1322   }
1323
1324   if ((ret == EXIT_SUCCESS) && (ptr_str != NULL)) {
1325     // Parse 'cpol'
1326     ptr_str = strstr(ptr_str, ",");     // Find ','
1327     if (ptr_str != NULL) {              // If ',' was found
1328       ptr_str++;                        // Skip ','
1329       while (*ptr_str == ' ') {         // Skip whitespaces after ','
1330         ptr_str++;
1331       }
1332       if (sscanf(ptr_str, "%u", &val) == 1) {
1333         switch (val) {
1334           case 0U:                      // Data are captured on rising edge
1335             usart_com_config_xfer.cpol = ARM_USART_CPOL0;
1336             break;
1337           case 1U:                      // Data are captured on falling edge
1338             usart_com_config_xfer.cpol = ARM_USART_CPOL1;
1339             break;
1340           default:
1341             ret = EXIT_FAILURE;
1342             break;
1343         }
1344       } else {
1345         ret = EXIT_FAILURE;
1346       }
1347     }
1348   }
1349
1350   if ((ret == EXIT_SUCCESS) && (ptr_str != NULL)) {
1351     // Parse 'cpha'
1352     ptr_str = strstr(ptr_str, ",");     // Find ','
1353     if (ptr_str != NULL) {              // If ',' was found
1354       ptr_str++;                        // Skip ','
1355       while (*ptr_str == ' ') {         // Skip whitespaces after ','
1356         ptr_str++;
1357       }
1358       if (sscanf(ptr_str, "%u", &val) == 1) {
1359         switch (val) {
1360           case 0U:                      // Sample on first (leading) edge
1361             usart_com_config_xfer.cpha = ARM_USART_CPHA0;
1362             break;
1363           case 1U:                      // Sample on second (trailing) edge
1364             usart_com_config_xfer.cpha = ARM_USART_CPHA1;
1365             break;
1366           default:
1367             ret = EXIT_FAILURE;
1368             break;
1369         }
1370       } else {
1371         ret = EXIT_FAILURE;
1372       }
1373     }
1374   }
1375
1376   if ((ret == EXIT_SUCCESS) && (ptr_str != NULL)) {
1377     // Parse 'baudrate'
1378     ptr_str = strstr(ptr_str, ",");     // Find ','
1379     if (ptr_str != NULL) {              // If ',' was found
1380       ptr_str++;                        // Skip ','
1381       while (*ptr_str == ' ') {         // Skip whitespaces after ','
1382         ptr_str++;
1383       }
1384       if (sscanf(ptr_str, "%u", &val) == 1) {
1385         usart_com_config_xfer.baudrate = val;
1386       } else {
1387         ret = EXIT_FAILURE;
1388       }
1389     }
1390   }
1391
1392   return ret;
1393 }
1394
1395 /**
1396   \fn            static int32_t USART_Cmd_Xfer (const char *cmd)
1397   \brief         Handle command "XFER dir,num[,delay][,timeout][,num_rts]".
1398   \detail        Send data from USART TX buffer if dir = 0, receive data to USART RX buffer 
1399                  if dir = 1, or do both if dir = 2.
1400                  (buffers must be set with "SET BUF" command before this command).
1401                  Transfer start is delayed by optional parameter 'delay' in milliseconds.
1402   \param[in]     cmd            Pointer to null-terminated command string
1403   \return        execution status
1404                    - EXIT_SUCCESS: Operation successful
1405                    - EXIT_FAILURE: Operation failed
1406 */
1407 static int32_t USART_Cmd_Xfer (const char *cmd) {
1408   const char    *ptr_str;
1409         uint32_t val, dir, num, delay, num_rts;
1410          int32_t ret;
1411         uint8_t  num_rts_provided;
1412
1413   ret              = EXIT_SUCCESS;
1414   val              = 0U;
1415   dir              = 0U;
1416   num              = 0U;
1417   delay            = 0U;
1418   num_rts          = 0U;
1419   num_rts_provided = 0U;
1420
1421   ptr_str = &cmd[4];                    // Skip "XFER"
1422   while (*ptr_str == ' ') {             // Skip whitespaces
1423     ptr_str++;
1424   }
1425
1426   // Parse 'dir'
1427   if (sscanf(ptr_str, "%u", &val) == 1) {
1428     if ((val >= 0U) && (val <= 2U)) {
1429       dir = val;
1430     } else {
1431       ret = EXIT_FAILURE;
1432     }
1433   } else {
1434     ret = EXIT_FAILURE;
1435   }
1436
1437   if ((ret == EXIT_SUCCESS) && (ptr_str != NULL)) {
1438     // Parse 'num'
1439     ptr_str = strstr(ptr_str, ",");     // Find ','
1440     if (ptr_str != NULL) {              // If ',' was found
1441       ptr_str++;                        // Skip ','
1442       while (*ptr_str == ' ') {         // Skip whitespaces after ','
1443         ptr_str++;
1444       }
1445       if (sscanf(ptr_str, "%u", &val) == 1) {
1446         if ((val > 0U) && (val <= usart_xfer_buf_size)) {
1447           num = val;
1448         } else {
1449           ret = EXIT_FAILURE;
1450         }
1451       } else {
1452         ret = EXIT_FAILURE;
1453       }
1454     } else {
1455       ret = EXIT_FAILURE;
1456     }
1457   }
1458
1459   if ((ret == EXIT_SUCCESS) && (ptr_str != NULL)) {
1460     // Parse optional 'delay'
1461     ptr_str = strstr(ptr_str, ",");     // Find ','
1462     if (ptr_str != NULL) {              // If ',' was found
1463       ptr_str++;                        // Skip ','
1464       while (*ptr_str == ' ') {         // Skip whitespaces after ','
1465         ptr_str++;
1466       }
1467       if (sscanf(ptr_str, "%u", &val) == 1) {
1468         if (val != osWaitForever) {
1469           delay = val;
1470         } else {
1471           ret = EXIT_FAILURE;
1472         }
1473       } else {
1474         ret = EXIT_FAILURE;
1475       }
1476     }
1477   }
1478
1479   if ((ret == EXIT_SUCCESS) && (ptr_str != NULL)) {
1480     // Parse optional 'timeout'
1481     ptr_str = strstr(ptr_str, ",");     // Find ','
1482     if (ptr_str != NULL) {              // If ',' was found
1483       ptr_str++;                        // Skip ','
1484       while (*ptr_str == ' ') {         // Skip whitespaces after ','
1485         ptr_str++;
1486       }
1487       if (sscanf(ptr_str, "%u", &val) == 1) {
1488         if (val != osWaitForever) {
1489           usart_xfer_timeout = val;
1490         } else {
1491           ret = EXIT_FAILURE;
1492         }
1493       } else {
1494         ret = EXIT_FAILURE;
1495       }
1496     }
1497   }
1498
1499   if ((ret == EXIT_SUCCESS) && (ptr_str != NULL)) {
1500     // Parse optional 'num_rts'
1501     ptr_str = strstr(ptr_str, ",");     // Find ','
1502     if (ptr_str != NULL) {              // If ',' was found
1503       ptr_str++;                        // Skip ','
1504       while (*ptr_str == ' ') {         // Skip whitespaces after ','
1505         ptr_str++;
1506       }
1507       if (sscanf(ptr_str, "%u", &val) == 1) {
1508         if (val <= num) {
1509           num_rts = val;
1510           num_rts_provided = 1U;
1511         } else {
1512           ret = EXIT_FAILURE;
1513         }
1514       } else {
1515         ret = EXIT_FAILURE;
1516       }
1517     }
1518   }
1519
1520   if ((ret == EXIT_SUCCESS) && (delay != 0U)) {
1521     (void)osDelay(delay);
1522   }
1523
1524   if (ret == EXIT_SUCCESS) {
1525     // Configure communication settings before transfer
1526     ret = USART_Com_Configure(&usart_com_config_xfer);
1527
1528     if (ret == EXIT_SUCCESS) {
1529       switch (dir) {
1530         case 0U:                        // Send
1531           ret = USART_Com_Send(ptr_usart_xfer_buf_tx, num, usart_xfer_timeout);
1532           usart_xfer_cnt = drvUSART->GetTxCount();
1533           break;
1534         case 1U:                        // Receive
1535           if (num_rts_provided == 0U) { // Normal Receive
1536             ret = USART_Com_Receive(ptr_usart_xfer_buf_rx, num, usart_xfer_timeout);
1537             usart_xfer_cnt = drvUSART->GetRxCount();
1538           } else {                      // Special handling for activation of Server's RTS line => Client's CTS line
1539             USART_Com_SetModemControl(ARM_USART_RTS_SET);
1540             ret = USART_Com_Receive(ptr_usart_xfer_buf_rx, num_rts, (usart_xfer_timeout * num_rts) / num);
1541             usart_xfer_cnt  = drvUSART->GetRxCount();
1542             USART_Com_SetModemControl(ARM_USART_RTS_CLEAR);
1543
1544             USART_Com_Receive(ptr_usart_xfer_buf_rx + num_rts, num - num_rts, (usart_xfer_timeout * (num - num_rts)) / num);
1545             usart_xfer_cnt += drvUSART->GetRxCount();
1546           }
1547           break;
1548         case 2U:                        // Transfer
1549           ret = USART_Com_Transfer(ptr_usart_xfer_buf_tx, ptr_usart_xfer_buf_rx, num, usart_xfer_timeout);
1550           usart_xfer_cnt = drvUSART->GetRxCount();
1551           break;
1552         default:
1553           ret = EXIT_FAILURE;
1554           break;
1555       }
1556     }
1557   }
1558
1559   // Revert communication settings to default
1560   (void)USART_Com_Configure(&usart_com_config_default);
1561
1562   return ret;
1563 }
1564
1565 /**
1566   \fn            static int32_t USART_Cmd_GetCnt (const char *cmd)
1567   \brief         Handle command "GET CNT".
1568   \detail        Return number of items transferred (sent/received/transferred) in last transfer 
1569                  (requested by last XFER command).
1570   \param[in]     cmd            Pointer to null-terminated command string
1571   \return        execution status
1572                    - EXIT_SUCCESS: Operation successful
1573                    - EXIT_FAILURE: Operation failed
1574 */
1575 static int32_t USART_Cmd_GetCnt (const char *cmd) {
1576   int32_t ret;
1577
1578   (void)cmd;
1579
1580   ret = EXIT_FAILURE;
1581
1582   (void)osDelay(10U);                   // Give client time to start the reception
1583
1584   memset(usart_cmd_buf_tx, 0, 16);
1585   if (snprintf((char *)usart_cmd_buf_tx, 16, "%u", USART_Com_GetCnt()) < 16) {
1586     ret = USART_Com_Send(usart_cmd_buf_tx, BYTES_TO_ITEMS(16U, USART_SERVER_DATA_BITS), usart_cmd_timeout);
1587   }
1588
1589   return ret;
1590 }
1591
1592 /**
1593   \fn            static int32_t USART_Cmd_SetBrk (const char *cmd)
1594   \brief         Handle command "SET BRK delay,duration".
1595   \detail        Control break signal.
1596                  After specified delay time activate break signal 
1597                  and hold it for specified duration.
1598   \param[in]     cmd            Pointer to null-terminated command string
1599   \return        execution status
1600                    - EXIT_SUCCESS: Operation successful
1601                    - EXIT_FAILURE: Operation failed
1602 */
1603 static int32_t USART_Cmd_SetBrk (const char *cmd) {
1604   const char    *ptr_str;
1605         uint32_t val, delay, duration;
1606          int32_t ret;
1607
1608   ret      = EXIT_SUCCESS;
1609   val      = 0U;
1610   delay    = 0U;
1611   duration = 0U;
1612
1613   ptr_str = &cmd[7];                    // Skip "SET BRK"
1614   while (*ptr_str == ' ') {             // Skip whitespaces
1615     ptr_str++;
1616   }
1617
1618   // Parse 'delay'
1619   if (sscanf(ptr_str, "%u", &val) == 1) {
1620     if (val != osWaitForever) {
1621       delay = val;
1622     } else {
1623       ret = EXIT_FAILURE;
1624     }
1625   } else {
1626     ret = EXIT_FAILURE;
1627   }
1628
1629   if ((ret == EXIT_SUCCESS) && (ptr_str != NULL)) {
1630     // Parse 'duration'
1631     ptr_str = strstr(ptr_str, ",");     // Find ','
1632     if (ptr_str != NULL) {              // If ',' was found
1633       ptr_str++;                        // Skip ','
1634       while (*ptr_str == ' ') {         // Skip whitespaces after ','
1635         ptr_str++;
1636       }
1637       if (sscanf(ptr_str, "%u", &val) == 1) {
1638         if (val != osWaitForever) {
1639           duration = val;
1640         } else {
1641           ret = EXIT_FAILURE;
1642         }
1643       } else {
1644         ret = EXIT_FAILURE;
1645       }
1646     }
1647   }
1648
1649   if ((ret == EXIT_SUCCESS) && (delay != 0U)) {
1650     (void)osDelay(delay);
1651   }
1652
1653   if (ret == EXIT_SUCCESS) {
1654     ret = USART_Com_Configure(&usart_com_config_default);
1655   }
1656
1657   if (ret == EXIT_SUCCESS) {
1658     ret = USART_Com_Break(1U);
1659   }
1660
1661   if ((ret == EXIT_SUCCESS) && (duration != 0U)) {
1662     (void)osDelay(duration);
1663   }
1664
1665   USART_Com_Break(0U);
1666
1667   return ret;
1668 }
1669
1670 /**
1671   \fn            static int32_t USART_Cmd_GetBrk (const char *cmd)
1672   \brief         Handle command "GET BRK".
1673   \detail        Return break status. Status is updated upon break event and cleared 
1674                  after this command is executed.
1675   \param[in]     cmd            Pointer to null-terminated command string
1676   \return        execution status
1677                    - EXIT_SUCCESS: Operation successful
1678                    - EXIT_FAILURE: Operation failed
1679 */
1680 static int32_t USART_Cmd_GetBrk (const char *cmd) {
1681   int32_t ret;
1682
1683   (void)cmd;
1684
1685   ret = EXIT_FAILURE;
1686
1687   usart_cmd_buf_tx[0] = '0' + break_status;
1688   break_status = 0U;
1689
1690   (void)osDelay(10U);                   // Give client time to start the reception
1691
1692   ret = USART_Com_Send(usart_cmd_buf_tx, 1U, usart_cmd_timeout);
1693
1694   return ret;
1695 }
1696
1697 /**
1698   \fn            static int32_t USART_Cmd_SetMdm (const char *cmd)
1699   \brief         Handle command "SET MDM mdm_ctrl,delay,duration".
1700   \detail        Control modem lines.
1701                  After specified delay time activate requested line states 
1702                  and hold it for specified duration.
1703   \param[in]     cmd            Pointer to null-terminated command string
1704   \return        execution status
1705                    - EXIT_SUCCESS: Operation successful
1706                    - EXIT_FAILURE: Operation failed
1707 */
1708 static int32_t USART_Cmd_SetMdm (const char *cmd) {
1709   const char    *ptr_str;
1710         uint32_t val, mdm_ctrl, delay, duration, control;
1711          int32_t ret;
1712
1713   ret      = EXIT_SUCCESS;
1714   val      = 0U;
1715   mdm_ctrl = 0U;
1716   delay    = 0U;
1717   duration = 0U;
1718   control  = 0U;
1719
1720   ptr_str = &cmd[7];                    // Skip "SET MDM"
1721   while (*ptr_str == ' ') {             // Skip whitespaces
1722     ptr_str++;
1723   }
1724
1725   // Parse 'mdm_ctrl'
1726   if (sscanf(ptr_str, "%x", &val) == 1) {
1727     mdm_ctrl = val;
1728   } else {
1729     ret = EXIT_FAILURE;
1730   }
1731
1732   if ((ret == EXIT_SUCCESS) && (ptr_str != NULL)) {
1733     // Parse 'delay'
1734     ptr_str = strstr(ptr_str, ",");     // Find ','
1735     if (ptr_str != NULL) {              // If ',' was found
1736       ptr_str++;                        // Skip ','
1737       while (*ptr_str == ' ') {         // Skip whitespaces after ','
1738         ptr_str++;
1739       }
1740       if (sscanf(ptr_str, "%u", &val) == 1) {
1741         if (val != osWaitForever) {
1742           delay = val;
1743         } else {
1744           ret = EXIT_FAILURE;
1745         }
1746       } else {
1747         ret = EXIT_FAILURE;
1748       }
1749     } else {
1750       ret = EXIT_FAILURE;
1751     }
1752   }
1753
1754   if ((ret == EXIT_SUCCESS) && (ptr_str != NULL)) {
1755     // Parse 'duration'
1756     ptr_str = strstr(ptr_str, ",");     // Find ','
1757     if (ptr_str != NULL) {              // If ',' was found
1758       ptr_str++;                        // Skip ','
1759       while (*ptr_str == ' ') {         // Skip whitespaces after ','
1760         ptr_str++;
1761       }
1762       if (sscanf(ptr_str, "%u", &val) == 1) {
1763         if (val != osWaitForever) {
1764           duration = val;
1765         } else {
1766           ret = EXIT_FAILURE;
1767         }
1768       } else {
1769         ret = EXIT_FAILURE;
1770       }
1771     }
1772   }
1773
1774   if (ret == EXIT_SUCCESS) {
1775     // Deactivate all lines initially
1776     if (drv_cap.rts == 1U) {
1777       (void)USART_Com_SetModemControl(ARM_USART_RTS_CLEAR);
1778     }
1779     if (drv_cap.dtr == 1U) {
1780       (void)USART_Com_SetModemControl(ARM_USART_DTR_CLEAR);
1781     }
1782     USART_Server_Pin_DCD_SetState(0U);
1783     USART_Server_Pin_RI_SetState (0U);
1784
1785     if (delay != 0U) {
1786       (void)osDelay(delay);
1787     }
1788   }
1789
1790   // Lower 4 bits are same as in USART ARM_USART_MODEM_CONTROL
1791   // bit 0. = RTS state
1792   // bit 1. = DTR state
1793   // bit 2. = DCD state
1794   // bit 3. = RI  state
1795   if (ret == EXIT_SUCCESS) {
1796     if (drv_cap.rts == 1U) {
1797       if ((mdm_ctrl & (1U     )) != 0U) {
1798         ret = USART_Com_SetModemControl(ARM_USART_RTS_SET);
1799       } else {
1800         ret = USART_Com_SetModemControl(ARM_USART_RTS_CLEAR);
1801       }
1802     }
1803   }
1804   if (ret == EXIT_SUCCESS) {
1805     if (drv_cap.dtr == 1U) {
1806       if ((mdm_ctrl & (1U << 1)) != 0U) {
1807         ret = USART_Com_SetModemControl(ARM_USART_DTR_SET);
1808       } else {
1809         ret = USART_Com_SetModemControl(ARM_USART_DTR_CLEAR);
1810       }
1811     }
1812   }
1813
1814   if (ret == EXIT_SUCCESS) {
1815     if ((mdm_ctrl >> 2) & 1) {
1816       // If pin to DCD should be set to active state
1817       USART_Server_Pin_DCD_SetState(1U);
1818     }
1819     if ((mdm_ctrl >> 3) & 1) {
1820       // If pin to RI should be set to active state
1821       USART_Server_Pin_RI_SetState(1U);
1822     }
1823
1824     if (duration != 0U) {
1825       (void)osDelay(duration);
1826     }
1827   }
1828
1829   if (drv_cap.rts == 1U) {
1830     (void)USART_Com_SetModemControl(ARM_USART_RTS_CLEAR);
1831   }
1832   if (drv_cap.dtr == 1U) {
1833     (void)USART_Com_SetModemControl(ARM_USART_DTR_CLEAR);
1834   }
1835   USART_Server_Pin_DCD_SetState(0U);
1836   USART_Server_Pin_RI_SetState (0U);
1837
1838   return ret;
1839 }
1840
1841 /**
1842   \fn            static int32_t USART_Cmd_GetMdm (const char *cmd)
1843   \brief         Handle command "GET MDM".
1844   \detail        Return modem lines current status.
1845   \param[in]     cmd            Pointer to null-terminated command string
1846   \return        execution status
1847                    - EXIT_SUCCESS: Operation successful
1848                    - EXIT_FAILURE: Operation failed
1849 */
1850 static int32_t USART_Cmd_GetMdm (const char *cmd) {
1851   int32_t                ret;
1852   ARM_USART_MODEM_STATUS val;
1853
1854   (void)cmd;
1855
1856   ret = EXIT_FAILURE;
1857
1858   val = drvUSART->GetModemStatus();
1859
1860   usart_cmd_buf_tx[0] = '0' + (val.cts) + (2U * val.dsr);
1861
1862   (void)osDelay(10U);                   // Give client time to start the reception
1863
1864   ret = USART_Com_Send(usart_cmd_buf_tx, 1U, usart_cmd_timeout);
1865
1866   return ret;
1867 }