1 /*
2  * Copyright 2019 NXP
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include "fsl_common.h"
9 #include "fsl_component_serial_manager.h"
10 #include "fsl_component_serial_port_internal.h"
11 
12 #if (defined(SERIAL_PORT_TYPE_VIRTUAL) && (SERIAL_PORT_TYPE_VIRTUAL > 0U))
13 
14 #include "fsl_component_serial_port_virtual.h"
15 
16 /*******************************************************************************
17  * Definitions
18  ******************************************************************************/
19 
20 #ifndef NDEBUG
21 #if (defined(DEBUG_CONSOLE_ASSERT_DISABLE) && (DEBUG_CONSOLE_ASSERT_DISABLE > 0U))
22 #undef assert
23 #define assert(n)
24 #else
25 /* MISRA C-2012 Rule 17.2 */
26 #undef assert
27 #define assert(n) \
28     while (!(n))  \
29     {             \
30         ;         \
31     }
32 #endif
33 #endif
34 
35 /* Weak function. */
36 #if defined(__GNUC__)
37 #define __WEAK_FUNC __attribute__((weak))
38 #elif defined(__ICCARM__)
39 #define __WEAK_FUNC __weak
40 #elif defined(__CC_ARM) || defined(__ARMCC_VERSION)
41 #define __WEAK_FUNC __attribute__((weak))
42 #endif
43 
44 typedef struct _serial_port_virtual_send_state
45 {
46     serial_manager_callback_t callback;
47     void *callbackParam;
48 } serial_port_virtual_send_state_t;
49 
50 typedef struct _serial_port_virtual_recv_state
51 {
52     serial_manager_callback_t callback;
53     void *callbackParam;
54 } serial_port_virtual_recv_state_t;
55 
56 /* Define the types for application */
57 typedef struct _serial_port_virtual_state
58 {
59     struct _serial_port_virtual_state *next; /* Next pointer of the interface */
60     serial_port_virtual_send_state_t tx;
61     serial_port_virtual_recv_state_t rx;
62     uint8_t instance; /* The instance of the interface */
63 } serial_port_virtual_state_t;
64 
65 /*******************************************************************************
66  * Prototypes
67  ******************************************************************************/
68 
69 /*******************************************************************************
70  * Variables
71  ******************************************************************************/
72 
73 static serial_port_virtual_state_t *s_serialPortVirtualHead;
74 
75 /*******************************************************************************
76  * Code
77  ******************************************************************************/
78 
Serial_PortVirtualAddItem(serial_port_virtual_state_t ** head,serial_port_virtual_state_t * node)79 static serial_manager_status_t Serial_PortVirtualAddItem(serial_port_virtual_state_t **head,
80                                                          serial_port_virtual_state_t *node)
81 {
82     serial_port_virtual_state_t *p = *head;
83     uint32_t regPrimask;
84 
85     regPrimask = DisableGlobalIRQ();
86 
87     if (NULL == p)
88     {
89         *head = node;
90     }
91     else
92     {
93         while (NULL != p->next)
94         {
95             if (p == node)
96             {
97                 EnableGlobalIRQ(regPrimask);
98                 return kStatus_SerialManager_Error;
99             }
100             p = p->next;
101         }
102 
103         p->next = node;
104     }
105     node->next = NULL;
106     EnableGlobalIRQ(regPrimask);
107     return kStatus_SerialManager_Success;
108 }
109 
Serial_PortVirtualRemoveItem(serial_port_virtual_state_t ** head,serial_port_virtual_state_t * node)110 static serial_manager_status_t Serial_PortVirtualRemoveItem(serial_port_virtual_state_t **head,
111                                                             serial_port_virtual_state_t *node)
112 {
113     serial_port_virtual_state_t *p = *head;
114     serial_port_virtual_state_t *q = NULL;
115     uint32_t regPrimask;
116 
117     regPrimask = DisableGlobalIRQ();
118     while (NULL != p)
119     {
120         if (p == node)
121         {
122             if (NULL == q)
123             {
124                 *head = p->next;
125             }
126             else
127             {
128                 q->next = p->next;
129             }
130             break;
131         }
132         else
133         {
134             q = p;
135             p = p->next;
136         }
137     }
138     EnableGlobalIRQ(regPrimask);
139     return kStatus_SerialManager_Success;
140 }
141 
Serial_PortVirtualGetInstance(uint8_t controller,serial_port_virtual_state_t ** handle)142 static serial_manager_status_t Serial_PortVirtualGetInstance(uint8_t controller, serial_port_virtual_state_t **handle)
143 {
144     serial_port_virtual_state_t *p = s_serialPortVirtualHead;
145     uint32_t regPrimask;
146 
147     *handle    = NULL;
148     regPrimask = DisableGlobalIRQ();
149     while (NULL != p)
150     {
151         if (p->instance == controller)
152         {
153             *handle = p;
154             break;
155         }
156     }
157     EnableGlobalIRQ(regPrimask);
158     return (NULL != p) ? kStatus_SerialManager_Success : kStatus_SerialManager_Error;
159 }
160 
Serial_PortVirtualTxCallback(void * callbackParam,serial_manager_callback_message_t * message,serial_manager_status_t status)161 static void Serial_PortVirtualTxCallback(void *callbackParam,
162                                          serial_manager_callback_message_t *message,
163                                          serial_manager_status_t status)
164 {
165     serial_port_virtual_state_t *serialPortVirtual;
166 
167     if (NULL != callbackParam)
168     {
169         serialPortVirtual = (serial_port_virtual_state_t *)callbackParam;
170         if (NULL != serialPortVirtual->tx.callback)
171         {
172             serialPortVirtual->tx.callback(serialPortVirtual->tx.callbackParam, message, status);
173         }
174     }
175 }
176 
Serial_PortVirtualRxCallback(void * callbackParam,serial_manager_callback_message_t * message,serial_manager_status_t status)177 static void Serial_PortVirtualRxCallback(void *callbackParam,
178                                          serial_manager_callback_message_t *message,
179                                          serial_manager_status_t status)
180 {
181     serial_port_virtual_state_t *serialPortVirtual;
182 
183     if (NULL != callbackParam)
184     {
185         serialPortVirtual = (serial_port_virtual_state_t *)callbackParam;
186         if (NULL != serialPortVirtual->rx.callback)
187         {
188             serialPortVirtual->rx.callback(serialPortVirtual->rx.callbackParam, message, status);
189         }
190     }
191 }
192 
193 __WEAK_FUNC status_t USB_DeviceVcomInit(uint8_t controller);
USB_DeviceVcomInit(uint8_t controller)194 __WEAK_FUNC status_t USB_DeviceVcomInit(uint8_t controller)
195 {
196     return kStatus_Success;
197 }
198 
199 __WEAK_FUNC status_t USB_DeviceVcomDeinit(uint8_t controller);
USB_DeviceVcomDeinit(uint8_t controller)200 __WEAK_FUNC status_t USB_DeviceVcomDeinit(uint8_t controller)
201 {
202     return kStatus_Success;
203 }
204 
205 __WEAK_FUNC status_t USB_DeviceVcomWrite(uint8_t controller, uint8_t *buffer, uint32_t length);
USB_DeviceVcomWrite(uint8_t controller,uint8_t * buffer,uint32_t length)206 __WEAK_FUNC status_t USB_DeviceVcomWrite(uint8_t controller, uint8_t *buffer, uint32_t length)
207 {
208     serial_port_virtual_state_t *serialPortVirtual;
209     serial_manager_callback_message_t msg;
210 
211     if (kStatus_SerialManager_Success != Serial_PortVirtualGetInstance(controller, &serialPortVirtual))
212     {
213         return kStatus_Fail;
214     }
215 
216     if ((NULL != serialPortVirtual->tx.callback))
217     {
218         msg.buffer = buffer;
219         msg.length = length;
220         serialPortVirtual->tx.callback(serialPortVirtual->tx.callbackParam, &msg, kStatus_SerialManager_Success);
221     }
222     return kStatus_Success;
223 }
224 
225 __WEAK_FUNC status_t USB_DeviceVcomRead(uint8_t controller, uint8_t *buffer, uint32_t length);
USB_DeviceVcomRead(uint8_t controller,uint8_t * buffer,uint32_t length)226 __WEAK_FUNC status_t USB_DeviceVcomRead(uint8_t controller, uint8_t *buffer, uint32_t length)
227 {
228     return kStatus_Fail;
229 }
230 
231 __WEAK_FUNC status_t USB_DeviceVcomCancelWrite(uint8_t controller);
USB_DeviceVcomCancelWrite(uint8_t controller)232 __WEAK_FUNC status_t USB_DeviceVcomCancelWrite(uint8_t controller)
233 {
234     return kStatus_Success;
235 }
236 
237 __WEAK_FUNC status_t USB_DeviceVcomInstallTxCallback(uint8_t controller,
238                                                      serial_manager_callback_t callback,
239                                                      void *callbackParam);
USB_DeviceVcomInstallTxCallback(uint8_t controller,serial_manager_callback_t callback,void * callbackParam)240 __WEAK_FUNC status_t USB_DeviceVcomInstallTxCallback(uint8_t controller,
241                                                      serial_manager_callback_t callback,
242                                                      void *callbackParam)
243 {
244     return kStatus_Success;
245 }
246 
247 __WEAK_FUNC status_t USB_DeviceVcomInstallRxCallback(uint8_t controller,
248                                                      serial_manager_callback_t callback,
249                                                      void *callbackParam);
USB_DeviceVcomInstallRxCallback(uint8_t controller,serial_manager_callback_t callback,void * callbackParam)250 __WEAK_FUNC status_t USB_DeviceVcomInstallRxCallback(uint8_t controller,
251                                                      serial_manager_callback_t callback,
252                                                      void *callbackParam)
253 {
254     return kStatus_Success;
255 }
256 
257 __WEAK_FUNC void USB_DeviceVcomIsrFunction(uint8_t controller);
USB_DeviceVcomIsrFunction(uint8_t controller)258 __WEAK_FUNC void USB_DeviceVcomIsrFunction(uint8_t controller)
259 {
260 }
261 
Serial_PortVirtualInit(serial_handle_t serialHandle,void * config)262 serial_manager_status_t Serial_PortVirtualInit(serial_handle_t serialHandle, void *config)
263 {
264     serial_port_virtual_state_t *serialPortVirtual;
265     serial_port_virtual_config_t *serialPortVirtualConfig;
266     serial_manager_status_t ret;
267 
268     assert(NULL != config);
269     assert(NULL != serialHandle);
270     assert(SERIAL_PORT_VIRTUAL_HANDLE_SIZE >= sizeof(serial_port_virtual_state_t));
271 
272     serialPortVirtual       = (serial_port_virtual_state_t *)serialHandle;
273     serialPortVirtualConfig = (serial_port_virtual_config_t *)config;
274 
275     serialPortVirtual->instance = (uint8_t)serialPortVirtualConfig->controllerIndex;
276 
277     if ((status_t)kStatus_Success != USB_DeviceVcomInit((uint8_t)serialPortVirtualConfig->controllerIndex))
278     {
279         return kStatus_SerialManager_Error;
280     }
281 
282     ret = Serial_PortVirtualAddItem(&s_serialPortVirtualHead, serialPortVirtual);
283 
284     if (kStatus_SerialManager_Success != ret)
285     {
286         return ret;
287     }
288 
289     return kStatus_SerialManager_Success;
290 }
291 
Serial_PortVirtualDeinit(serial_handle_t serialHandle)292 serial_manager_status_t Serial_PortVirtualDeinit(serial_handle_t serialHandle)
293 {
294     serial_port_virtual_state_t *serialPortVirtual;
295 
296     assert(serialHandle);
297 
298     serialPortVirtual = (serial_port_virtual_state_t *)serialHandle;
299 
300     (void)USB_DeviceVcomDeinit(serialPortVirtual->instance);
301 
302     (void)Serial_PortVirtualRemoveItem(&s_serialPortVirtualHead, serialPortVirtual);
303 
304     return kStatus_SerialManager_Success;
305 }
306 
Serial_PortVirtualWrite(serial_handle_t serialHandle,uint8_t * buffer,uint32_t length)307 serial_manager_status_t Serial_PortVirtualWrite(serial_handle_t serialHandle, uint8_t *buffer, uint32_t length)
308 {
309     serial_port_virtual_state_t *serialPortVirtual;
310 
311     assert(serialHandle);
312 
313     serialPortVirtual = (serial_port_virtual_state_t *)serialHandle;
314 
315     if (kStatus_Success != USB_DeviceVcomWrite(serialPortVirtual->instance, buffer, length))
316     {
317         return kStatus_SerialManager_Error;
318     }
319 
320     return kStatus_SerialManager_Success;
321 }
322 
Serial_PortVirtualRead(serial_handle_t serialHandle,uint8_t * buffer,uint32_t length)323 serial_manager_status_t Serial_PortVirtualRead(serial_handle_t serialHandle, uint8_t *buffer, uint32_t length)
324 {
325     serial_port_virtual_state_t *serialPortVirtual;
326 
327     assert(serialHandle);
328 
329     serialPortVirtual = (serial_port_virtual_state_t *)serialHandle;
330 
331     if (kStatus_Success != USB_DeviceVcomRead(serialPortVirtual->instance, buffer, length))
332     {
333         return kStatus_SerialManager_Error;
334     }
335 
336     return kStatus_SerialManager_Success;
337 }
338 
Serial_PortVirtualCancelWrite(serial_handle_t serialHandle)339 serial_manager_status_t Serial_PortVirtualCancelWrite(serial_handle_t serialHandle)
340 {
341     serial_port_virtual_state_t *serialPortVirtual;
342 
343     assert(serialHandle);
344 
345     serialPortVirtual = (serial_port_virtual_state_t *)serialHandle;
346 
347     if (kStatus_Success != USB_DeviceVcomCancelWrite(serialPortVirtual->instance))
348     {
349         return kStatus_SerialManager_Error;
350     }
351 
352     return kStatus_SerialManager_Success;
353 }
354 
Serial_PortVirtualInstallTxCallback(serial_handle_t serialHandle,serial_manager_callback_t callback,void * callbackParam)355 serial_manager_status_t Serial_PortVirtualInstallTxCallback(serial_handle_t serialHandle,
356                                                             serial_manager_callback_t callback,
357                                                             void *callbackParam)
358 {
359     serial_port_virtual_state_t *serialPortVirtual;
360 
361     assert(serialHandle);
362 
363     serialPortVirtual = (serial_port_virtual_state_t *)serialHandle;
364 
365     serialPortVirtual->tx.callback      = callback;
366     serialPortVirtual->tx.callbackParam = callbackParam;
367 
368     return (serial_manager_status_t)USB_DeviceVcomInstallTxCallback(serialPortVirtual->instance,
369                                                                     Serial_PortVirtualTxCallback, serialHandle);
370 }
371 
Serial_PortVirtualInstallRxCallback(serial_handle_t serialHandle,serial_manager_callback_t callback,void * callbackParam)372 serial_manager_status_t Serial_PortVirtualInstallRxCallback(serial_handle_t serialHandle,
373                                                             serial_manager_callback_t callback,
374                                                             void *callbackParam)
375 {
376     serial_port_virtual_state_t *serialPortVirtual;
377 
378     assert(serialHandle);
379 
380     serialPortVirtual = (serial_port_virtual_state_t *)serialHandle;
381 
382     serialPortVirtual->rx.callback      = callback;
383     serialPortVirtual->rx.callbackParam = callbackParam;
384 
385     return (serial_manager_status_t)USB_DeviceVcomInstallRxCallback(serialPortVirtual->instance,
386                                                                     Serial_PortVirtualRxCallback, serialHandle);
387 }
388 
Serial_PortVirtualIsrFunction(serial_handle_t serialHandle)389 void Serial_PortVirtualIsrFunction(serial_handle_t serialHandle)
390 {
391     serial_port_virtual_state_t *serialPortVirtual;
392 
393     assert(serialHandle);
394 
395     serialPortVirtual = (serial_port_virtual_state_t *)serialHandle;
396 
397     USB_DeviceVcomIsrFunction(serialPortVirtual->instance);
398 }
399 
400 #endif /* SERIAL_PORT_TYPE_VIRTUAL */
401