1 /*
2 * Trace Recorder for Tracealyzer v4.10.3
3 * Copyright 2023 Percepio AB
4 * www.percepio.com
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 *
8 * Supporting functions for trace streaming, used by the "stream ports"
9 * for reading and writing data to the interface.
10 * Existing ports can easily be modified to fit another setup, e.g., a
11 * different UDP stack, or to define your own stream port.
12 */
13
14 #include <trcRecorder.h>
15
16 #if (TRC_USE_TRACEALYZER_RECORDER == 1)
17
18 #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
19
20 /* udp includes - for lwIP in this case */
21 #include <lwip/sockets.h>
22 #include <lwip/errno.h>
23
24 int sock = -1;
25 int remoteSize;
26 struct sockaddr_in address_out;
27
28 typedef struct TraceStreamPortUDP
29 {
30 #if (TRC_USE_INTERNAL_BUFFER)
31 uint8_t buffer[(TRC_ALIGNED_STREAM_PORT_BUFFER_SIZE)];
32 #else
33 TraceUnsignedBaseType_t buffer[1];
34 #endif
35 } TraceStreamPortUDP_t;
36
37 static TraceStreamPortUDP_t* pxStreamPortUDP TRC_CFG_RECORDER_DATA_ATTRIBUTE;
38
39 static int32_t prvSocketSend(void* pvData, uint32_t uiSize, int32_t* piBytesWritten);
40 static int32_t prvSocketReceive(void* pvData, uint32_t uiSize, int32_t* piBytesRead);
41 static int32_t prvSocketInitialize(void);
42
prvSocketSend(void * pvData,uint32_t uiSize,int32_t * piBytesWritten)43 static int32_t prvSocketSend( void* pvData, uint32_t uiSize, int32_t* piBytesWritten )
44 {
45 if (sock < 0)
46 {
47 return -1;
48 }
49
50 if (piBytesWritten == (void*)0)
51 {
52 return -1;
53 }
54
55 *piBytesWritten = sendto( sock, pvData, uiSize, 0, (struct sockaddr *)&address_out, sizeof(address_out) );
56
57 if (*piBytesWritten < 0)
58 {
59 *piBytesWritten = 0;
60
61 /* EWOULDBLOCK may be expected when buffers are full */
62 if (errno != EWOULDBLOCK)
63 {
64 close(sock);
65 sock = -1;
66 return -1;
67 }
68 }
69
70 return 0;
71 }
72
prvSocketReceive(void * pvData,uint32_t uiSize,int32_t * piBytesRead)73 static int32_t prvSocketReceive( void* pvData, uint32_t uiSize, int32_t* piBytesRead )
74 {
75 if (sock < 0)
76 return -1;
77
78 if (piBytesRead == (void*)0)
79 return -1;
80
81 *piBytesRead = recv( sock, pvData, uiSize, 0 );
82
83 if (*piBytesRead < 0)
84 {
85 *piBytesRead = 0;
86
87 /* EWOULDBLOCK may be expected when there is no pvData to receive */
88 if (errno != EWOULDBLOCK)
89 {
90 close(sock);
91 sock = -1;
92 return -1;
93 }
94 }
95
96 return 0;
97 }
98
prvSocketInitialize(void)99 static int32_t prvSocketInitialize(void)
100 {
101 int flags = 0;
102 struct sockaddr_in address_in;
103
104 if (sock >= 0)
105 {
106 return 0;
107 }
108
109 sock = socket(AF_INET, SOCK_DGRAM, 0);
110
111 if (sock < 0)
112 {
113 return -1;
114 }
115
116 address_in.sin_family = AF_INET;
117 address_in.sin_port = htons(TRC_CFG_STREAM_PORT_UDP_PORT);
118 address_in.sin_addr.s_addr = INADDR_ANY;
119
120 if (bind(sock, (struct sockaddr*)&address_in, sizeof(address_in)) != 0)
121 {
122 close(sock);
123 sock = -1;
124 return -1;
125 }
126
127 flags = fcntl( sock, F_GETFL, 0 );
128 fcntl( sock, F_SETFL, flags | O_NONBLOCK );
129
130 address_out.sin_family = AF_INET;
131 address_out.sin_port = htons(TRC_CFG_STREAM_PORT_UDP_PORT);
132 address_out.sin_addr.s_addr = inet_addr(TRC_CFG_STREAM_PORT_UDP_ADDRESS);
133
134 return 0;
135 }
136
137 /************** MODIFY THE ABOVE PART TO USE YOUR UDP STACK ****************/
138
prvTraceUdpWrite(void * pvData,uint32_t uiSize,int32_t * piBytesWritten)139 int32_t prvTraceUdpWrite(void* pvData, uint32_t uiSize, int32_t *piBytesWritten)
140 {
141 prvSocketInitialize();
142
143 return prvSocketSend(pvData, uiSize, piBytesWritten);
144 }
145
prvTraceUdpRead(void * pvData,uint32_t uiSize,int32_t * piBytesRead)146 int32_t prvTraceUdpRead(void* pvData, uint32_t uiSize, int32_t *piBytesRead)
147 {
148 prvSocketInitialize();
149
150 return prvSocketReceive(pvData, uiSize, piBytesRead);
151 }
152
xTraceStreamPortInitialize(TraceStreamPortBuffer_t * pxBuffer)153 traceResult xTraceStreamPortInitialize(TraceStreamPortBuffer_t* pxBuffer)
154 {
155 TRC_ASSERT_EQUAL_SIZE(TraceStreamPortBuffer_t, TraceStreamPortUDP_t);
156
157 if (pxBuffer == 0)
158 {
159 return TRC_FAIL;
160 }
161
162 pxStreamPortUDP = (TraceStreamPortUDP_t*)pxBuffer;
163
164 #if (TRC_USE_INTERNAL_BUFFER == 1)
165 return xTraceInternalEventBufferInitialize(pxStreamPortUDP->buffer, sizeof(pxStreamPortUDP->buffer));
166 #else
167 return TRC_SUCCESS;
168 #endif
169 }
170
xTraceStreamPortOnTraceEnd(void)171 traceResult xTraceStreamPortOnTraceEnd(void)
172 {
173 if (sock >= 0)
174 {
175 close(sock);
176 }
177
178 return TRC_SUCCESS;
179 }
180
181 #endif /*(TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)*/
182
183 #endif /*(TRC_USE_TRACEALYZER_RECORDER == 1)*/
184