SimpleLink CC3120/CC3220 Host Driver  Version 2.0.1.22
Simplifies the implementation of Internet connectivity
sl_socket.c
1 /*
2  * sl_socket.c - CC31xx/CC32xx Host Driver Implementation
3  *
4  * Copyright (C) 2017 Texas Instruments Incorporated - https://www.ti.com/
5  *
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  *
14  * Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in the
16  * documentation and/or other materials provided with the
17  * distribution.
18  *
19  * Neither the name of Texas Instruments Incorporated nor the names of
20  * its contributors may be used to endorse or promote products derived
21  * from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34  *
35 */
36 
37 
38 
39 /*****************************************************************************/
40 /* Include files */
41 /*****************************************************************************/
42 #include <ti/drivers/net/wifi/simplelink.h>
43 #include <ti/drivers/net/wifi/source/protocol.h>
44 #include <ti/drivers/net/wifi/source/driver.h>
45 
46 static void _SlSocketBuildAddress(const SlSockAddr_t *addr, SlSocketAddrCommand_u *pCmd);
47 _SlReturnVal_t _SlSocketHandleAsync_Connect(void *pVoidBuf);
48 _SlReturnVal_t _SlSocketHandleAsync_Close(void *pVoidBuf);
49 
50 #ifndef SL_TINY
51 void _SlSocketParseAddress(SlSocketAddrResponse_u *pRsp, SlSockAddr_t *addr, SlSocklen_t *addrlen);
52 _SlReturnVal_t _SlSocketHandleAsync_Accept(void *pVoidBuf);
53 _SlReturnVal_t _SlSocketHandleAsync_Select(void *pVoidBuf);
54 #if (defined(SL_PLATFORM_MULTI_THREADED) && !defined(slcb_SocketTriggerEventHandler))
55 static _i16 _SlDrvClearCtrlSocket(void);
56 static _i8 _SlDrvGetNextTimeoutValue(void);
57 #endif
58 #endif
59 
60 /*******************************************************************************/
61 /* Functions */
62 /*******************************************************************************/
63 
64 
65 
66 
67 
68 /* ******************************************************************************/
69 /* _SlSocketBuildAddress */
70 /* ******************************************************************************/
71 static void _SlSocketBuildAddress(const SlSockAddr_t *addr, SlSocketAddrCommand_u *pCmd)
72 {
73 
74  /* Note: parsing of family and port in the generic way for all IPV4, IPV6 and EUI48
75  is possible as long as these parameters are in the same offset and size for these
76  three families. */
77  pCmd->IpV4.FamilyAndFlags = (_u8)((addr->sa_family << 4) & 0xF0);
78  pCmd->IpV4.Port = ((SlSockAddrIn_t *)addr)->sin_port;
79 
80  if(SL_AF_INET == addr->sa_family)
81  {
82  pCmd->IpV4.Address = ((SlSockAddrIn_t *)addr)->sin_addr.s_addr;
83  }
84 #ifdef SL_SUPPORT_IPV6
85  else
86  {
87  sl_Memcpy(pCmd->IpV6.Address, ((SlSockAddrIn6_t *)addr)->sin6_addr._S6_un._S6_u32, 16 );
88  }
89 #endif
90 }
91 
92 
93 /*******************************************************************************/
94 /* _SlSocketParseAddress */
95 /*******************************************************************************/
96 
97 #ifndef SL_TINY
98 void _SlSocketParseAddress(SlSocketAddrResponse_u *pRsp, SlSockAddr_t *addr, SlSocklen_t *addrlen)
99 {
100  /* Note: parsing of family and port in the generic way for all IPV4, IPV6 and EUI48 */
101  /* is possible as long as these parameters are in the same offset and size for these */
102  /* three families. */
103  addr->sa_family = pRsp->IpV4.Family;
104  ((SlSockAddrIn_t *)addr)->sin_port = pRsp->IpV4.Port;
105 
106  *addrlen = (SL_AF_INET == addr->sa_family) ? sizeof(SlSockAddrIn_t) : sizeof(SlSockAddrIn6_t);
107 
108  if(SL_AF_INET == addr->sa_family)
109  {
110  ((SlSockAddrIn_t *)addr)->sin_addr.s_addr = pRsp->IpV4.Address;
111  }
112 #ifdef SL_SUPPORT_IPV6
113  else
114  {
115  sl_Memcpy(((SlSockAddrIn6_t *)addr)->sin6_addr._S6_un._S6_u32, pRsp->IpV6.Address, 16);
116  }
117 #endif
118 }
119 
120 #endif
121 
122 /*******************************************************************************/
123 /* sl_Socket */
124 /*******************************************************************************/
125 typedef union
126 {
127  _u32 Dummy;
128  SlSocketCommand_t Cmd;
129  SlSocketResponse_t Rsp;
130 }_SlSockSocketMsg_u;
131 
132 
133 
134 #if _SL_INCLUDE_FUNC(sl_Socket)
135 
136 static const _SlCmdCtrl_t _SlSockSocketCmdCtrl =
137 {
138  SL_OPCODE_SOCKET_SOCKET,
139  (_SlArgSize_t)sizeof(SlSocketCommand_t),
140  (_SlArgSize_t)sizeof(SlSocketResponse_t)
141 };
142 
143 _i16 sl_Socket(_i16 Domain, _i16 Type, _i16 Protocol)
144 {
145  _SlSockSocketMsg_u Msg;
146 
147  Msg.Cmd.Domain = (_u8)Domain;
148  Msg.Cmd.Type = (_u8)Type;
149  Msg.Cmd.Protocol = (_u8)Protocol;
150 
151  /* verify that this api is allowed. if not allowed then
152  ignore the API execution and return immediately with an error */
153  VERIFY_API_ALLOWED(SL_OPCODE_SILO_SOCKET);
154 
155  VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlSockSocketCmdCtrl, &Msg, NULL));
156 
157  if( Msg.Rsp.StatusOrLen < 0 )
158  {
159  return ( Msg.Rsp.StatusOrLen);
160  }
161  else
162  {
163  return (_i16)((_u8)Msg.Rsp.Sd);
164  }
165 }
166 #endif
167 
168 /*******************************************************************************/
169 /* sl_Close */
170 /*******************************************************************************/
171 typedef union
172 {
173  SlCloseCommand_t Cmd;
174  SlSocketResponse_t Rsp;
175 }_SlSockCloseMsg_u;
176 
177 
178 #if _SL_INCLUDE_FUNC(sl_Close)
179 
180 static const _SlCmdCtrl_t _SlSockCloseCmdCtrl =
181 {
182  SL_OPCODE_SOCKET_CLOSE,
183  (_SlArgSize_t)sizeof(SlCloseCommand_t),
184  (_SlArgSize_t)sizeof(SlSocketResponse_t)
185 };
186 
187 _i16 sl_Close(_i16 sd)
188 {
189  _SlSockCloseMsg_u Msg;
190  _u8 ObjIdx = MAX_CONCURRENT_ACTIONS;
191  SlSocketResponse_t AsyncRsp;
192  _SlReturnVal_t RetVal;
193  _u8 bSocketInAction = FALSE;
194 
195  /* verify that this api is allowed. if not allowed then
196  ignore the API execution and return immediately with an error */
197  VERIFY_API_ALLOWED(SL_OPCODE_SILO_SOCKET);
198 
199  Msg.Cmd.Sd = (_u8)sd;
200  _SlDrvMemZero(&AsyncRsp, sizeof(SlSocketResponse_t));
201 
202  /* check if the socket has already action in progress */
203  bSocketInAction = !!(g_pCB->ActiveActionsBitmap & (1<<sd));
204 
205  if (bSocketInAction == FALSE)
206  {
207  ObjIdx = _SlDrvProtectAsyncRespSetting((_u8*)&AsyncRsp, CLOSE_ID, (_u8)(sd & SL_BSD_SOCKET_ID_MASK));
208 
209  if (MAX_CONCURRENT_ACTIONS == ObjIdx)
210  {
211  return SL_POOL_IS_EMPTY;
212  }
213  }
214 
215  VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlSockCloseCmdCtrl, &Msg, NULL));
216 
217  RetVal = Msg.Rsp.StatusOrLen;
218 
219  if (bSocketInAction == FALSE)
220  {
221  if( SL_RET_CODE_OK == RetVal)
222  {
223  SL_DRV_SYNC_OBJ_WAIT_TIMEOUT(&g_pCB->ObjPool[ObjIdx].SyncObj,
224  SL_DRIVER_TIMEOUT_LONG,
225  SL_OPCODE_SOCKET_SOCKETCLOSEASYNCEVENT
226  );
227  RetVal = AsyncRsp.StatusOrLen;
228  }
229 
230  _SlDrvReleasePoolObj(ObjIdx);
231  }
232 
233  return RetVal;
234 }
235 #endif
236 
237 /*******************************************************************************/
238 /* sl_Bind */
239 /*******************************************************************************/
240 typedef union
241 {
243  SlSocketResponse_t Rsp;
244 }_SlSockBindMsg_u;
245 
246 #if _SL_INCLUDE_FUNC(sl_Bind)
247 _i16 sl_Bind(_i16 sd, const SlSockAddr_t *addr, _i16 addrlen)
248 {
249  _SlSockBindMsg_u Msg;
250  _SlCmdCtrl_t CmdCtrl = {0, 0, (_SlArgSize_t)sizeof(SlSocketResponse_t)};
251 
252  /* verify that this api is allowed. if not allowed then
253  ignore the API execution and return immediately with an error */
254  VERIFY_API_ALLOWED(SL_OPCODE_SILO_SOCKET);
255 
256  switch(addr->sa_family)
257  {
258  case SL_AF_INET :
259  CmdCtrl.Opcode = SL_OPCODE_SOCKET_BIND;
260  CmdCtrl.TxDescLen = (_SlArgSize_t)sizeof(SlSocketAddrIPv4Command_t);
261  break;
262 #ifndef SL_TINY
263 #ifdef SL_SUPPORT_IPV6
264  case SL_AF_INET6:
265  CmdCtrl.Opcode = SL_OPCODE_SOCKET_BIND_V6;
266  CmdCtrl.TxDescLen = (_SlArgSize_t)sizeof(SlSocketAddrIPv6Command_t);
267  break;
268 #endif
269 #endif
270 
271  case SL_AF_RF :
272  default:
273  return SL_RET_CODE_INVALID_INPUT;
274  }
275 
276  Msg.Cmd.IpV4.LenOrPadding = 0;
277  Msg.Cmd.IpV4.Sd = (_u8)sd;
278 
279  _SlSocketBuildAddress(addr, &Msg.Cmd);
280  VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&CmdCtrl, &Msg, NULL));
281 
282  return Msg.Rsp.StatusOrLen;
283 }
284 #endif
285 
286 /*******************************************************************************/
287 /* sl_Sendto */
288 /*******************************************************************************/
289 typedef union
290 {
292  /* no response for 'sendto' commands*/
293 }_SlSendtoMsg_u;
294 
295 #if _SL_INCLUDE_FUNC(sl_SendTo)
296 _i16 sl_SendTo(_i16 sd, const void *pBuf, _i16 Len, _i16 flags, const SlSockAddr_t *to, SlSocklen_t tolen)
297 {
298  _SlSendtoMsg_u Msg;
299  _SlCmdCtrl_t CmdCtrl = {0, 0, 0};
300  _SlCmdExt_t CmdExt;
301  _i16 RetVal;
302 
303  /* verify that this api is allowed. if not allowed then
304  ignore the API execution and return immediately with an error */
305  VERIFY_API_ALLOWED(SL_OPCODE_SILO_SOCKET);
306  /* RAW transceiver use only sl_Send */
307  if ((sd & SL_SOCKET_PAYLOAD_TYPE_MASK) == SL_SOCKET_PAYLOAD_TYPE_RAW_TRANCEIVER)
308  {
309  return SL_ERROR_BSD_SOC_ERROR;
310  }
311  else
312  {
313  if (Len < 1)
314  {
315  /* ignore */
316  return 0;
317  }
318  }
319 
320  _SlDrvResetCmdExt(&CmdExt);
321  CmdExt.TxPayload1Len = (_u16)Len;
322  CmdExt.pTxPayload1 = (_u8 *)pBuf;
323 
324  switch(to->sa_family)
325  {
326  case SL_AF_INET:
327  CmdCtrl.Opcode = SL_OPCODE_SOCKET_SENDTO;
328  CmdCtrl.TxDescLen = (_SlArgSize_t)sizeof(SlSocketAddrIPv4Command_t);
329  break;
330 #ifndef SL_TINY
331 #ifdef SL_SUPPORT_IPV6
332  case SL_AF_INET6:
333  CmdCtrl.Opcode = SL_OPCODE_SOCKET_SENDTO_V6;
334  CmdCtrl.TxDescLen = (_SlArgSize_t)sizeof(SlSocketAddrIPv6Command_t);
335  break;
336 #endif
337 #endif
338  case SL_AF_RF:
339  default:
340  return SL_RET_CODE_INVALID_INPUT;
341  }
342 
343  Msg.Cmd.IpV4.LenOrPadding = Len;
344  Msg.Cmd.IpV4.Sd = (_u8)sd;
345  _SlSocketBuildAddress(to, &Msg.Cmd);
346  Msg.Cmd.IpV4.FamilyAndFlags |= flags & 0x0F;
347 
348  RetVal = _SlDrvDataWriteOp((_SlSd_t)sd, &CmdCtrl, &Msg, &CmdExt);
349  if(SL_OS_RET_CODE_OK != RetVal)
350  {
351  return RetVal;
352  }
353 
354  return (_i16)Len;
355 }
356 #endif
357 
358 /*******************************************************************************/
359 /* sl_Recvfrom */
360 /*******************************************************************************/
361 typedef union
362 {
365 }_SlRecvfromMsg_u;
366 
367 static const _SlCmdCtrl_t _SlRecvfomCmdCtrl =
368 {
369  SL_OPCODE_SOCKET_RECVFROM,
370  (_SlArgSize_t)sizeof(SlSendRecvCommand_t),
371  (_SlArgSize_t)sizeof(SlSocketAddrResponse_u)
372 };
373 
374 #if _SL_INCLUDE_FUNC(sl_RecvFrom)
375 _i16 sl_RecvFrom(_i16 sd, void *buf, _i16 Len, _i16 flags, SlSockAddr_t *from, SlSocklen_t *fromlen)
376 {
377  _SlRecvfromMsg_u Msg;
378  _SlCmdExt_t CmdExt;
379  _i16 RetVal;
380 
381  /* verify that this api is allowed. if not allowed then
382  ignore the API execution and return immediately with an error */
383  VERIFY_API_ALLOWED(SL_OPCODE_SILO_SOCKET);
384 
385  /* RAW transceiver use only sl_Recv */
386  if ((sd & SL_SOCKET_PAYLOAD_TYPE_MASK) == SL_SOCKET_PAYLOAD_TYPE_RAW_TRANCEIVER)
387  {
388  return SL_ERROR_BSD_SOC_ERROR;
389  }
390 
391  _SlDrvResetCmdExt(&CmdExt);
392  CmdExt.RxPayloadLen = Len;
393  CmdExt.pRxPayload = (_u8 *)buf;
394 
395  Msg.Cmd.Sd = (_u8)sd;
396  Msg.Cmd.StatusOrLen = (_u16)Len;
397 
398  /* no size truncation in recv path */
399  CmdExt.RxPayloadLen = (_i16)Msg.Cmd.StatusOrLen;
400 
401  Msg.Cmd.FamilyAndFlags = (_u8)(flags & 0x0F);
402 
403  if(sizeof(SlSockAddrIn_t) == *fromlen)
404  {
405  Msg.Cmd.FamilyAndFlags |= (SL_AF_INET << 4);
406  }
407  else if (sizeof(SlSockAddrIn6_t) == *fromlen)
408  {
409  Msg.Cmd.FamilyAndFlags |= (SL_AF_INET6 << 4);
410  }
411  else
412  {
413  return SL_RET_CODE_INVALID_INPUT;
414  }
415 
416  RetVal = _SlDrvDataReadOp((_SlSd_t)sd, (_SlCmdCtrl_t *)&_SlRecvfomCmdCtrl, &Msg, &CmdExt);
417  if( RetVal != SL_OS_RET_CODE_OK )
418  {
419  return RetVal;
420  }
421 
422  RetVal = Msg.Rsp.IpV4.StatusOrLen;
423 
424  if(RetVal >= 0)
425  {
426  VERIFY_PROTOCOL(sd == (_i16)Msg.Rsp.IpV4.Sd);
427 #if 0
428  _SlSocketParseAddress(&Msg.Rsp, from, fromlen);
429 #else
430  from->sa_family = Msg.Rsp.IpV4.Family;
431  if(SL_AF_INET == from->sa_family)
432  {
433  ((SlSockAddrIn_t *)from)->sin_port = Msg.Rsp.IpV4.Port;
434  ((SlSockAddrIn_t *)from)->sin_addr.s_addr = Msg.Rsp.IpV4.Address;
435  *fromlen = (SlSocklen_t)sizeof(SlSockAddrIn_t);
436  }
437 #ifdef SL_SUPPORT_IPV6
438  else if(SL_AF_INET6 == from->sa_family)
439  {
440  VERIFY_PROTOCOL(*fromlen >= sizeof(SlSockAddrIn6_t));
441 
442  ((SlSockAddrIn6_t *)from)->sin6_port = Msg.Rsp.IpV6.Port;
443  sl_Memcpy(((SlSockAddrIn6_t *)from)->sin6_addr._S6_un._S6_u32, Msg.Rsp.IpV6.Address, 16);
444  *fromlen = sizeof(SlSockAddrIn6_t);
445  }
446 #endif
447 #endif
448  }
449 
450  return (_i16)RetVal;
451 }
452 #endif
453 
454 /*******************************************************************************/
455 /* sl_Connect */
456 /*******************************************************************************/
457 typedef union
458 {
460  SlSocketResponse_t Rsp;
461 }_SlSockConnectMsg_u;
462 
463 #if _SL_INCLUDE_FUNC(sl_Connect)
464 _i16 sl_Connect(_i16 sd, const SlSockAddr_t *addr, _i16 addrlen)
465 {
466  _SlSockConnectMsg_u Msg;
467  _SlReturnVal_t RetVal;
468  _SlCmdCtrl_t CmdCtrl = {0, (_SlArgSize_t)0, (_SlArgSize_t)sizeof(SlSocketResponse_t)};
469  SlSocketResponse_t AsyncRsp;
470  _u8 ObjIdx = MAX_CONCURRENT_ACTIONS;
471 
472  /* verify that this api is allowed. if not allowed then
473  ignore the API execution and return immediately with an error */
474  VERIFY_API_ALLOWED(SL_OPCODE_SILO_SOCKET);
475  _SlDrvMemZero(&AsyncRsp, sizeof(SlSocketResponse_t));
476 
477  switch(addr->sa_family)
478  {
479  case SL_AF_INET :
480  CmdCtrl.Opcode = SL_OPCODE_SOCKET_CONNECT;
481  CmdCtrl.TxDescLen = (_SlArgSize_t)sizeof(SlSocketAddrIPv4Command_t);
482  /* Do nothing - cmd already initialized to this type */
483  break;
484 #ifdef SL_SUPPORT_IPV6
485  case SL_AF_INET6:
486  CmdCtrl.Opcode = SL_OPCODE_SOCKET_CONNECT_V6;
487  CmdCtrl.TxDescLen = (_SlArgSize_t)sizeof(SlSocketAddrIPv6Command_t);
488  break;
489 #endif
490  case SL_AF_RF:
491  default:
492  return SL_RET_CODE_INVALID_INPUT;
493  }
494 
495  Msg.Cmd.IpV4.LenOrPadding = 0;
496  Msg.Cmd.IpV4.Sd = (_u8)sd;
497 
498  _SlSocketBuildAddress(addr, &Msg.Cmd);
499 
500  ObjIdx = _SlDrvProtectAsyncRespSetting((_u8*)&AsyncRsp, CONNECT_ID, (_u8)(sd & SL_BSD_SOCKET_ID_MASK));
501 
502  if (MAX_CONCURRENT_ACTIONS == ObjIdx)
503  {
504  return SL_POOL_IS_EMPTY;
505  }
506 
507  /* send the command */
508  VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&CmdCtrl, &Msg, NULL));
509  VERIFY_PROTOCOL(Msg.Rsp.Sd == (_u8)sd);
510 
511  RetVal = Msg.Rsp.StatusOrLen;
512 
513  if(SL_RET_CODE_OK == RetVal)
514  {
515 #ifndef SL_TINY
516  /*In case socket is non-blocking one, the async event should be received immediately */
517  if( g_pCB->SocketNonBlocking & (1<<(sd & SL_BSD_SOCKET_ID_MASK) ))
518  {
519  SL_DRV_SYNC_OBJ_WAIT_TIMEOUT(&g_pCB->ObjPool[ObjIdx].SyncObj,
520  SL_DRIVER_TIMEOUT_SHORT,
521  SL_OPCODE_SOCKET_CONNECTASYNCRESPONSE
522  );
523  }
524  else
525 #endif
526  {
527 
528  /* wait for async and get Data Read parameters */
529  SL_DRV_SYNC_OBJ_WAIT_FOREVER(&g_pCB->ObjPool[ObjIdx].SyncObj);
530  }
531 
532  VERIFY_PROTOCOL(AsyncRsp.Sd == (_u8)sd);
533  RetVal = AsyncRsp.StatusOrLen;
534  }
535 
536  _SlDrvReleasePoolObj(ObjIdx);
537  return RetVal;
538 }
539 
540 #endif
541 
542 
543 /*******************************************************************************/
544 /* _SlSocketHandleAsync_Connect */
545 /*******************************************************************************/
546 _SlReturnVal_t _SlSocketHandleAsync_Connect(void *pVoidBuf)
547 {
548  SlSocketResponse_t *pMsgArgs = (SlSocketResponse_t *)_SL_RESP_ARGS_START(pVoidBuf);
549 
550  SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
551 
552  VERIFY_PROTOCOL((pMsgArgs->Sd & SL_BSD_SOCKET_ID_MASK) <= SL_MAX_SOCKETS);
553  VERIFY_SOCKET_CB(NULL != g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs);
554 
555 
556  ((SlSocketResponse_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->Sd = pMsgArgs->Sd;
557  ((SlSocketResponse_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->StatusOrLen = pMsgArgs->StatusOrLen;
558 
559 
560  SL_DRV_SYNC_OBJ_SIGNAL(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj);
561  SL_DRV_PROTECTION_OBJ_UNLOCK();
562 
563  return SL_OS_RET_CODE_OK;
564 }
565 
566 /*******************************************************************************/
567 /* _SlSocketHandleAsync_Close */
568 /*******************************************************************************/
569 _SlReturnVal_t _SlSocketHandleAsync_Close(void *pVoidBuf)
570 {
571  SlSocketResponse_t *pMsgArgs = (SlSocketResponse_t *)_SL_RESP_ARGS_START(pVoidBuf);
572 
573  SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
574 
575  VERIFY_PROTOCOL((pMsgArgs->Sd & SL_BSD_SOCKET_ID_MASK) <= SL_MAX_SOCKETS);
576  VERIFY_SOCKET_CB(NULL != g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs);
577 
578 
579  ((SlSocketResponse_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->Sd = pMsgArgs->Sd;
580  ((SlSocketResponse_t *)(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs))->StatusOrLen = pMsgArgs->StatusOrLen;
581 
582 
583  SL_DRV_SYNC_OBJ_SIGNAL(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj);
584  SL_DRV_PROTECTION_OBJ_UNLOCK();
585 
586  return SL_OS_RET_CODE_OK;
587 }
588 
589 /*******************************************************************************/
590 /* sl_Send */
591 /*******************************************************************************/
592 typedef union
593 {
595  /* no response for 'sendto' commands*/
596 }_SlSendMsg_u;
597 
598 static const _SlCmdCtrl_t _SlSendCmdCtrl =
599 {
600  SL_OPCODE_SOCKET_SEND,
601  (_SlArgSize_t)sizeof(SlSendRecvCommand_t),
602  (_SlArgSize_t)0
603 };
604 
605 #if _SL_INCLUDE_FUNC(sl_Send)
606 _i16 sl_Send(_i16 sd, const void *pBuf, _i16 Len, _i16 flags)
607 {
608  _SlSendMsg_u Msg;
609  _SlCmdExt_t CmdExt;
610  _i16 RetVal;
611  _u32 tempVal;
612 
613  /* verify that this api is allowed. if not allowed then
614  ignore the API execution and return immediately with an error */
615  VERIFY_API_ALLOWED(SL_OPCODE_SILO_SOCKET);
616 
617  _SlDrvResetCmdExt(&CmdExt);
618  CmdExt.TxPayload1Len = (_u16)Len;
619  CmdExt.pTxPayload1 = (_u8 *)pBuf;
620 
621  /* Only for RAW transceiver type socket, relay the flags parameter in the 2 bytes (4 byte aligned) before the actual payload */
622  if ((sd & SL_SOCKET_PAYLOAD_TYPE_MASK) == SL_SOCKET_PAYLOAD_TYPE_RAW_TRANCEIVER)
623  {
624  tempVal = (_u32)flags;
625  CmdExt.pRxPayload = (_u8 *)&tempVal;
626  CmdExt.RxPayloadLen = -4; /* the (-) sign is used to mark the rx buff as output buff as well*/
627  }
628  else
629  {
630  CmdExt.pRxPayload = NULL;
631  if (Len < 1)
632  {
633  /* ignore */
634  return 0;
635  }
636  }
637 
638  Msg.Cmd.StatusOrLen = Len;
639  Msg.Cmd.Sd = (_u8)sd;
640  Msg.Cmd.FamilyAndFlags |= flags & 0x0F;
641 
642  RetVal = _SlDrvDataWriteOp((_u8)sd, (_SlCmdCtrl_t *)&_SlSendCmdCtrl, &Msg, &CmdExt);
643  if(SL_OS_RET_CODE_OK != RetVal)
644  {
645  return RetVal;
646  }
647 
648  return (_i16)Len;
649 }
650 #endif
651 
652 /*******************************************************************************/
653 /* sl_Listen */
654 /*******************************************************************************/
655 typedef union
656 {
657  SlListenCommand_t Cmd;
658  _BasicResponse_t Rsp;
659 }_SlListenMsg_u;
660 
661 
662 
663 #if _SL_INCLUDE_FUNC(sl_Listen)
664 
665 static const _SlCmdCtrl_t _SlListenCmdCtrl =
666 {
667  SL_OPCODE_SOCKET_LISTEN,
668  (_SlArgSize_t)sizeof(SlListenCommand_t),
669  (_SlArgSize_t)sizeof(_BasicResponse_t),
670 };
671 
672 _i16 sl_Listen(_i16 sd, _i16 backlog)
673 {
674  _SlListenMsg_u Msg;
675 
676  /* verify that this api is allowed. if not allowed then
677  ignore the API execution and return immediately with an error */
678  VERIFY_API_ALLOWED(SL_OPCODE_SILO_SOCKET);
679 
680  Msg.Cmd.Sd = (_u8)sd;
681  Msg.Cmd.Backlog = (_u8)backlog;
682 
683  VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlListenCmdCtrl, &Msg, NULL));
684  return (_i16)Msg.Rsp.status;
685 }
686 #endif
687 
688 /*******************************************************************************/
689 /* sl_Accept */
690 /*******************************************************************************/
691 typedef union
692 {
693  SlAcceptCommand_t Cmd;
694  SlSocketResponse_t Rsp;
695 }_SlSockAcceptMsg_u;
696 
697 
698 
699 #if _SL_INCLUDE_FUNC(sl_Accept)
700 
701 static const _SlCmdCtrl_t _SlAcceptCmdCtrl =
702 {
703  SL_OPCODE_SOCKET_ACCEPT,
704  (_SlArgSize_t)sizeof(SlAcceptCommand_t),
705  (_SlArgSize_t)sizeof(_BasicResponse_t),
706 };
707 
708 _i16 sl_Accept(_i16 sd, SlSockAddr_t *addr, SlSocklen_t *addrlen)
709 {
710  _SlSockAcceptMsg_u Msg;
711  _SlReturnVal_t RetVal;
712  SlSocketAddrResponse_u AsyncRsp;
713 
714  _u8 ObjIdx = MAX_CONCURRENT_ACTIONS;
715 
716  /* verify that this api is allowed. if not allowed then
717  ignore the API execution and return immediately with an error */
718  VERIFY_API_ALLOWED(SL_OPCODE_SILO_SOCKET);
719 
720  Msg.Cmd.Sd = (_u8)sd;
721 
722  if((addr != NULL) && (addrlen != NULL))
723  {
724  /* If addr is present, addrlen has to be provided */
725  Msg.Cmd.Family = (_u8)((sizeof(SlSockAddrIn_t) == *addrlen) ? SL_AF_INET : SL_AF_INET6);
726  }
727  else
728  {
729  /* In any other case, addrlen is ignored */
730  Msg.Cmd.Family = (_u8)0;
731  }
732 
733  ObjIdx = _SlDrvProtectAsyncRespSetting((_u8*)&AsyncRsp, ACCEPT_ID, (_u8)sd & SL_BSD_SOCKET_ID_MASK);
734 
735  if (MAX_CONCURRENT_ACTIONS == ObjIdx)
736  {
737  return SL_POOL_IS_EMPTY;
738  }
739 
740  /* send the command */
741  VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlAcceptCmdCtrl, &Msg, NULL));
742  VERIFY_PROTOCOL(Msg.Rsp.Sd == (_u8)sd);
743 
744  RetVal = Msg.Rsp.StatusOrLen;
745 
746  if(SL_OS_RET_CODE_OK == RetVal)
747  {
748 #ifndef SL_TINY
749  /* in case socket is non-blocking one, the async event should be received immediately */
750  if( g_pCB->SocketNonBlocking & (1<<(sd & SL_BSD_SOCKET_ID_MASK) ))
751  {
752  SL_DRV_SYNC_OBJ_WAIT_TIMEOUT(&g_pCB->ObjPool[ObjIdx].SyncObj,
753  SL_DRIVER_TIMEOUT_SHORT,
754  SL_OPCODE_SOCKET_ACCEPTASYNCRESPONSE
755  );
756  }
757  else
758 #endif
759  {
760  /* wait for async and get Data Read parameters */
761  SL_DRV_SYNC_OBJ_WAIT_FOREVER(&g_pCB->ObjPool[ObjIdx].SyncObj);
762  }
763 
764  VERIFY_PROTOCOL(AsyncRsp.IpV4.Sd == (_u8)sd);
765 
766  RetVal = AsyncRsp.IpV4.StatusOrLen;
767 #if 0 /* Kept for backup */
768  _SlSocketParseAddress(&AsyncRsp, addr, addrlen);
769 #else
770  if((addr != NULL) && (addrlen != NULL))
771  {
772  addr->sa_family = AsyncRsp.IpV4.Family;
773 
774  if(SL_AF_INET == addr->sa_family)
775  {
776  if( *addrlen == (SlSocklen_t)sizeof( SlSockAddrIn_t ) )
777  {
778  ((SlSockAddrIn_t *)addr)->sin_port = AsyncRsp.IpV4.Port;
779  ((SlSockAddrIn_t *)addr)->sin_addr.s_addr = AsyncRsp.IpV4.Address;
780  }
781  else
782  {
783  *addrlen = 0;
784  }
785  }
786 #ifdef SL_SUPPORT_IPV6
787  else if(SL_AF_INET6 == addr->sa_family)
788  {
789  if( *addrlen == sizeof( SlSockAddrIn6_t ) )
790  {
791  ((SlSockAddrIn6_t *)addr)->sin6_port = AsyncRsp.IpV6.Port ;
792  sl_Memcpy(((SlSockAddrIn6_t *)addr)->sin6_addr._S6_un._S6_u32, AsyncRsp.IpV6.Address, 16);
793  }
794  else
795  {
796  *addrlen = 0;
797  }
798  }
799 #endif
800  }
801 #endif
802  }
803 
804  _SlDrvReleasePoolObj(ObjIdx);
805  return (_i16)RetVal;
806 }
807 #endif
808 
809 
810 /*******************************************************************************/
811 /* sl_Htonl */
812 /*******************************************************************************/
813 _u32 sl_Htonl( _u32 val )
814 {
815  _u32 i = 1;
816  _i8 *p = (_i8 *)&i;
817  if (p[0] == 1) /* little endian */
818  {
819  p[0] = ((_i8* )&val)[3];
820  p[1] = ((_i8* )&val)[2];
821  p[2] = ((_i8* )&val)[1];
822  p[3] = ((_i8* )&val)[0];
823  return i;
824  }
825  else /* big endian */
826  {
827  return val;
828  }
829 }
830 
831 /*******************************************************************************/
832 /* sl_Htonl */
833 /*******************************************************************************/
834 _u16 sl_Htons( _u16 val )
835 {
836  _i16 i = 1;
837  _i8 *p = (_i8 *)&i;
838  if (p[0] == 1) /* little endian */
839  {
840  p[0] = ((_i8* )&val)[1];
841  p[1] = ((_i8* )&val)[0];
842  return (_u16)i;
843  }
844  else /* big endian */
845  {
846  return val;
847  }
848 }
849 
850 /*******************************************************************************/
851 /* _SlSocketHandleAsync_Accept */
852 /*******************************************************************************/
853 #ifndef SL_TINY
854 _SlReturnVal_t _SlSocketHandleAsync_Accept(void *pVoidBuf)
855 {
856  SlSocketAddrResponse_u *pMsgArgs = (SlSocketAddrResponse_u *)_SL_RESP_ARGS_START(pVoidBuf);
857 
858  SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
859 
860  VERIFY_PROTOCOL(( pMsgArgs->IpV4.Sd & SL_BSD_SOCKET_ID_MASK) <= SL_MAX_SOCKETS);
861  VERIFY_SOCKET_CB(NULL != g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs);
862 
863  sl_Memcpy(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs, pMsgArgs,sizeof(SlSocketAddrResponse_u));
864  SL_DRV_SYNC_OBJ_SIGNAL(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj);
865 
866  SL_DRV_PROTECTION_OBJ_UNLOCK();
867 
868  return SL_OS_RET_CODE_OK;
869 }
870 #endif
871 
872 /*******************************************************************************/
873 /* sl_Recv */
874 /*******************************************************************************/
875 typedef union
876 {
878  SlSocketResponse_t Rsp;
879 }_SlRecvMsg_u;
880 
881 
882 #if _SL_INCLUDE_FUNC(sl_Recv)
883 
884 static const _SlCmdCtrl_t _SlRecvCmdCtrl =
885 {
886  SL_OPCODE_SOCKET_RECV,
887  (_SlArgSize_t)sizeof(SlSendRecvCommand_t),
888  (_SlArgSize_t)sizeof(SlSocketResponse_t)
889 };
890 
891 
892 _i16 sl_Recv(_i16 sd, void *pBuf, _i16 Len, _i16 flags)
893 {
894  _SlRecvMsg_u Msg;
895  _SlCmdExt_t CmdExt;
896  _SlReturnVal_t status;
897 
898  /* verify that this api is allowed. if not allowed then
899  ignore the API execution and return immediately with an error */
900  VERIFY_API_ALLOWED(SL_OPCODE_SILO_SOCKET);
901 
902  _SlDrvResetCmdExt(&CmdExt);
903  CmdExt.RxPayloadLen = Len;
904  CmdExt.pRxPayload = (_u8 *)pBuf;
905 
906  Msg.Cmd.Sd = (_u8)sd;
907  Msg.Cmd.StatusOrLen = (_u16)Len;
908 
909  /* no size truncation in recv path */
910  CmdExt.RxPayloadLen = (_i16)Msg.Cmd.StatusOrLen;
911 
912  Msg.Cmd.FamilyAndFlags = (_u8)(flags & 0x0F);
913 
914  status = _SlDrvDataReadOp((_SlSd_t)sd, (_SlCmdCtrl_t *)&_SlRecvCmdCtrl, &Msg, &CmdExt);
915  if( status != SL_OS_RET_CODE_OK )
916  {
917  return status;
918  }
919 
920  /* if the Device side sends less than expected it is not the Driver's role */
921  /* the returned value could be smaller than the requested size */
922  return (_i16)Msg.Rsp.StatusOrLen;
923 }
924 #endif
925 
926 /*******************************************************************************/
927 /* sl_SetSockOpt */
928 /*******************************************************************************/
929 typedef union
930 {
932  SlSocketResponse_t Rsp;
933 }_SlSetSockOptMsg_u;
934 
935 static const _SlCmdCtrl_t _SlSetSockOptCmdCtrl =
936 {
937  SL_OPCODE_SOCKET_SETSOCKOPT,
938  (_SlArgSize_t)sizeof(SlSetSockOptCommand_t),
939  (_SlArgSize_t)sizeof(SlSocketResponse_t)
940 };
941 
942 #if _SL_INCLUDE_FUNC(sl_SetSockOpt)
943 _i16 sl_SetSockOpt(_i16 sd, _i16 level, _i16 optname, const void *optval, SlSocklen_t optlen)
944 {
945  _SlSetSockOptMsg_u Msg;
946  _SlCmdExt_t CmdExt;
947 
948  /* verify that this api is allowed. if not allowed then
949  ignore the API execution and return immediately with an error */
950  VERIFY_API_ALLOWED(SL_OPCODE_SILO_SOCKET);
951 
952  _SlDrvResetCmdExt(&CmdExt);
953  CmdExt.TxPayload1Len = optlen;
954  CmdExt.pTxPayload1 = (_u8 *)optval;
955 
956  Msg.Cmd.Sd = (_u8)sd;
957  Msg.Cmd.Level = (_u8)level;
958  Msg.Cmd.OptionLen = (_u8)optlen;
959  Msg.Cmd.OptionName = (_u8)optname;
960 
961  VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlSetSockOptCmdCtrl, &Msg, &CmdExt));
962 
963  return (_i16)Msg.Rsp.StatusOrLen;
964 }
965 #endif
966 
967 /*******************************************************************************/
968 /* sl_GetSockOpt */
969 /*******************************************************************************/
970 typedef union
971 {
974 }_SlGetSockOptMsg_u;
975 
976 
977 #if _SL_INCLUDE_FUNC(sl_GetSockOpt)
978 
979 static const _SlCmdCtrl_t _SlGetSockOptCmdCtrl =
980 {
981  SL_OPCODE_SOCKET_GETSOCKOPT,
982  (_SlArgSize_t)sizeof(SlGetSockOptCommand_t),
983  (_SlArgSize_t)sizeof(SlGetSockOptResponse_t)
984 };
985 
986 _i16 sl_GetSockOpt(_i16 sd, _i16 level, _i16 optname, void *optval, SlSocklen_t *optlen)
987 {
988  _SlGetSockOptMsg_u Msg;
989  _SlCmdExt_t CmdExt;
990 
991  /* verify that this api is allowed. if not allowed then
992  ignore the API execution and return immediately with an error */
993  VERIFY_API_ALLOWED(SL_OPCODE_SILO_SOCKET);
994  if (*optlen == 0)
995  {
996  return SL_EZEROLEN;
997  }
998 
999  _SlDrvResetCmdExt(&CmdExt);
1000  CmdExt.RxPayloadLen = (_i16)(*optlen);
1001  CmdExt.pRxPayload = optval;
1002 
1003  Msg.Cmd.Sd = (_u8)sd;
1004  Msg.Cmd.Level = (_u8)level;
1005  Msg.Cmd.OptionLen = (_u8)(*optlen);
1006  Msg.Cmd.OptionName = (_u8)optname;
1007 
1008  VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlGetSockOptCmdCtrl, &Msg, &CmdExt));
1009 
1010  if (CmdExt.RxPayloadLen < CmdExt.ActualRxPayloadLen)
1011  {
1012  *optlen = Msg.Rsp.OptionLen;
1013  return SL_ESMALLBUF;
1014  }
1015  else
1016  {
1017  *optlen = (_u8)CmdExt.ActualRxPayloadLen;
1018  }
1019  return (_i16)Msg.Rsp.Status;
1020 }
1021 #endif
1022 
1023 /********************************************************************************/
1024 /* sl_Select */
1025 /* ******************************************************************************/
1026 #ifndef SL_TINY
1027 #if _SL_INCLUDE_FUNC(sl_Select)
1028 
1029 typedef union
1030 {
1031  SlSelectCommand_t Cmd;
1032  _BasicResponse_t Rsp;
1033 }_SlSelectMsg_u;
1034 
1035 static const _SlCmdCtrl_t _SlSelectCmdCtrl =
1036 {
1037  SL_OPCODE_SOCKET_SELECT,
1038  (_SlArgSize_t)sizeof(SlSelectCommand_t),
1039  (_SlArgSize_t)sizeof(_BasicResponse_t)
1040 };
1041 
1042 /********************************************************************************/
1043 /* SL_SOCKET_FD_SET */
1044 /* ******************************************************************************/
1045 void SL_SOCKET_FD_SET(_i16 fd, SlFdSet_t *fdset)
1046 {
1047  fdset->fd_array[0] |= (1<< (fd & SL_BSD_SOCKET_ID_MASK));
1048 }
1049 
1050 /*******************************************************************************/
1051 /* SL_SOCKET_FD_CLR */
1052 /*******************************************************************************/
1053 void SL_SOCKET_FD_CLR(_i16 fd, SlFdSet_t *fdset)
1054 {
1055  fdset->fd_array[0] &= ~(1<< (fd & SL_BSD_SOCKET_ID_MASK));
1056 }
1057 
1058 /*******************************************************************************/
1059 /* SL_SOCKET_FD_ISSET */
1060 /*******************************************************************************/
1061 _i16 SL_SOCKET_FD_ISSET(_i16 fd, SlFdSet_t *fdset)
1062 {
1063  if( fdset->fd_array[0] & (1<< (fd & SL_BSD_SOCKET_ID_MASK)) )
1064  {
1065  return 1;
1066  }
1067  return 0;
1068 }
1069 
1070 /*******************************************************************************/
1071 /* SL_SOCKET_FD_ZERO */
1072 /*******************************************************************************/
1073 void SL_SOCKET_FD_ZERO(SlFdSet_t *fdset)
1074 {
1075  fdset->fd_array[0] = 0;
1076 }
1077 
1078 #if (defined(SL_PLATFORM_MULTI_THREADED) && !defined(slcb_SocketTriggerEventHandler))
1079 
1080 /*******************************************************************************/
1081 /* Multiple Select */
1082 /*******************************************************************************/
1083 
1084 /* Multiple Select Defines */
1085 #define LOCAL_CTRL_PORT (3632)
1086 #define SL_LOOPBACK_ADDR (0x0100007F)
1087 #define DUMMY_BUF_SIZE (4)
1088 #define CTRL_SOCK_FD (((_u16)(1)) << g_pCB->MultiSelectCB.CtrlSockFD)
1089 #define SELECT_TIMEOUT ((_u16)0)
1090 #define SELECT_NO_TIMEOUT (0xFFFFFFFF)
1091 
1092 /* Multiple Select Structures */
1093 _SlSelectMsg_u Msg;
1094 
1095 static const SlSockAddrIn_t _SlCtrlSockAddr =
1096 {
1097  SL_AF_INET,
1098  LOCAL_CTRL_PORT,
1099  SL_INADDR_ANY,
1100  (_u32)0x0,
1101  (_u32)0x0
1102 };
1103 
1104 static const SlSockAddrIn_t _SlCtrlSockRelese =
1105 {
1106  SL_AF_INET,
1107  LOCAL_CTRL_PORT,
1108  SL_LOOPBACK_ADDR,
1109  (_u32)0x0,
1110  (_u32)0x0
1111 };
1112 
1113 /*******************************************************************************/
1114 /* CountSetBits */
1115 /*******************************************************************************/
1116 static inline _u8 CountSetBits(_u16 fdList)
1117 {
1118  _u8 Count = 0;
1119 
1120  while(fdList)
1121  {
1122  Count += (fdList & ((_u16)1));
1123  fdList = fdList >> 1;
1124  }
1125 
1126  return Count;
1127 }
1128 
1129 /*******************************************************************************/
1130 /* _SlSocketHandleAsync_Select */
1131 /*******************************************************************************/
1132 _SlReturnVal_t _SlSocketHandleAsync_Select(void *pVoidBuf)
1133 {
1134  _SlReturnVal_t RetVal;
1135  SlSelectAsyncResponse_t *pMsgArgs = (SlSelectAsyncResponse_t *)_SL_RESP_ARGS_START(pVoidBuf);
1136  _u8 RegIdx = 0;
1137  _u32 time_now;
1138  _u8 TimeoutEvent = 0;
1139  _u16 SelectEvent = 0;
1140 
1141  _SlDrvMemZero(&Msg, sizeof(_SlSelectMsg_u));
1142 
1143  SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
1144 
1145  SL_DRV_OBJ_LOCK_FOREVER(&g_pCB->MultiSelectCB.SelectLockObj);
1146 
1147  /* Check if this context was triggered by a 'select joiner' only,
1148  * without timeout occuering, in order to launch the next select as quick as possible */
1149  if((CTRL_SOCK_FD == pMsgArgs->ReadFds) && (pMsgArgs->Status != SELECT_TIMEOUT))
1150  {
1151  RetVal = _SlDrvClearCtrlSocket();
1152  Msg.Cmd.ReadFds = g_pCB->MultiSelectCB.readsds;
1153  Msg.Cmd.WriteFds = g_pCB->MultiSelectCB.writesds;
1154  Msg.Cmd.ReadFds |= CTRL_SOCK_FD;
1155  Msg.Cmd.tv_sec = 0xFFFF;
1156  Msg.Cmd.tv_usec = 0xFFFF;
1157 
1158  RegIdx = _SlDrvGetNextTimeoutValue();
1159 
1160  SL_TRACE3(DBG_MSG, MSG_312, "\n\rAdded caller: call Select with: Write:%x Sec:%d uSec:%d\n\r",
1161  Msg.Cmd.WriteFds, Msg.Cmd.tv_sec, Msg.Cmd.tv_usec);
1162 
1163  RetVal = _SlDrvCmdSend_noWait((_SlCmdCtrl_t *)&_SlSelectCmdCtrl, &Msg, NULL);
1164 
1165  SL_DRV_OBJ_UNLOCK(&g_pCB->MultiSelectCB.SelectLockObj);
1166 
1167  SL_DRV_PROTECTION_OBJ_UNLOCK();
1168 
1169  return RetVal;
1170  }
1171 
1172  /* If we're triggered by the NWP, take time-stamps to monitor the time-outs */
1173  time_now = ((slcb_GetTimestamp() / SL_TIMESTAMP_TICKS_IN_10_MILLISECONDS) * 10);
1174 
1175  /* If it's a proper select response, or if timeout occurred, release the relevant waiters */
1176  for(RegIdx = 0 ; RegIdx < MAX_CONCURRENT_ACTIONS ; RegIdx++)
1177  {
1178  if(g_pCB->MultiSelectCB.SelectEntry[RegIdx] != NULL)
1179  {
1180  /* In case a certain entry has 100 mSec or less until it's timeout, the overhead
1181  * caused by calling select again with it's fd lists is redundant, just return a time-out. */
1182 
1183  TimeoutEvent = ((time_now + 100) >= g_pCB->MultiSelectCB.SelectEntry[RegIdx]->TimeStamp);
1184 
1185  if(pMsgArgs->Status != SELECT_TIMEOUT)
1186  {
1187  SelectEvent = ((g_pCB->MultiSelectCB.SelectEntry[RegIdx]->readlist & pMsgArgs->ReadFds) ||
1188  (g_pCB->MultiSelectCB.SelectEntry[RegIdx]->writelist & pMsgArgs->WriteFds));
1189  }
1190 
1191  if(SelectEvent || TimeoutEvent)
1192  {
1193  SL_TRACE4(DBG_MSG, MSG_312, "\n\rg: %x, sl:%d, run:%d, idx:%d\n\r", g_pCB->MultiSelectCB.writesds, SelectEvent , times, RegIdx);
1194 
1195  /* Clear the global select socket descriptor bitmaps */
1196  g_pCB->MultiSelectCB.readsds &= ~(g_pCB->MultiSelectCB.SelectEntry[RegIdx]->readlist);
1197  g_pCB->MultiSelectCB.writesds &= ~(g_pCB->MultiSelectCB.SelectEntry[RegIdx]->writelist);
1198 
1199  if(SelectEvent)
1200  {
1201  /* set the corresponding fd lists. */
1202  g_pCB->MultiSelectCB.SelectEntry[RegIdx]->Response.ReadFds = (pMsgArgs->ReadFds & g_pCB->MultiSelectCB.SelectEntry[RegIdx]->readlist);
1203  g_pCB->MultiSelectCB.SelectEntry[RegIdx]->Response.WriteFds = (pMsgArgs->WriteFds & g_pCB->MultiSelectCB.SelectEntry[RegIdx]->writelist);
1204  g_pCB->MultiSelectCB.SelectEntry[RegIdx]->Response.ReadFdsCount = CountSetBits(g_pCB->MultiSelectCB.SelectEntry[RegIdx]->readlist);
1205  g_pCB->MultiSelectCB.SelectEntry[RegIdx]->Response.WriteFdsCount = CountSetBits(g_pCB->MultiSelectCB.SelectEntry[RegIdx]->writelist);
1206  g_pCB->MultiSelectCB.SelectEntry[RegIdx]->Response.Status = (g_pCB->MultiSelectCB.SelectEntry[RegIdx]->Response.ReadFdsCount +
1207  g_pCB->MultiSelectCB.SelectEntry[RegIdx]->Response.WriteFdsCount);
1208  }
1209  else
1210  {
1211  g_pCB->MultiSelectCB.SelectEntry[RegIdx]->Response.Status = SELECT_TIMEOUT;
1212  }
1213 
1214  g_pCB->MultiSelectCB.SelectEntry[RegIdx]->Response.ReadFds &= ~(CTRL_SOCK_FD);
1215 
1216  /* Signal the waiting caller. */
1217  SL_DRV_SYNC_OBJ_SIGNAL(&g_pCB->ObjPool[g_pCB->MultiSelectCB.SelectEntry[RegIdx]->ObjIdx].SyncObj);
1218 
1219  /* Clean it's table entry */
1220  g_pCB->MultiSelectCB.SelectEntry[RegIdx] = NULL;
1221  }
1222  }
1223  }
1224 
1225  /* In case where A caller was added, but also some sockfd were set on the NWP,
1226  * We clear the control socket. */
1227  if((pMsgArgs->ReadFds & CTRL_SOCK_FD) && (pMsgArgs->Status != SELECT_TIMEOUT))
1228  {
1229  RetVal = _SlDrvClearCtrlSocket();
1230  }
1231 
1232  /* If more readers/Writers are present, send select again */
1233  if((0 != g_pCB->MultiSelectCB.readsds) || (0 != g_pCB->MultiSelectCB.writesds))
1234  {
1235  Msg.Cmd.ReadFds = g_pCB->MultiSelectCB.readsds;
1236  Msg.Cmd.ReadFds |= CTRL_SOCK_FD;
1237  Msg.Cmd.WriteFds = g_pCB->MultiSelectCB.writesds;
1238 
1239  /* Set timeout to blocking, in case there is no caller with timeout value. */
1240  Msg.Cmd.tv_sec = 0xFFFF;
1241  Msg.Cmd.tv_usec = 0xFFFF;
1242 
1243  /* Get the next awaiting timeout caller */
1244  RegIdx = _SlDrvGetNextTimeoutValue();
1245 
1246  SL_TRACE3(DBG_MSG, MSG_312, "\n\rRelease Partial: call Select with: Read:%x Sec:%d uSec:%d\n\r",
1247  Msg.Cmd.ReadFds, Msg.Cmd.tv_sec, Msg.Cmd.tv_usec);
1248 
1249  RetVal = _SlDrvCmdSend_noWait((_SlCmdCtrl_t *)&_SlSelectCmdCtrl, &Msg, NULL);
1250  }
1251  else
1252  {
1253  while(g_pCB->MultiSelectCB.ActiveWaiters)
1254  {
1255  SL_DRV_SYNC_OBJ_SIGNAL(&g_pCB->MultiSelectCB.SelectSyncObj);
1256  g_pCB->MultiSelectCB.ActiveWaiters--;
1257  }
1258 
1259  g_pCB->MultiSelectCB.ActiveSelect = FALSE;
1260 
1261  SL_TRACE1(DBG_MSG, MSG_312, "\n\rSelect isn't Active: %d\n\r", g_pCB->MultiSelectCB.ActiveSelect);
1262  }
1263 
1264  SL_DRV_OBJ_UNLOCK(&g_pCB->MultiSelectCB.SelectLockObj);
1265 
1266  SL_DRV_PROTECTION_OBJ_UNLOCK();
1267 
1268  return SL_OS_RET_CODE_OK;
1269 }
1270 
1271 /*******************************************************************************/
1272 /* SlDrvGetNextTimeoutValue */
1273 /*******************************************************************************/
1274 static _i8 _SlDrvGetNextTimeoutValue(void)
1275 {
1276  _u32 time_now;
1277  _i8 Found = -1;
1278  _u8 idx = 0;
1279 
1280  /* Take a timestamp */
1281  time_now = ((slcb_GetTimestamp() / SL_TIMESTAMP_TICKS_IN_10_MILLISECONDS) * 10);
1282 
1283  /* Go through all waiting time-outs, and select the closest */
1284  for(idx = 0 ; idx < MAX_CONCURRENT_ACTIONS ; idx++)
1285  {
1286  if(NULL != g_pCB->MultiSelectCB.SelectEntry[idx])
1287  {
1288  /* Check if the time-stamp is bigger or equal to current time, and if it's the minimal time-stamp (closest event) */
1289  if(g_pCB->MultiSelectCB.SelectEntry[idx]->TimeStamp >= time_now)
1290  {
1291  if(Found == -1)
1292  {
1293  Found = idx;
1294  }
1295  else
1296  {
1297  if(g_pCB->MultiSelectCB.SelectEntry[idx]->TimeStamp <= g_pCB->MultiSelectCB.SelectEntry[Found]->TimeStamp)
1298  {
1299  Found = idx;
1300  }
1301  }
1302  }
1303  }
1304  }
1305 
1306  /* If a non-wait-forever index was found, calculate delta until closest event */
1307  if(g_pCB->MultiSelectCB.SelectEntry[Found]->TimeStamp != SELECT_NO_TIMEOUT)
1308  {
1309  _i32 delta = (g_pCB->MultiSelectCB.SelectEntry[Found]->TimeStamp - time_now);
1310 
1311  if(delta >= 0)
1312  {
1313  Msg.Cmd.tv_sec = (delta / 1000);
1314  Msg.Cmd.tv_usec = (((delta % 1000) * 1000) >> 10);
1315  }
1316  else
1317  {
1318  /* if delta time calculated is negative, call a non-blocking select */
1319  Msg.Cmd.tv_sec = 0;
1320  Msg.Cmd.tv_usec = 0;
1321  }
1322  }
1323 
1324  return Found;
1325 }
1326 
1327 /*******************************************************************************/
1328 /* _SlDrvClearCtrlSocket */
1329 /*******************************************************************************/
1330 static _i16 _SlDrvClearCtrlSocket(void)
1331 {
1332  _SlRecvfromMsg_u Msg;
1333  _SlCmdExt_t CmdExt;
1334  _u8 dummyBuf[DUMMY_BUF_SIZE];
1335  _SlReturnVal_t RetVal;
1336 
1337  /* Prepare a recvFrom Cmd */
1338  _SlDrvResetCmdExt(&CmdExt);
1339  _SlDrvMemZero(&Msg, sizeof(_SlRecvfromMsg_u));
1340 
1341  CmdExt.RxPayloadLen = DUMMY_BUF_SIZE;
1342  CmdExt.pRxPayload = (_u8 *)&dummyBuf;
1343 
1344  Msg.Cmd.Sd = (_u8)g_pCB->MultiSelectCB.CtrlSockFD;
1345  Msg.Cmd.StatusOrLen = (_u16)DUMMY_BUF_SIZE;
1346  Msg.Cmd.FamilyAndFlags = (SL_AF_INET << 4);
1347 
1348  RetVal = _SlDrvCmdSend_noWait((_SlCmdCtrl_t *)&_SlRecvfomCmdCtrl, &Msg, &CmdExt);
1349 
1350  return RetVal;
1351 }
1352 
1353 /*******************************************************************************/
1354 /* _SlDrvOpenCtrlSocket */
1355 /*******************************************************************************/
1356 static _i16 _SlDrvOpenCtrlSocket(void)
1357 {
1358  _i16 retVal;
1359 
1360  /* In case a control socket is already open, return. */
1361  if(g_pCB->MultiSelectCB.CtrlSockFD != 0xFF)
1362  {
1363  return 0;
1364  }
1365 
1366  /* Open a local control socket */
1367  retVal = sl_Socket(SL_AF_INET, SL_SOCK_DGRAM, 0);
1368 
1369  if(retVal == SL_ERROR_BSD_ENSOCK)
1370  {
1371  return 0;
1372  }
1373  else if(retVal < 0)
1374  {
1375  return retVal;
1376  }
1377  else
1378  {
1379  g_pCB->MultiSelectCB.CtrlSockFD = retVal;
1380  }
1381 
1382  /* Bind it to local control port */
1383  retVal = sl_Bind(g_pCB->MultiSelectCB.CtrlSockFD, (const SlSockAddr_t *)&_SlCtrlSockAddr, sizeof(SlSockAddrIn_t));
1384 
1385  return retVal;
1386 }
1387 
1388 /*******************************************************************************/
1389 /* _SlDrvCloseCtrlSocket */
1390 /*******************************************************************************/
1391 static _i16 _SlDrvCloseCtrlSocket(void)
1392 {
1393  _i16 retVal = 0;
1394  _i16 sockfd = 0xFF;
1395 
1396  /* Close the internal Control socket */
1397  sockfd = g_pCB->MultiSelectCB.CtrlSockFD;
1398 
1399  if(sockfd != 0xFF)
1400  {
1401  /* Close the local control socket */
1402  retVal = sl_Close(sockfd);
1403  }
1404 
1405  g_pCB->MultiSelectCB.CtrlSockFD = 0xFF;
1406 
1407  if(retVal < 0)
1408  {
1409  return SL_ERROR_BSD_SOC_ERROR;
1410  }
1411 
1412  return retVal;
1413 }
1414 
1415 /*******************************************************************************/
1416 /* to_Msec */
1417 /*******************************************************************************/
1418 static inline _u32 to_mSec(struct SlTimeval_t* timeout)
1419 {
1420  return (((slcb_GetTimestamp() / SL_TIMESTAMP_TICKS_IN_10_MILLISECONDS) * 10) + (timeout->tv_sec * 1000) + (timeout->tv_usec / 1000));
1421 }
1422 
1423 /*******************************************************************************/
1424 /* _SlDrvUnRegisterForSelectAsync */
1425 /*******************************************************************************/
1426 static _i16 _SlDrvUnRegisterForSelectAsync(_SlSelectEntry_t* pEntry, _u8 SelectInProgress)
1427 {
1428  SL_DRV_OBJ_LOCK_FOREVER(&g_pCB->MultiSelectCB.SelectLockObj);
1429 
1430  /* Clear the global select fd lists */
1431  g_pCB->MultiSelectCB.readsds &= ~(pEntry->readlist);
1432  g_pCB->MultiSelectCB.writesds &= ~(pEntry->writelist);
1433 
1434  /* Empty the caller's table entry. */
1435  g_pCB->MultiSelectCB.SelectEntry[pEntry->ObjIdx] = NULL;
1436 
1437  if(g_pCB->MultiSelectCB.ActiveSelect == FALSE)
1438  {
1439  _SlDrvCloseCtrlSocket();
1440  }
1441 
1442  SL_DRV_OBJ_UNLOCK(&g_pCB->MultiSelectCB.SelectLockObj);
1443 
1444  /* Release it's pool object */
1445  _SlDrvReleasePoolObj(pEntry->ObjIdx);
1446 
1447  return SL_ERROR_BSD_SOC_ERROR;
1448 }
1449 
1450 /*******************************************************************************/
1451 /* _SlDrvRegisterForSelectAsync */
1452 /*******************************************************************************/
1453 static _i16 _SlDrvRegisterForSelectAsync(_SlSelectEntry_t* pEntry, _SlSelectMsg_u* pMsg, struct SlTimeval_t *timeout, _u8 SelectInProgress)
1454 {
1455  _SlReturnVal_t _RetVal = 0;
1456  _u8 dummyBuf[4] = {0};
1457 
1458  /* Register this caller's parameters */
1459  pEntry->readlist = pMsg->Cmd.ReadFds;
1460  pEntry->writelist = pMsg->Cmd.WriteFds;
1461 
1462  if((pMsg->Cmd.tv_sec != 0xFFFF) && (timeout != NULL))
1463  {
1464  pEntry->TimeStamp = to_mSec(timeout);
1465  }
1466  else
1467  {
1468  pEntry->TimeStamp = SELECT_NO_TIMEOUT;
1469  }
1470 
1471  g_pCB->MultiSelectCB.readsds |= pMsg->Cmd.ReadFds;
1472  g_pCB->MultiSelectCB.writesds |= pMsg->Cmd.WriteFds;
1473  g_pCB->MultiSelectCB.SelectEntry[pEntry->ObjIdx] = pEntry;
1474 
1475  SL_TRACE3(DBG_MSG, MSG_312, "\n\rRegistered: Objidx:%d, sec:%d, usec%d\n\r",
1476  pEntry->ObjIdx, pMsg->Cmd.tv_sec, pMsg->Cmd.tv_usec);
1477 
1478  if((!SelectInProgress) || (g_pCB->MultiSelectCB.ActiveSelect == FALSE))
1479  {
1480  /* Add ctrl socket to the read list for this 'select' call */
1481  pMsg->Cmd.ReadFds |= CTRL_SOCK_FD;
1482 
1483  SL_DRV_OBJ_UNLOCK(&g_pCB->MultiSelectCB.SelectLockObj);
1484 
1485  _RetVal = _SlDrvCmdOp((_SlCmdCtrl_t *)&_SlSelectCmdCtrl, pMsg, NULL);
1486 
1487  if((_RetVal == SL_RET_CODE_OK) && (g_pCB->MultiSelectCB.CtrlSockFD != 0xFF))
1488  {
1489  /* Signal any waiting "Select" callers */
1490  SL_DRV_SYNC_OBJ_SIGNAL(&g_pCB->MultiSelectCB.SelectSyncObj);
1491  }
1492  }
1493  else
1494  {
1495  SL_DRV_OBJ_UNLOCK(&g_pCB->MultiSelectCB.SelectLockObj);
1496 
1497  /* Wait here to be signaled by a successfully completed select caller */
1498  SL_DRV_SYNC_OBJ_WAIT_FOREVER(&g_pCB->MultiSelectCB.SelectSyncObj);
1499 
1500  _RetVal = sl_SendTo(g_pCB->MultiSelectCB.CtrlSockFD,
1501  &dummyBuf[0],
1502  sizeof(dummyBuf),
1503  0,
1504  (const SlSockAddr_t *)&_SlCtrlSockRelese,
1505  sizeof(SlSockAddrIn_t));
1506  }
1507 
1508  return _RetVal;
1509 }
1510 
1511 /********************************************************************************/
1512 /* sl_Select */
1513 /* ******************************************************************************/
1514 _i16 sl_Select(_i16 nfds, SlFdSet_t *readsds, SlFdSet_t *writesds, SlFdSet_t *exceptsds, struct SlTimeval_t *timeout)
1515 {
1516  _i16 ret;
1517  _u8 isCaller = FALSE;
1518  _SlSelectMsg_u Msg;
1519  _SlSelectEntry_t SelectParams;
1520  _u8 SelectInProgress = FALSE;
1521 
1522  /* verify that this API is allowed. if not allowed then
1523  ignore the API execution and return immediately with an error */
1524  VERIFY_API_ALLOWED(SL_OPCODE_SILO_SOCKET);
1525  _SlDrvMemZero(&Msg, sizeof(_SlSelectMsg_u));
1526  _SlDrvMemZero(&SelectParams, sizeof(_SlSelectEntry_t));
1527 
1528  Msg.Cmd.Nfds = (_u8)nfds;
1529 
1530  if(readsds)
1531  {
1532  Msg.Cmd.ReadFds = (_u16)readsds->fd_array[0];
1533  }
1534 
1535  if(writesds)
1536  {
1537  Msg.Cmd.WriteFds = (_u16)writesds->fd_array[0];
1538  }
1539 
1540  if(NULL == timeout)
1541  {
1542  Msg.Cmd.tv_sec = 0xffff;
1543  Msg.Cmd.tv_usec = 0xffff;
1544  }
1545  else
1546  {
1547  if(0xffff <= timeout->tv_sec)
1548  {
1549  Msg.Cmd.tv_sec = 0xffff;
1550  }
1551  else
1552  {
1553  Msg.Cmd.tv_sec = (_u16)timeout->tv_sec;
1554  }
1555 
1556  /* this divides by 1024 to fit the result in a int16_t.
1557  * Upon receiving, the NWP multiply this value by 1024. */
1558  timeout->tv_usec = (timeout->tv_usec >> 10);
1559 
1560  if(0xffff <= timeout->tv_usec)
1561  {
1562  Msg.Cmd.tv_usec = 0xffff;
1563  }
1564  else
1565  {
1566  Msg.Cmd.tv_usec = (_u16)timeout->tv_usec;
1567  }
1568  }
1569 
1570  while(FALSE == isCaller)
1571  {
1572  SelectParams.ObjIdx = _SlDrvProtectAsyncRespSetting((_u8*)&SelectParams.Response, SELECT_ID, SL_MAX_SOCKETS);
1573 
1574  if(MAX_CONCURRENT_ACTIONS == SelectParams.ObjIdx)
1575  {
1576  return SL_POOL_IS_EMPTY;
1577  }
1578 
1579  SL_DRV_OBJ_LOCK_FOREVER(&g_pCB->MultiSelectCB.SelectLockObj);
1580 
1581  /* Check if no other 'Select' calls are in progress */
1582  if(FALSE == g_pCB->MultiSelectCB.ActiveSelect)
1583  {
1584  g_pCB->MultiSelectCB.ActiveSelect = TRUE;
1585  }
1586  else
1587  {
1588  SelectInProgress = TRUE;
1589  }
1590 
1591  if(!SelectInProgress)
1592  {
1593  ret = _SlDrvOpenCtrlSocket();
1594 
1595  if(ret < 0)
1596  {
1597  _SlDrvCloseCtrlSocket();
1598  g_pCB->MultiSelectCB.ActiveSelect = FALSE;
1599  SL_DRV_OBJ_UNLOCK(&g_pCB->MultiSelectCB.SelectLockObj);
1600  _SlDrvReleasePoolObj(SelectParams.ObjIdx);
1601  return ret;
1602  }
1603  else
1604  {
1605  /* All conditions are met for calling "Select" */
1606  isCaller = TRUE;
1607  }
1608  }
1609  else if(g_pCB->MultiSelectCB.CtrlSockFD == 0xFF)
1610  {
1611  _SlDrvReleasePoolObj(SelectParams.ObjIdx);
1612 
1613  /* This is not a first select caller and all sockets are open,
1614  * caller is expected to wait until select is inactive,
1615  * before trying to register again. */
1616  g_pCB->MultiSelectCB.ActiveWaiters++;
1617 
1618  SL_DRV_OBJ_UNLOCK(&g_pCB->MultiSelectCB.SelectLockObj);
1619 
1620  SL_DRV_SYNC_OBJ_WAIT_FOREVER(&g_pCB->MultiSelectCB.SelectSyncObj);
1621 
1622  if((_i16)g_pCB->MultiSelectCB.SelectCmdResp.status != SL_RET_CODE_OK)
1623  {
1624  return (_i16)(g_pCB->MultiSelectCB.SelectCmdResp.status);
1625  }
1626 
1627  SelectInProgress = FALSE;
1628  }
1629  else
1630  {
1631  /* All conditions are met for calling "Select" */
1632  isCaller = TRUE;
1633  }
1634  }
1635 
1636  /* Register this caller details for an select Async event.
1637  * SelectLockObj is released inside this function,
1638  * right before sending 'Select' command. */
1639  ret = _SlDrvRegisterForSelectAsync(&SelectParams, &Msg, timeout, SelectInProgress);
1640 
1641  if(ret < 0)
1642  {
1643  return (_SlDrvUnRegisterForSelectAsync(&SelectParams, SelectInProgress));
1644  }
1645 
1646  /* Wait here for a Async event, or command response in case select fails.*/
1647  SL_DRV_SYNC_OBJ_WAIT_FOREVER(&g_pCB->ObjPool[SelectParams.ObjIdx].SyncObj);
1648 
1649  _SlDrvReleasePoolObj(SelectParams.ObjIdx);
1650 
1651  ret = (_i16)g_pCB->MultiSelectCB.SelectCmdResp.status;
1652 
1653  if(ret == SL_RET_CODE_OK)
1654  {
1655  ret = (_i16)SelectParams.Response.Status;
1656 
1657  if(ret > SELECT_TIMEOUT)
1658  {
1659  if(readsds)
1660  {
1661  readsds->fd_array[0] = SelectParams.Response.ReadFds;
1662  }
1663 
1664  if(writesds)
1665  {
1666  writesds->fd_array[0] = SelectParams.Response.WriteFds;
1667  }
1668  }
1669  }
1670 
1671  return ret;
1672 }
1673 
1674 #else
1675 
1676 /*******************************************************************************/
1677 /* _SlSocketHandleAsync_Select */
1678 /*******************************************************************************/
1679 _SlReturnVal_t _SlSocketHandleAsync_Select(void *pVoidBuf)
1680 {
1681  SlSelectAsyncResponse_t *pMsgArgs = (SlSelectAsyncResponse_t *)_SL_RESP_ARGS_START(pVoidBuf);
1682 #if ((defined(SL_RUNTIME_EVENT_REGISTERATION) || defined(slcb_SocketTriggerEventHandler)))
1683  SlSockTriggerEvent_t SockTriggerEvent;
1684 #endif
1685 
1686  SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
1687 
1688  VERIFY_SOCKET_CB(NULL != g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs);
1689 
1690  sl_Memcpy(g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].pRespArgs, pMsgArgs, sizeof(SlSelectAsyncResponse_t));
1691 
1692 #if ((defined(SL_RUNTIME_EVENT_REGISTERATION) || defined(slcb_SocketTriggerEventHandler)))
1693  if(1 == _SlIsEventRegistered(SL_EVENT_HDL_SOCKET_TRIGGER))
1694  {
1695  if (g_pCB->SocketTriggerSelect.Info.State == SOCK_TRIGGER_WAITING_FOR_RESP)
1696  {
1697 
1698  SockTriggerEvent.Event = SL_SOCKET_TRIGGER_EVENT_SELECT;
1699  SockTriggerEvent.EventData = 0;
1700 
1701 
1702  g_pCB->SocketTriggerSelect.Info.State = SOCK_TRIGGER_RESP_RECEIVED;
1703 
1704  SL_DRV_PROTECTION_OBJ_UNLOCK();
1705 
1706  /* call the user handler */
1707  _SlDrvHandleSocketTriggerEvents(&SockTriggerEvent);
1708 
1709  return SL_OS_RET_CODE_OK;
1710  }
1711  else
1712  {
1713  SL_DRV_SYNC_OBJ_SIGNAL(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj);
1714  }
1715  }
1716  else
1717 #endif
1718  {
1719 
1720  SL_DRV_SYNC_OBJ_SIGNAL(&g_pCB->ObjPool[g_pCB->FunctionParams.AsyncExt.ActionIndex].SyncObj);
1721  }
1722 
1723  SL_DRV_PROTECTION_OBJ_UNLOCK();
1724 
1725  return SL_OS_RET_CODE_OK;
1726 }
1727 
1728 _i16 sl_Select(_i16 nfds, SlFdSet_t *readsds, SlFdSet_t *writesds, SlFdSet_t *exceptsds, struct SlTimeval_t *timeout)
1729 {
1730  _SlSelectMsg_u Msg;
1731  SlSelectAsyncResponse_t AsyncRsp;
1732  _u8 ObjIdx = MAX_CONCURRENT_ACTIONS;
1733 #if ((defined(SL_RUNTIME_EVENT_REGISTERATION) || defined(slcb_SocketTriggerEventHandler)))
1734  _u8 IsNonBlocking = FALSE;
1735 #endif
1736 
1737  /* verify that this API is allowed. if not allowed then
1738  ignore the API execution and return immediately with an error */
1739  VERIFY_API_ALLOWED(SL_OPCODE_SILO_SOCKET);
1740 
1741 #if ((defined(SL_RUNTIME_EVENT_REGISTERATION) || defined(slcb_SocketTriggerEventHandler)))
1742  if(1 == _SlIsEventRegistered(SL_EVENT_HDL_SOCKET_TRIGGER))
1743  {
1744  if( NULL != timeout )
1745  {
1746  /* Set that we are in Non-Blocking mode */
1747  if ( (0 == timeout->tv_sec) && (0 == timeout->tv_usec) )
1748  {
1749  IsNonBlocking = TRUE;
1750  }
1751  else
1752  {
1753  SL_DRV_PROTECTION_OBJ_LOCK_FOREVER();
1754 
1755  /* If there is a trigger select running in the progress abort the new blocking request */
1756  if (g_pCB->SocketTriggerSelect.Info.State > SOCK_TRIGGER_READY)
1757  {
1758  SL_DRV_PROTECTION_OBJ_UNLOCK();
1759  return SL_RET_CODE_SOCKET_SELECT_IN_PROGRESS_ERROR;
1760  }
1761 
1762  SL_DRV_PROTECTION_OBJ_UNLOCK();
1763  }
1764 
1765  if (IsNonBlocking == TRUE)
1766  {
1767  /* return EAGAIN if we alreay have select trigger in progress */
1768  if (g_pCB->SocketTriggerSelect.Info.State == SOCK_TRIGGER_WAITING_FOR_RESP)
1769  {
1770  return SL_ERROR_BSD_EAGAIN;
1771  }
1772  /* return the stored response if already received */
1773  else if (g_pCB->SocketTriggerSelect.Info.State == SOCK_TRIGGER_RESP_RECEIVED)
1774  {
1775 
1776  if( ((_i16)g_pCB->SocketTriggerSelect.Resp.Status) >= 0 )
1777  {
1778  if( readsds )
1779  {
1780  readsds->fd_array[0] = g_pCB->SocketTriggerSelect.Resp.ReadFds;
1781  }
1782  if( writesds )
1783  {
1784  writesds->fd_array[0] = g_pCB->SocketTriggerSelect.Resp.WriteFds;
1785  }
1786  }
1787 
1788  /* Now relaese the pool object */
1789  _SlDrvReleasePoolObj(g_pCB->SocketTriggerSelect.Info.ObjPoolIdx);
1790 
1791  g_pCB->SocketTriggerSelect.Info.ObjPoolIdx = MAX_CONCURRENT_ACTIONS;
1792 
1793  /* Reset the socket select trigger object */
1794  g_pCB->SocketTriggerSelect.Info.State = SOCK_TRIGGER_READY;
1795 
1796  return (_i16)g_pCB->SocketTriggerSelect.Resp.Status;
1797  }
1798  }
1799  }
1800  }
1801 #endif
1802 
1803  Msg.Cmd.Nfds = (_u8)nfds;
1804  Msg.Cmd.ReadFdsCount = 0;
1805  Msg.Cmd.WriteFdsCount = 0;
1806 
1807  Msg.Cmd.ReadFds = 0;
1808  Msg.Cmd.WriteFds = 0;
1809 
1810 
1811  if( readsds )
1812  {
1813  Msg.Cmd.ReadFds = (_u16)readsds->fd_array[0];
1814  }
1815  if( writesds )
1816  {
1817  Msg.Cmd.WriteFds = (_u16)writesds->fd_array[0];
1818  }
1819  if( NULL == timeout )
1820  {
1821  Msg.Cmd.tv_sec = 0xffff;
1822  Msg.Cmd.tv_usec = 0xffff;
1823  }
1824  else
1825  {
1826  if( 0xffff <= timeout->tv_sec )
1827  {
1828  Msg.Cmd.tv_sec = 0xffff;
1829  }
1830  else
1831  {
1832  Msg.Cmd.tv_sec = (_u16)timeout->tv_sec;
1833  }
1834 
1835  /* convert to milliseconds */
1836  timeout->tv_usec = timeout->tv_usec >> 10;
1837 
1838  if( 0xffff <= timeout->tv_usec )
1839  {
1840  Msg.Cmd.tv_usec = 0xffff;
1841  }
1842  else
1843  {
1844  Msg.Cmd.tv_usec = (_u16)timeout->tv_usec;
1845  }
1846 
1847  }
1848 
1849  /* Use Obj to issue the command, if not available try later */
1850  ObjIdx = _SlDrvProtectAsyncRespSetting((_u8*)&AsyncRsp, SELECT_ID, SL_MAX_SOCKETS);
1851 
1852  if (MAX_CONCURRENT_ACTIONS == ObjIdx)
1853  {
1854  return SL_POOL_IS_EMPTY;
1855  }
1856 
1857  /* send the command */
1858  VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlSelectCmdCtrl, &Msg, NULL));
1859 
1860  if(SL_OS_RET_CODE_OK == (_i16)Msg.Rsp.status)
1861  {
1862  SL_DRV_SYNC_OBJ_WAIT_FOREVER(&g_pCB->ObjPool[ObjIdx].SyncObj);
1863 
1864  Msg.Rsp.status = (_i16)AsyncRsp.Status;
1865 
1866  /* this code handles the socket trigger mode case */
1867 #if((defined(SL_RUNTIME_EVENT_REGISTERATION) || defined(slcb_SocketTriggerEventHandler)))
1868  if(1 == _SlIsEventRegistered(SL_EVENT_HDL_SOCKET_TRIGGER))
1869  {
1870  /* if no data returned and we are in trigger mode,
1871  send another select cmd but now with timeout infinite,
1872  and return immediately with EAGAIN to the user */
1873  if ((IsNonBlocking == TRUE) && (AsyncRsp.Status == 0))
1874  {
1875  /* set the select trigger-in-progress bit */
1876  g_pCB->SocketTriggerSelect.Info.State = SOCK_TRIGGER_WAITING_FOR_RESP;
1877 
1878  Msg.Cmd.tv_sec = 0xffff;
1879  Msg.Cmd.tv_usec = 0xffff;
1880 
1881  /* Release pool object and try to take another call */
1882  _SlDrvReleasePoolObj(ObjIdx);
1883 
1884  /* Use Obj to issue the command, if not available try later */
1885  ObjIdx = _SlDrvProtectAsyncRespSetting((_u8*)&g_pCB->SocketTriggerSelect.Resp, SELECT_ID, SL_MAX_SOCKETS);
1886 
1887  if (MAX_CONCURRENT_ACTIONS == ObjIdx)
1888  {
1889  return SL_POOL_IS_EMPTY;
1890  }
1891 
1892  /* Save the pool index to be released only after the user read the response */
1893  g_pCB->SocketTriggerSelect.Info.ObjPoolIdx = ObjIdx;
1894 
1895  /* send the command */
1896  VERIFY_RET_OK(_SlDrvCmdOp((_SlCmdCtrl_t *)&_SlSelectCmdCtrl, &Msg, NULL));
1897  return SL_ERROR_BSD_EAGAIN;
1898 
1899  }
1900  }
1901 #endif
1902 
1903  if( ((_i16)Msg.Rsp.status) >= 0 )
1904  {
1905  if( readsds )
1906  {
1907  readsds->fd_array[0] = AsyncRsp.ReadFds;
1908  }
1909  if( writesds )
1910  {
1911  writesds->fd_array[0] = AsyncRsp.WriteFds;
1912  }
1913  }
1914  }
1915 
1916  _SlDrvReleasePoolObj(ObjIdx);
1917  return (_i16)Msg.Rsp.status;
1918 }
1919 
1920 #endif /* defined(SL_PLATFORM_MULTI_THREADED) || !defined(slcb_SocketTriggerEventHandler) */
1921 #endif /* _SL_INCLUDE_FUNC(sl_Select) */
1922 #endif /* SL_TINY */
_i16 sl_Bind(_i16 sd, const SlSockAddr_t *addr, _i16 addrlen)
Assign a name to a socket.
Definition: sl_socket.c:247
_u32 sl_Htonl(_u32 val)
Reorder the bytes of a 32-bit unsigned value.
Definition: sl_socket.c:813
_i16 sl_Select(_i16 nfds, SlFdSet_t *readsds, SlFdSet_t *writesds, SlFdSet_t *exceptsds, struct SlTimeval_t *timeout)
Monitor socket activity.
Definition: sl_socket.c:1514
void slcb_SocketTriggerEventHandler(SlSockTriggerEvent_t *pSlSockTriggerEvent)
Socket trigger routine. This routine will notify the application that a netwrok activity has been com...
_i16 sl_SetSockOpt(_i16 sd, _i16 level, _i16 optname, const void *optval, SlSocklen_t optlen)
Set socket options-.
Definition: sl_socket.c:943
_u32 slcb_GetTimestamp(void)
Get the timer counter value (timestamp). The timer must count from zero to its MAX value...
_u16 sl_Htons(_u16 val)
Reorder the bytes of a 16-bit unsigned value.
Definition: sl_socket.c:834
_i16 sl_Close(_i16 sd)
Gracefully close socket.
Definition: sl_socket.c:187
_i16 sl_Recv(_i16 sd, void *pBuf, _i16 Len, _i16 flags)
Read data from TCP socket.
Definition: sl_socket.c:892
_i16 sl_GetSockOpt(_i16 sd, _i16 level, _i16 optname, void *optval, SlSocklen_t *optlen)
Get socket options.
Definition: sl_socket.c:986
_i16 sl_Socket(_i16 Domain, _i16 Type, _i16 Protocol)
Create an endpoint for communication.
Definition: sl_socket.c:143
_i16 sl_RecvFrom(_i16 sd, void *buf, _i16 Len, _i16 flags, SlSockAddr_t *from, SlSocklen_t *fromlen)
Read data from socket.
Definition: sl_socket.c:375
_i16 sl_Accept(_i16 sd, SlSockAddr_t *addr, SlSocklen_t *addrlen)
Accept a connection on a socket.
Definition: sl_socket.c:708
Definition: driver.h:301
_i16 sl_Connect(_i16 sd, const SlSockAddr_t *addr, _i16 addrlen)
Initiate a connection on a socket.
Definition: sl_socket.c:464
_i16 sl_Listen(_i16 sd, _i16 backlog)
Listen for connections on a socket.
Definition: sl_socket.c:672
_i16 sl_SendTo(_i16 sd, const void *pBuf, _i16 Len, _i16 flags, const SlSockAddr_t *to, SlSocklen_t tolen)
Write data to socket.
Definition: sl_socket.c:296
_i16 sl_Send(_i16 sd, const void *pBuf, _i16 Len, _i16 flags)
Write data to TCP socket.
Definition: sl_socket.c:606