2 * Copyright (c) 2016-2017, The OpenThread Authors.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. Neither the name of the copyright holder nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
31 * This file implements the OpenThread platform abstraction for cli over ip socket communication.
35 #include "alarm_qorvo.h"
36 #include "platform_qorvo.h"
37 #include "uart_qorvo.h"
51 #include <netinet/in.h>
52 #include <netinet/tcp.h>
53 #include <sys/socket.h>
54 #include <sys/types.h>
58 #include <openthread/config.h>
60 #include <common/code_utils.hpp>
61 #include <openthread/platform/uart.h>
63 #include "utils/code_utils.h"
65 #define BUFFER_MAX_SIZE 255
66 #define SOCKET_PORT 9190
67 #define SOCKET_WRITE(socketInfo, buf, length) \
68 sendto(socketInfo.socketId, (const char *)buf, length, 0, &socketInfo.addr, sizeof(socketInfo.addr))
69 #define SOCKET_READ(socketId, buf, length) recv(socketId, buf, length, 0)
76 pthread_t rfReadThread;
79 PlatSocket_t PlatSocketConnection;
80 int PlatSocketPipeFd[2];
81 int PlatServerSocketId;
83 void PlatSocketRxNewConn(uint8_t id);
84 void PlatSocketInit(void);
85 void PlatSocketDeInit(void);
86 int PlatSocketTxData(uint16_t length, uint8_t *pData, uint32_t socketId);
88 #define PLAT_UART_MAX_CHAR 1024
90 uint32_t PlatSocketId = 0;
92 void PlatSocketSendInput(void *buffer)
95 uint8_t *buf = (uint8_t *)buffer;
96 len = strlen((char *)buf);
97 otPlatUartReceived((uint8_t *)buf, (uint16_t)len);
103 void PlatSocketRx(uint16_t length, const char *buffer, uint32_t socketId)
106 PlatSocketId = socketId;
110 buf = malloc(length + 2);
111 memcpy(buf, buffer, length);
114 qorvoAlarmScheduleEventArg(0, PlatSocketSendInput, (void *)buf);
118 void PlatSocketClose(uint32_t socketId)
120 OT_UNUSED_VARIABLE(socketId);
123 otError otPlatUartEnable(void)
126 return OT_ERROR_NONE;
129 otError otPlatUartDisable(void)
132 return OT_ERROR_NONE;
135 otError otPlatUartSend(const uint8_t *aBuf, uint16_t aBufLength)
137 otError error = OT_ERROR_NONE;
138 char localbuf[PLAT_UART_MAX_CHAR];
140 memcpy(localbuf, aBuf, aBufLength);
141 localbuf[aBufLength] = 0;
142 printf("%s", localbuf);
146 PlatSocketTxData(aBufLength, (uint8_t *)aBuf, PlatSocketId);
149 otPlatUartSendDone();
153 otError otPlatUartFlush(void)
155 return OT_ERROR_NOT_IMPLEMENTED;
158 void platformUartInit(void)
162 void platformUartProcess(void)
166 int PlatSocketListenForClients()
168 // Setup server side socket
170 struct sockaddr_in serv_addr;
174 sockfd = socket(AF_INET, SOCK_STREAM, 0);
175 otEXPECT_ACTION(sockfd >= 0, sockfd = -1);
177 // disable Nagle's algorithm to avoid long latency
178 setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(flag));
179 // allow reuse of the same address
180 setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *)&flag, sizeof(flag));
181 memset(&serv_addr, 0, sizeof(serv_addr));
183 serv_addr.sin_addr.s_addr = INADDR_ANY;
184 serv_addr.sin_family = AF_INET;
185 serv_addr.sin_port = htons(SOCKET_PORT);
186 ret = bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));
187 otEXPECT_ACTION(ret >= 0, close(sockfd); sockfd = -1);
188 ret = listen(sockfd, 10);
189 otEXPECT_ACTION(ret != -1, exit(1));
194 void PlatSocketRxSignaled(uint8_t id)
196 OT_UNUSED_VARIABLE(id);
198 // Dummy callback function to flush pipe
200 // Remove trigger byte from pipe
201 read(PlatSocketPipeFd[0], &readChar, 1);
204 void *PlatSocketReadThread(void *pClientSocket)
206 char buffer[BUFFER_MAX_SIZE];
207 PlatSocket_t *clientSocket = ((PlatSocket_t *)pClientSocket);
209 memset(buffer, 0, BUFFER_MAX_SIZE);
213 int readLen = SOCKET_READ(clientSocket->socketId, buffer, BUFFER_MAX_SIZE);
217 perror("Reading socket");
228 uint8_t someByte = 0x12; // No functional use only using pipe to kick main thread
230 PlatSocketRx(readLen, buffer, clientSocket->socketId);
232 write(PlatSocketPipeFd[1], &someByte, 1); //[1] = write fd
237 clientSocket->isValid = 0;
238 qorvoPlatUnRegisterPollFunction(clientSocket->socketId);
239 close(clientSocket->socketId);
241 PlatSocketClose(clientSocket->socketId);
246 void PlatSocketRxNewConn(uint8_t id)
248 // Find first non-valid client in list - add here
249 if (PlatSocketConnection.isValid == 0)
251 // Add new client to client list
253 len = sizeof(PlatSocketConnection.addr);
254 int retval = accept(id, (struct sockaddr *)&PlatSocketConnection.addr, (socklen_t *)&len);
259 PlatSocketConnection.socketId = retval;
261 pthread_create(&PlatSocketConnection.rfReadThread, NULL, PlatSocketReadThread, &PlatSocketConnection);
265 close(PlatSocketConnection.socketId);
269 PlatSocketConnection.isValid = 1;
276 tempfd = accept(id, (struct sockaddr *)NULL, NULL);
285 /*****************************************************************************
286 * Public Function Definitions
287 *****************************************************************************/
289 void PlatSocketInit(void)
291 memset(&PlatSocketConnection, 0, sizeof(PlatSocketConnection));
293 // in case we are a server, setup listening for client
294 PlatServerSocketId = PlatSocketListenForClients();
295 qorvoPlatRegisterPollFunction(PlatServerSocketId, PlatSocketRxNewConn);
298 pipe(PlatSocketPipeFd);
299 qorvoPlatRegisterPollFunction(PlatSocketPipeFd[0], PlatSocketRxSignaled);
302 void platformUartRestore(void)
307 void PlatSocketDeInit(void)
309 qorvoPlatUnRegisterPollFunction(PlatServerSocketId);
310 close(PlatServerSocketId);
311 qorvoPlatUnRegisterPollFunction(PlatSocketPipeFd[0]);
312 close(PlatSocketPipeFd[0]);
313 close(PlatSocketPipeFd[1]);
314 close(PlatSocketConnection.socketId);
317 int PlatSocketTxData(uint16_t length, uint8_t *pData, uint32_t socketId)
322 if (PlatSocketConnection.isValid)
324 if (PlatSocketConnection.socketId == socketId)
326 if (SOCKET_WRITE(PlatSocketConnection, (const char *)pData, length) < 0)
328 perror("TxSocket: Error Writing to client");
329 close(PlatSocketConnection.socketId);
330 PlatSocketConnection.isValid = 0;