PageRenderTime 49ms CodeModel.GetById 14ms app.highlight 27ms RepoModel.GetById 1ms app.codeStats 1ms

/core-common-lib/CC3000_Host_Driver/socket.c

https://github.com/vk2tds/Spark_Ethernet
C | 1212 lines | 459 code | 163 blank | 590 comment | 39 complexity | f7eaa0671a5d692c4123b52a01fcf07c MD5 | raw file
   1/*****************************************************************************
   2 *
   3 *  socket.c  - CC3000 Host Driver Implementation.
   4 *  Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
   5 *
   6 *  Updated: 14-Feb-2014 David Sidrane <david_s5@usa.net>
   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//! \addtogroup socket_api
  40//! @{
  41//
  42//*****************************************************************************
  43
  44#include <stdio.h>
  45#include <string.h>
  46#include <stdlib.h>
  47#include "hci.h"
  48#include "socket.h"
  49#include "evnt_handler.h"
  50#include "netapp.h"
  51#include "hw_config.h"
  52#include "debug.h"
  53#include "spark_macros.h"
  54
  55
  56
  57//Enable this flag if and only if you must comply with BSD socket 
  58//close() function
  59#ifdef _API_USE_BSD_CLOSE
  60#define close(sd) closesocket(sd)
  61#endif
  62
  63//Enable this flag if and only if you must comply with BSD socket read() and 
  64//write() functions
  65#ifdef _API_USE_BSD_READ_WRITE
  66#define read(sd, buf, len, flags) recv(sd, buf, len, flags)
  67#define write(sd, buf, len, flags) send(sd, buf, len, flags)
  68#endif
  69
  70#define SOCKET_OPEN_PARAMS_LEN				(12)
  71#define SOCKET_CLOSE_PARAMS_LEN				(4)
  72#define SOCKET_ACCEPT_PARAMS_LEN			(4)
  73#define SOCKET_BIND_PARAMS_LEN				(20)
  74#define SOCKET_LISTEN_PARAMS_LEN			(8)
  75#define SOCKET_GET_HOST_BY_NAME_PARAMS_LEN	(9)
  76#define SOCKET_CONNECT_PARAMS_LEN			(20)
  77#define SOCKET_SELECT_PARAMS_LEN			(44)
  78#define SOCKET_SET_SOCK_OPT_PARAMS_LEN		(20)
  79#define SOCKET_GET_SOCK_OPT_PARAMS_LEN		(12)
  80#define SOCKET_RECV_FROM_PARAMS_LEN			(12)
  81#define SOCKET_SENDTO_PARAMS_LEN			(24)
  82#define SOCKET_MDNS_ADVERTISE_PARAMS_LEN	(12)
  83#define SOCKET_GET_MSS_VALUE_PARAMS_LEN		(4)
  84
  85// The legnth of arguments for the SEND command: sd + buff_offset + len + flags, 
  86// while size of each parameter is 32 bit - so the total length is 16 bytes;
  87
  88#define HCI_CMND_SEND_ARG_LENGTH	(16)
  89
  90
  91#define SELECT_TIMEOUT_MIN_MICRO_SECONDS  5000
  92
  93#define HEADERS_SIZE_DATA       (SPI_HEADER_SIZE + 5)
  94
  95#define SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE  (SPI_HEADER_SIZE + SIMPLE_LINK_HCI_CMND_HEADER_SIZE)
  96
  97#define MDNS_DEVICE_SERVICE_MAX_LENGTH 	(32)
  98
  99
 100//*****************************************************************************
 101//
 102//! HostFlowControlConsumeBuff
 103//!
 104//!  @param  sd  socket descriptor
 105//!
 106//!  @return 0 in case there are buffers available, 
 107//!          -1 in case of bad socket
 108//!          -2 if there are no free buffers present (only when 
 109//!          SEND_NON_BLOCKING is enabled)
 110//!
 111//!  @brief  if SEND_NON_BLOCKING not define - block until have free buffer 
 112//!          becomes available, else return immediately  with correct status 
 113//!          regarding the buffers available.
 114//
 115//*****************************************************************************
 116INT16 HostFlowControlConsumeBuff(INT16 sd)
 117{
 118#ifndef SEND_NON_BLOCKING
 119	/* wait in busy loop */
 120	volatile system_tick_t start = GetSystem1MsTick();
 121
 122	do
 123	{
 124		// In case last transmission failed then we will return the last failure 
 125		// reason here.
 126		// Note that the buffer will not be allocated in this case
 127		if (tSLInformation.slTransmitDataError != 0)
 128		{
 129			errno = tSLInformation.slTransmitDataError;
 130			tSLInformation.slTransmitDataError = 0;
 131			return errno;
 132		}
 133
 134		if(SOCKET_STATUS_ACTIVE != get_socket_active_status(sd)) {
 135			return -1;
 136		}
 137
 138		volatile system_tick_t now = GetSystem1MsTick();
 139		volatile long elapsed = now - start;
 140		if (elapsed < 0) { // Did we wrap
 141			elapsed = start + now; // yes now
 142		}
 143		if (elapsed >= cc3000__event_timeout_ms) {
 144			ERROR("Timeout waiting on on buffers now %ld start %ld elapsed %ld cc3000__event_timeout_ms %ld",now,start,elapsed,cc3000__event_timeout_ms);
 145			return -1;
 146		}
 147
 148	} while(0 == tSLInformation.usNumberOfFreeBuffers);
 149
 150	tSLInformation.usNumberOfFreeBuffers--;
 151
 152	return 0;
 153#else
 154
 155	// In case last transmission failed then we will return the last failure 
 156	// reason here.
 157	// Note that the buffer will not be allocated in this case
 158	if (tSLInformation.slTransmitDataError != 0)
 159	{
 160		errno = tSLInformation.slTransmitDataError;
 161		tSLInformation.slTransmitDataError = 0;
 162		return errno;
 163	}
 164	if(SOCKET_STATUS_ACTIVE != get_socket_active_status(sd))
 165		return -1;
 166
 167	//If there are no available buffers, return -2. It is recommended to use  
 168	// select or receive to see if there is any buffer occupied with received data
 169	// If so, call receive() to release the buffer.
 170	if(0 == tSLInformation.usNumberOfFreeBuffers)
 171	{
 172		return -2;
 173	}
 174	else
 175	{
 176		tSLInformation.usNumberOfFreeBuffers--;
 177		return 0;
 178	}
 179#endif
 180}
 181
 182//*****************************************************************************
 183//
 184//! socket
 185//!
 186//!  @param  domain    selects the protocol family which will be used for 
 187//!                    communication. On this version only AF_INET is supported
 188//!  @param  type      specifies the communication semantics. On this version 
 189//!                    only SOCK_STREAM, SOCK_DGRAM, SOCK_RAW are supported
 190//!  @param  protocol  specifies a particular protocol to be used with the 
 191//!                    socket IPPROTO_TCP, IPPROTO_UDP or IPPROTO_RAW are 
 192//!                    supported.
 193//!
 194//!  @return  On success, socket handle that is used for consequent socket 
 195//!           operations. On error, -1 is returned.
 196//!
 197//!  @brief  create an endpoint for communication
 198//!          The socket function creates a socket that is bound to a specific 
 199//!          transport service provider. This function is called by the 
 200//!          application layer to obtain a socket handle.
 201//
 202//*****************************************************************************
 203
 204INT16 socket(INT32 domain, INT32 type, INT32 protocol)
 205{
 206	INT32 ret;
 207	UINT8 *ptr, *args;
 208
 209	ret = EFAIL;
 210	ptr = tSLInformation.pucTxCommandBuffer;
 211	args = (ptr + HEADERS_SIZE_CMD);
 212
 213	// Fill in HCI packet structure
 214	args = UINT32_TO_STREAM(args, domain);
 215	args = UINT32_TO_STREAM(args, type);
 216	args = UINT32_TO_STREAM(args, protocol);
 217
 218	// Initiate a HCI command
 219	hci_command_send(HCI_CMND_SOCKET, ptr, SOCKET_OPEN_PARAMS_LEN);
 220
 221	// Since we are in blocking state - wait for event complete
 222	SimpleLinkWaitEvent(HCI_CMND_SOCKET, &ret);
 223
 224	// Process the event 
 225	errno = ret;
 226
 227	set_socket_active_status(ret, SOCKET_STATUS_ACTIVE);
 228
 229	return(ret);
 230}
 231
 232//*****************************************************************************
 233//
 234//! closesocket
 235//!
 236//!  @param  sd    socket handle.
 237//!
 238//!  @return  On success, zero is returned. On error, -1 is returned.
 239//!
 240//!  @brief  The socket function closes a created socket.
 241//
 242//*****************************************************************************
 243
 244INT32 closesocket(INT32 sd)
 245{
 246	INT32 ret;
 247	UINT8 *ptr, *args;
 248
 249	ret = EFAIL;
 250	ptr = tSLInformation.pucTxCommandBuffer;
 251	args = (ptr + HEADERS_SIZE_CMD);
 252
 253	// Fill in HCI packet structure
 254	args = UINT32_TO_STREAM(args, sd);
 255
 256	// Initiate a HCI command
 257	hci_command_send(HCI_CMND_CLOSE_SOCKET,
 258			ptr, SOCKET_CLOSE_PARAMS_LEN);
 259
 260	// Since we are in blocking state - wait for event complete
 261	SimpleLinkWaitEvent(HCI_CMND_CLOSE_SOCKET, &ret);
 262	errno = ret;
 263
 264	// since 'close' call may result in either OK (and then it closed) or error 
 265	// mark this socket as invalid 
 266	set_socket_active_status(sd, SOCKET_STATUS_INACTIVE);
 267
 268	return(ret);
 269}
 270
 271//*****************************************************************************
 272//
 273//! accept
 274//!
 275//!  @param[in]   sd      socket descriptor (handle)              
 276//!  @param[out]  addr    the argument addr is a pointer to a sockaddr structure
 277//!                       This structure is filled in with the address of the  
 278//!                       peer socket, as known to the communications layer.        
 279//!                       determined. The exact format of the address returned             
 280//!                       addr is by the socket's address sockaddr. 
 281//!                       On this version only AF_INET is supported.
 282//!                       This argument returns in network order.
 283//!  @param[out] addrlen  the addrlen argument is a value-result argument: 
 284//!                       it should initially contain the size of the structure
 285//!                       pointed to by addr.
 286//!
 287//!  @return  For socket in blocking mode:
 288//!				      On success, socket handle. on failure negative
 289//!			      For socket in non-blocking mode:
 290//!				     - On connection establishment, socket handle
 291//!				     - On connection pending, SOC_IN_PROGRESS (-2)
 292//!			       - On failure, SOC_ERROR	(-1)
 293//!
 294//!  @brief  accept a connection on a socket:
 295//!          This function is used with connection-based socket types 
 296//!          (SOCK_STREAM). It extracts the first connection request on the 
 297//!          queue of pending connections, creates a new connected socket, and
 298//!          returns a new file descriptor referring to that socket.
 299//!          The newly created socket is not in the listening state. 
 300//!          The original socket sd is unaffected by this call. 
 301//!          The argument sd is a socket that has been created with socket(),
 302//!          bound to a local address with bind(), and is  listening for 
 303//!          connections after a listen(). The argument addr is a pointer 
 304//!          to a sockaddr structure. This structure is filled in with the 
 305//!          address of the peer socket, as known to the communications layer.
 306//!          The exact format of the address returned addr is determined by the 
 307//!          socket's address family. The addrlen argument is a value-result
 308//!          argument: it should initially contain the size of the structure
 309//!          pointed to by addr, on return it will contain the actual 
 310//!          length (in bytes) of the address returned.
 311//!
 312//! @sa     socket ; bind ; listen
 313//
 314//*****************************************************************************
 315
 316INT32 accept(INT32 sd, sockaddr *addr, socklen_t *addrlen)
 317{
 318	INT32 ret;
 319	UINT8 *ptr, *args;
 320	tBsdReturnParams tAcceptReturnArguments;
 321
 322	ret = EFAIL;
 323	ptr = tSLInformation.pucTxCommandBuffer;
 324	args = (ptr + HEADERS_SIZE_CMD);
 325
 326	// Fill in temporary command buffer
 327	args = UINT32_TO_STREAM(args, sd);
 328
 329	// Initiate a HCI command
 330	hci_command_send(HCI_CMND_ACCEPT,
 331			ptr, SOCKET_ACCEPT_PARAMS_LEN);
 332
 333	// Since we are in blocking state - wait for event complete
 334	SimpleLinkWaitEvent(HCI_CMND_ACCEPT, &tAcceptReturnArguments);
 335
 336
 337	// need specify return parameters!!!
 338	memcpy(addr, &tAcceptReturnArguments.tSocketAddress, ASIC_ADDR_LEN);
 339	*addrlen = ASIC_ADDR_LEN;
 340	errno = tAcceptReturnArguments.iStatus; 
 341	ret = errno;
 342
 343	// if succeeded, iStatus = new socket descriptor. otherwise - error number 
 344	if(M_IS_VALID_SD(ret))
 345	{
 346		set_socket_active_status(ret, SOCKET_STATUS_ACTIVE);
 347	}
 348	else
 349	{
 350		set_socket_active_status(sd, SOCKET_STATUS_INACTIVE);
 351	}
 352
 353	return(ret);
 354}
 355
 356//*****************************************************************************
 357//
 358//! bind
 359//!
 360//!  @param[in]   sd      socket descriptor (handle)              
 361//!  @param[out]  addr    specifies the destination address. On this version 
 362//!                       only AF_INET is supported.
 363//!  @param[out] addrlen  contains the size of the structure pointed to by addr.
 364//!
 365//!  @return  	On success, zero is returned. On error, -1 is returned.
 366//!
 367//!  @brief  assign a name to a socket
 368//!          This function gives the socket the local address addr.
 369//!          addr is addrlen bytes long. Traditionally, this is called when a 
 370//!          socket is created with socket, it exists in a name space (address 
 371//!          family) but has no name assigned.
 372//!          It is necessary to assign a local address before a SOCK_STREAM
 373//!          socket may receive connections.
 374//!
 375//! @sa     socket ; accept ; listen
 376//
 377//*****************************************************************************
 378
 379INT32 bind(INT32 sd, const sockaddr *addr, INT32 addrlen)
 380{
 381	INT32 ret;
 382	UINT8 *ptr, *args;
 383
 384	ret = EFAIL;
 385	ptr = tSLInformation.pucTxCommandBuffer;
 386	args = (ptr + HEADERS_SIZE_CMD);
 387
 388	addrlen = ASIC_ADDR_LEN;
 389
 390	// Fill in temporary command buffer
 391	args = UINT32_TO_STREAM(args, sd);
 392	args = UINT32_TO_STREAM(args, 0x00000008);
 393	args = UINT32_TO_STREAM(args, addrlen);
 394	ARRAY_TO_STREAM(args, ((UINT8 *)addr), addrlen);
 395
 396	// Initiate a HCI command
 397	hci_command_send(HCI_CMND_BIND,
 398			ptr, SOCKET_BIND_PARAMS_LEN);
 399
 400	// Since we are in blocking state - wait for event complete
 401	SimpleLinkWaitEvent(HCI_CMND_BIND, &ret);
 402
 403	errno = ret;
 404
 405	return(ret);
 406}
 407
 408//*****************************************************************************
 409//
 410//! listen
 411//!
 412//!  @param[in]   sd      socket descriptor (handle)              
 413//!  @param[in]  backlog  specifies the listen queue depth. On this version
 414//!                       backlog is not supported.
 415//!  @return  	On success, zero is returned. On error, -1 is returned.
 416//!
 417//!  @brief  listen for connections on a socket
 418//!          The willingness to accept incoming connections and a queue
 419//!          limit for incoming connections are specified with listen(),
 420//!          and then the connections are accepted with accept.
 421//!          The listen() call applies only to sockets of type SOCK_STREAM
 422//!          The backlog parameter defines the maximum length the queue of
 423//!          pending connections may grow to. 
 424//!
 425//! @sa     socket ; accept ; bind
 426//!
 427//! @note   On this version, backlog is not supported
 428//
 429//*****************************************************************************
 430
 431INT32 listen(INT32 sd, INT32 backlog)
 432{
 433	INT32 ret;
 434	UINT8 *ptr, *args;
 435
 436	ret = EFAIL;
 437	ptr = tSLInformation.pucTxCommandBuffer;
 438	args = (ptr + HEADERS_SIZE_CMD);
 439
 440	// Fill in temporary command buffer
 441	args = UINT32_TO_STREAM(args, sd);
 442	args = UINT32_TO_STREAM(args, backlog);
 443
 444	// Initiate a HCI command
 445	hci_command_send(HCI_CMND_LISTEN,
 446			ptr, SOCKET_LISTEN_PARAMS_LEN);
 447
 448	// Since we are in blocking state - wait for event complete
 449	SimpleLinkWaitEvent(HCI_CMND_LISTEN, &ret);
 450	errno = ret;
 451
 452	return(ret);
 453}
 454
 455//*****************************************************************************
 456//
 457//! gethostbyname
 458//!
 459//!  @param[in]   hostname     host name              
 460//!  @param[in]   usNameLen    name length 
 461//!  @param[out]  out_ip_addr  This parameter is filled in with host IP address. 
 462//!                            In case that host name is not resolved, 
 463//!                            out_ip_addr is zero.                  
 464//!  @return  	On success, positive is returned. On error, negative is returned
 465//!
 466//!  @brief  Get host IP by name. Obtain the IP Address of machine on network, 
 467//!          by its name.
 468//!
 469//!  @note  On this version, only blocking mode is supported. Also note that
 470//!		     the function requires DNS server to be configured prior to its usage.
 471//
 472//*****************************************************************************
 473
 474#ifndef CC3000_TINY_DRIVER
 475INT16 gethostbyname(CHAR * hostname, UINT16 usNameLen, 
 476		UINT32* out_ip_addr)
 477{
 478	tBsdGethostbynameParams ret;
 479	UINT8 *ptr, *args;
 480
 481	errno = EFAIL;
 482
 483	if (usNameLen > HOSTNAME_MAX_LENGTH)
 484	{
 485		return errno;
 486	}
 487
 488	ptr = tSLInformation.pucTxCommandBuffer;
 489	args = (ptr + SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE);
 490
 491	// Fill in HCI packet structure
 492	args = UINT32_TO_STREAM(args, 8);
 493	args = UINT32_TO_STREAM(args, usNameLen);
 494	ARRAY_TO_STREAM(args, hostname, usNameLen);
 495
 496	// Initiate a HCI command
 497	hci_command_send(HCI_CMND_GETHOSTNAME, ptr, SOCKET_GET_HOST_BY_NAME_PARAMS_LEN
 498			+ usNameLen - 1);
 499
 500	// Since we are in blocking state - wait for event complete
 501	SimpleLinkWaitEvent(HCI_EVNT_BSD_GETHOSTBYNAME, &ret);
 502
 503	errno = ret.retVal;
 504
 505	(*((INT32*)out_ip_addr)) = ret.outputAddress;
 506
 507	return (errno);
 508
 509}
 510#endif
 511
 512//*****************************************************************************
 513//
 514//! connect
 515//!
 516//!  @param[in]   sd       socket descriptor (handle)         
 517//!  @param[in]   addr     specifies the destination addr. On this version
 518//!                        only AF_INET is supported.
 519//!  @param[out]  addrlen  contains the size of the structure pointed to by addr    
 520//!  @return  	On success, zero is returned. On error, -1 is returned
 521//!
 522//!  @brief  initiate a connection on a socket 
 523//!          Function connects the socket referred to by the socket descriptor 
 524//!          sd, to the address specified by addr. The addrlen argument 
 525//!          specifies the size of addr. The format of the address in addr is 
 526//!          determined by the address space of the socket. If it is of type 
 527//!          SOCK_DGRAM, this call specifies the peer with which the socket is 
 528//!          to be associated; this address is that to which datagrams are to be
 529//!          sent, and the only address from which datagrams are to be received.  
 530//!          If the socket is of type SOCK_STREAM, this call attempts to make a 
 531//!          connection to another socket. The other socket is specified  by 
 532//!          address, which is an address in the communications space of the
 533//!          socket. Note that the function implements only blocking behavior 
 534//!          thus the caller will be waiting either for the connection 
 535//!          establishment or for the connection establishment failure.
 536//!
 537//!  @sa socket
 538//
 539//*****************************************************************************
 540
 541INT32 connect(INT32 sd, const sockaddr *addr, INT32 addrlen)
 542{
 543	INT32 ret;
 544	UINT8 *ptr, *args;
 545
 546	ret = EFAIL;
 547	ptr = tSLInformation.pucTxCommandBuffer;
 548	args = (ptr + SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE);
 549	addrlen = 8;
 550
 551	// Fill in temporary command buffer
 552	args = UINT32_TO_STREAM(args, sd);
 553	args = UINT32_TO_STREAM(args, 0x00000008);
 554	args = UINT32_TO_STREAM(args, addrlen);
 555	ARRAY_TO_STREAM(args, ((UINT8 *)addr), addrlen);
 556
 557	// Initiate a HCI command
 558	hci_command_send(HCI_CMND_CONNECT,
 559			ptr, SOCKET_CONNECT_PARAMS_LEN);
 560
 561	// Since we are in blocking state - wait for event complete
 562	SimpleLinkWaitEvent(HCI_CMND_CONNECT, &ret);
 563
 564	errno = ret;
 565
 566	return((INT32)ret);
 567}
 568
 569
 570//*****************************************************************************
 571//
 572//! select
 573//!
 574//!  @param[in]   nfds       the highest-numbered file descriptor in any of the
 575//!                           three sets, plus 1.     
 576//!  @param[out]   writesds   socket descriptors list for write monitoring
 577//!  @param[out]   readsds    socket descriptors list for read monitoring  
 578//!  @param[out]   exceptsds  socket descriptors list for exception monitoring
 579//!  @param[in]   timeout     is an upper bound on the amount of time elapsed
 580//!                           before select() returns. Null means infinity 
 581//!                           timeout. The minimum timeout is 5 milliseconds,
 582//!                          less than 5 milliseconds will be set
 583//!                           automatically to 5 milliseconds.
 584//!  @return  	On success, select() returns the number of file descriptors
 585//!             contained in the three returned descriptor sets (that is, the
 586//!             total number of bits that are set in readfds, writefds,
 587//!             exceptfds) which may be zero if the timeout expires before
 588//!             anything interesting  happens.
 589//!             On error, -1 is returned.
 590//!                   *readsds - return the sockets on which Read request will
 591//!                              return without delay with valid data.
 592//!                   *writesds - return the sockets on which Write request 
 593//!                                 will return without delay.
 594//!                   *exceptsds - return the sockets which closed recently.
 595//!
 596//!  @brief  Monitor socket activity  
 597//!          Select allow a program to monitor multiple file descriptors,
 598//!          waiting until one or more of the file descriptors become 
 599//!         "ready" for some class of I/O operation 
 600//!
 601//!  @Note   If the timeout value set to less than 5ms it will automatically set
 602//!          to 5ms to prevent overload of the system
 603//!
 604//!  @sa socket
 605//
 606//*****************************************************************************
 607
 608INT16 select(INT32 nfds, fd_set *readsds, fd_set *writesds, fd_set *exceptsds, 
 609		struct timeval *timeout)
 610{
 611	UINT8 *ptr, *args;
 612	tBsdSelectRecvParams tParams;
 613	UINT32 is_blocking;
 614
 615	if( timeout == NULL)
 616	{
 617		is_blocking = 1; /* blocking , infinity timeout */
 618	}
 619	else
 620	{
 621		is_blocking = 0; /* no blocking, timeout */
 622	}
 623
 624	// Fill in HCI packet structure
 625	ptr = tSLInformation.pucTxCommandBuffer;
 626	args = (ptr + HEADERS_SIZE_CMD);
 627
 628	// Fill in temporary command buffer
 629	args = UINT32_TO_STREAM(args, nfds);
 630	args = UINT32_TO_STREAM(args, 0x00000014);
 631	args = UINT32_TO_STREAM(args, 0x00000014);
 632	args = UINT32_TO_STREAM(args, 0x00000014);
 633	args = UINT32_TO_STREAM(args, 0x00000014);
 634	args = UINT32_TO_STREAM(args, is_blocking);
 635	args = UINT32_TO_STREAM(args, ((readsds) ? *(UINT32*)readsds : 0));
 636	args = UINT32_TO_STREAM(args, ((writesds) ? *(UINT32*)writesds : 0));
 637	args = UINT32_TO_STREAM(args, ((exceptsds) ? *(UINT32*)exceptsds : 0));
 638
 639	if (timeout)
 640	{
 641		if ( 0 == timeout->tv_sec && timeout->tv_usec < 
 642				SELECT_TIMEOUT_MIN_MICRO_SECONDS)
 643		{
 644			timeout->tv_usec = SELECT_TIMEOUT_MIN_MICRO_SECONDS;
 645		}
 646		args = UINT32_TO_STREAM(args, timeout->tv_sec);
 647		args = UINT32_TO_STREAM(args, timeout->tv_usec);
 648	}
 649
 650	// Initiate a HCI command
 651	hci_command_send(HCI_CMND_BSD_SELECT, ptr, SOCKET_SELECT_PARAMS_LEN);
 652
 653	// Since we are in blocking state - wait for event complete
 654	SimpleLinkWaitEvent(HCI_EVNT_SELECT, &tParams);
 655
 656	// Update actually read FD
 657	if (tParams.iStatus >= 0)
 658	{
 659		if (readsds)
 660		{
 661			memcpy(readsds, &tParams.uiRdfd, sizeof(tParams.uiRdfd));
 662		}
 663
 664		if (writesds)
 665		{
 666			memcpy(writesds, &tParams.uiWrfd, sizeof(tParams.uiWrfd)); 
 667		}
 668
 669		if (exceptsds)
 670		{
 671			memcpy(exceptsds, &tParams.uiExfd, sizeof(tParams.uiExfd)); 
 672		}
 673
 674		return(tParams.iStatus);
 675
 676	}
 677	else
 678	{
 679		errno = tParams.iStatus;
 680		return(-1);
 681	}
 682}
 683
 684//*****************************************************************************
 685//
 686//! setsockopt
 687//!
 688//!  @param[in]   sd          socket handle
 689//!  @param[in]   level       defines the protocol level for this option
 690//!  @param[in]   optname     defines the option name to Interrogate
 691//!  @param[in]   optval      specifies a value for the option
 692//!  @param[in]   optlen      specifies the length of the option value
 693//!  @return  	On success, zero is returned. On error, -1 is returned
 694//!
 695//!  @brief  set socket options
 696//!          This function manipulate the options associated with a socket.
 697//!          Options may exist at multiple protocol levels; they are always
 698//!          present at the uppermost socket level.
 699//!          When manipulating socket options the level at which the option 
 700//!          resides and the name of the option must be specified.  
 701//!          To manipulate options at the socket level, level is specified as 
 702//!          SOL_SOCKET. To manipulate options at any other level the protocol 
 703//!          number of the appropriate protocol controlling the option is 
 704//!          supplied. For example, to indicate that an option is to be 
 705//!          interpreted by the TCP protocol, level should be set to the 
 706//!          protocol number of TCP; 
 707//!          The parameters optval and optlen are used to access optval - 
 708//!          use for setsockopt(). For getsockopt() they identify a buffer
 709//!          in which the value for the requested option(s) are to 
 710//!          be returned. For getsockopt(), optlen is a value-result 
 711//!          parameter, initially containing the size of the buffer 
 712//!          pointed to by option_value, and modified on return to 
 713//!          indicate the actual size of the value returned. If no option 
 714//!          value is to be supplied or returned, option_value may be NULL.
 715//!
 716//!  @Note   On this version the following two socket options are enabled:
 717//!    			 The only protocol level supported in this version
 718//!          is SOL_SOCKET (level).
 719//!		       1. SOCKOPT_RECV_TIMEOUT (optname)
 720//!			      SOCKOPT_RECV_TIMEOUT configures recv and recvfrom timeout 
 721//!           in milliseconds.
 722//!		        In that case optval should be pointer to UINT32.
 723//!		       2. SOCKOPT_NONBLOCK (optname). sets the socket non-blocking mode on 
 724//!           or off.
 725//!		        In that case optval should be SOCK_ON or SOCK_OFF (optval).
 726//!
 727//!  @sa getsockopt
 728//
 729//*****************************************************************************
 730
 731#ifndef CC3000_TINY_DRIVER
 732INT16 setsockopt(INT32 sd, INT32 level, INT32 optname, const void *optval,
 733		socklen_t optlen)
 734{
 735	INT32 ret;
 736	UINT8 *ptr, *args;
 737
 738	ptr = tSLInformation.pucTxCommandBuffer;
 739	args = (ptr + HEADERS_SIZE_CMD);
 740
 741	// Fill in temporary command buffer
 742	args = UINT32_TO_STREAM(args, sd);
 743	args = UINT32_TO_STREAM(args, level);
 744	args = UINT32_TO_STREAM(args, optname);
 745	args = UINT32_TO_STREAM(args, 0x00000008);
 746	args = UINT32_TO_STREAM(args, optlen);
 747	ARRAY_TO_STREAM(args, ((UINT8 *)optval), optlen);
 748
 749	// Initiate a HCI command
 750	hci_command_send(HCI_CMND_SETSOCKOPT,
 751			ptr, SOCKET_SET_SOCK_OPT_PARAMS_LEN  + optlen);
 752
 753	// Since we are in blocking state - wait for event complete
 754	SimpleLinkWaitEvent(HCI_CMND_SETSOCKOPT, &ret);
 755
 756	if (ret >= 0)
 757	{
 758		return (0);
 759	}
 760	else
 761	{
 762		errno = ret;
 763		return ret;
 764	}
 765}
 766#endif
 767
 768//*****************************************************************************
 769//
 770//! getsockopt
 771//!
 772//!  @param[in]   sd          socket handle
 773//!  @param[in]   level       defines the protocol level for this option
 774//!  @param[in]   optname     defines the option name to Interrogate
 775//!  @param[out]   optval      specifies a value for the option
 776//!  @param[out]   optlen      specifies the length of the option value
 777//!  @return  	On success, zero is returned. On error, -1 is returned
 778//!
 779//!  @brief  set socket options
 780//!          This function manipulate the options associated with a socket.
 781//!          Options may exist at multiple protocol levels; they are always
 782//!          present at the uppermost socket level.
 783//!          When manipulating socket options the level at which the option 
 784//!          resides and the name of the option must be specified.  
 785//!          To manipulate options at the socket level, level is specified as 
 786//!          SOL_SOCKET. To manipulate options at any other level the protocol 
 787//!          number of the appropriate protocol controlling the option is 
 788//!          supplied. For example, to indicate that an option is to be 
 789//!          interpreted by the TCP protocol, level should be set to the 
 790//!          protocol number of TCP; 
 791//!          The parameters optval and optlen are used to access optval - 
 792//!          use for setsockopt(). For getsockopt() they identify a buffer
 793//!          in which the value for the requested option(s) are to 
 794//!          be returned. For getsockopt(), optlen is a value-result 
 795//!          parameter, initially containing the size of the buffer 
 796//!          pointed to by option_value, and modified on return to 
 797//!          indicate the actual size of the value returned. If no option 
 798//!          value is to be supplied or returned, option_value may be NULL.
 799//!
 800//!  @Note   On this version the following two socket options are enabled:
 801//!    			 The only protocol level supported in this version
 802//!          is SOL_SOCKET (level).
 803//!		       1. SOCKOPT_RECV_TIMEOUT (optname)
 804//!			      SOCKOPT_RECV_TIMEOUT configures recv and recvfrom timeout 
 805//!           in milliseconds.
 806//!		        In that case optval should be pointer to UINT32.
 807//!		       2. SOCKOPT_NONBLOCK (optname). sets the socket non-blocking mode on 
 808//!           or off.
 809//!		        In that case optval should be SOCK_ON or SOCK_OFF (optval).
 810//!
 811//!  @sa setsockopt
 812//
 813//*****************************************************************************
 814
 815INT16 getsockopt (INT32 sd, INT32 level, INT32 optname, void *optval, socklen_t *optlen)
 816{
 817	UINT8 *ptr, *args;
 818	tBsdGetSockOptReturnParams  tRetParams;
 819
 820	ptr = tSLInformation.pucTxCommandBuffer;
 821	args = (ptr + HEADERS_SIZE_CMD);
 822
 823	// Fill in temporary command buffer
 824	args = UINT32_TO_STREAM(args, sd);
 825	args = UINT32_TO_STREAM(args, level);
 826	args = UINT32_TO_STREAM(args, optname);
 827
 828	// Initiate a HCI command
 829	hci_command_send(HCI_CMND_GETSOCKOPT,
 830			ptr, SOCKET_GET_SOCK_OPT_PARAMS_LEN);
 831
 832	// Since we are in blocking state - wait for event complete
 833	SimpleLinkWaitEvent(HCI_CMND_GETSOCKOPT, &tRetParams);
 834
 835	if (((INT8)tRetParams.iStatus) >= 0)
 836	{
 837		*optlen = 4;
 838		memcpy(optval, tRetParams.ucOptValue, 4);
 839		return (0);
 840	}
 841	else
 842	{
 843		errno = tRetParams.iStatus;
 844		return errno;
 845	}
 846}
 847
 848//*****************************************************************************
 849//
 850//!  simple_link_recv
 851//!
 852//!  @param sd       socket handle
 853//!  @param buf      read buffer
 854//!  @param len      buffer length
 855//!  @param flags    indicates blocking or non-blocking operation
 856//!  @param from     pointer to an address structure indicating source address
 857//!  @param fromlen  source address structure size
 858//!
 859//!  @return         Return the number of bytes received, or -1 if an error
 860//!                  occurred
 861//!
 862//!  @brief          Read data from socket
 863//!                  Return the length of the message on successful completion.
 864//!                  If a message is too long to fit in the supplied buffer,
 865//!                  excess bytes may be discarded depending on the type of
 866//!                  socket the message is received from
 867//
 868//*****************************************************************************
 869INT16 simple_link_recv(INT32 sd, void *buf, INT32 len, INT32 flags, sockaddr *from,
 870		socklen_t *fromlen, INT32 opcode)
 871{
 872	UINT8 *ptr, *args;
 873	tBsdReadReturnParams tSocketReadEvent;
 874
 875	ptr = tSLInformation.pucTxCommandBuffer;
 876	args = (ptr + HEADERS_SIZE_CMD);
 877
 878	// Fill in HCI packet structure
 879	args = UINT32_TO_STREAM(args, sd);
 880	args = UINT32_TO_STREAM(args, len);
 881	args = UINT32_TO_STREAM(args, flags);
 882
 883	// Generate the read command, and wait for the 
 884	hci_command_send(opcode,  ptr, SOCKET_RECV_FROM_PARAMS_LEN);
 885
 886	// Since we are in blocking state - wait for event complete
 887	SimpleLinkWaitEvent(opcode, &tSocketReadEvent);
 888
 889	// In case the number of bytes is more then zero - read data
 890	if (tSocketReadEvent.iNumberOfBytes > 0)
 891	{
 892		// Wait for the data in a synchronous way. Here we assume that the bug is 
 893		// big enough to store also parameters of receive from too....
 894		long lenRead; // Let's look at length
 895		SimpleLinkWaitData(buf, (unsigned char *)from, &lenRead);
 896
 897		// return it if wanted
 898		if (fromlen) {
 899			*fromlen =  lenRead;
 900		}
 901		// Error ?
 902		if (lenRead <= 0) {
 903			tSocketReadEvent.iNumberOfBytes = lenRead;
 904		}
 905	}
 906
 907	errno = tSocketReadEvent.iNumberOfBytes;
 908
 909	return(tSocketReadEvent.iNumberOfBytes);
 910}
 911
 912//*****************************************************************************
 913//
 914//!  recv
 915//!
 916//!  @param[in]  sd     socket handle
 917//!  @param[out] buf    Points to the buffer where the message should be stored
 918//!  @param[in]  len    Specifies the length in bytes of the buffer pointed to 
 919//!                     by the buffer argument.
 920//!  @param[in] flags   Specifies the type of message reception. 
 921//!                     On this version, this parameter is not supported.
 922//!
 923//!  @return         Return the number of bytes received, or -1 if an error
 924//!                  occurred
 925//!
 926//!  @brief          function receives a message from a connection-mode socket
 927//!
 928//!  @sa recvfrom
 929//!
 930//!  @Note On this version, only blocking mode is supported.
 931//
 932//*****************************************************************************
 933
 934INT16 recv(INT32 sd, void *buf, INT32 len, INT32 flags)
 935{
 936	return(simple_link_recv(sd, buf, len, flags, NULL, NULL, HCI_CMND_RECV));
 937}
 938
 939//*****************************************************************************
 940//
 941//!  recvfrom
 942//!
 943//!  @param[in]  sd     socket handle
 944//!  @param[out] buf    Points to the buffer where the message should be stored
 945//!  @param[in]  len    Specifies the length in bytes of the buffer pointed to 
 946//!                     by the buffer argument.
 947//!  @param[in] flags   Specifies the type of message reception. 
 948//!                     On this version, this parameter is not supported.
 949//!  @param[in] from   pointer to an address structure indicating the source
 950//!                    address: sockaddr. On this version only AF_INET is
 951//!                    supported.
 952//!  @param[in] fromlen   source address tructure size
 953//!
 954//!  @return         Return the number of bytes received, or -1 if an error
 955//!                  occurred
 956//!
 957//!  @brief         read data from socket
 958//!                 function receives a message from a connection-mode or
 959//!                 connectionless-mode socket. Note that raw sockets are not
 960//!                 supported.
 961//!
 962//!  @sa recv
 963//!
 964//!  @Note On this version, only blocking mode is supported.
 965//
 966//*****************************************************************************
 967INT16 recvfrom(INT32 sd, void *buf, INT32 len, INT32 flags, sockaddr *from,
 968		socklen_t *fromlen)
 969{
 970	return(simple_link_recv(sd, buf, len, flags, from, fromlen,
 971			HCI_CMND_RECVFROM));
 972}
 973
 974//*****************************************************************************
 975//
 976//!  simple_link_send
 977//!
 978//!  @param sd       socket handle
 979//!  @param buf      write buffer
 980//!  @param len      buffer length
 981//!  @param flags    On this version, this parameter is not supported
 982//!  @param to       pointer to an address structure indicating destination
 983//!                  address
 984//!  @param tolen    destination address structure size
 985//!
 986//!  @return         Return the number of bytes transmitted, or -1 if an error
 987//!                  occurred, or -2 in case there are no free buffers available
 988//!                 (only when SEND_NON_BLOCKING is enabled)
 989//!
 990//!  @brief          This function is used to transmit a message to another
 991//!                  socket
 992//
 993//*****************************************************************************
 994INT16 simple_link_send(INT32 sd, const void *buf, INT32 len, INT32 flags,
 995		const sockaddr *to, INT32 tolen, INT32 opcode)
 996{    
 997	UINT8 uArgSize,  addrlen;
 998	UINT8 *ptr, *pDataPtr, *args;
 999	UINT32 addr_offset;
1000	INT16 res;
1001	tBsdReadReturnParams tSocketSendEvent;
1002
1003	// Check the bsd_arguments
1004	if (0 != (res = HostFlowControlConsumeBuff(sd)))
1005	{
1006		return res;
1007	}
1008
1009	//Update the number of sent packets
1010	tSLInformation.NumberOfSentPackets++;
1011
1012	// Allocate a buffer and construct a packet and send it over spi
1013	ptr = tSLInformation.pucTxCommandBuffer;
1014	args = (ptr + HEADERS_SIZE_DATA);
1015
1016	// Update the offset of data and parameters according to the command
1017	switch(opcode)
1018	{ 
1019	case HCI_CMND_SENDTO:
1020	{
1021		addr_offset = len + sizeof(len) + sizeof(len);
1022		addrlen = 8;
1023		uArgSize = SOCKET_SENDTO_PARAMS_LEN;
1024		pDataPtr = ptr + HEADERS_SIZE_DATA + SOCKET_SENDTO_PARAMS_LEN;
1025		break;
1026	}
1027
1028	case HCI_CMND_SEND:
1029	{
1030		tolen = 0;
1031		to = NULL;
1032		uArgSize = HCI_CMND_SEND_ARG_LENGTH;
1033		pDataPtr = ptr + HEADERS_SIZE_DATA + HCI_CMND_SEND_ARG_LENGTH;
1034		break;
1035	}
1036
1037	default:
1038	{
1039		break;
1040	}
1041	}
1042
1043	// Fill in temporary command buffer
1044	args = UINT32_TO_STREAM(args, sd);
1045	args = UINT32_TO_STREAM(args, uArgSize - sizeof(sd));
1046	args = UINT32_TO_STREAM(args, len);
1047	args = UINT32_TO_STREAM(args, flags);
1048
1049	if (opcode == HCI_CMND_SENDTO)
1050	{
1051		args = UINT32_TO_STREAM(args, addr_offset);
1052		args = UINT32_TO_STREAM(args, addrlen);
1053	}
1054
1055	// Copy the data received from user into the TX Buffer
1056	ARRAY_TO_STREAM(pDataPtr, ((UINT8 *)buf), len);
1057
1058	// In case we are using SendTo, copy the to parameters
1059	if (opcode == HCI_CMND_SENDTO)
1060	{	
1061		ARRAY_TO_STREAM(pDataPtr, ((UINT8 *)to), tolen);
1062	}
1063
1064	// Initiate a HCI command
1065	hci_data_send(opcode, ptr, uArgSize, len,(UINT8*)to, tolen);
1066
1067	if (opcode == HCI_CMND_SENDTO)
1068		SimpleLinkWaitEvent(HCI_EVNT_SENDTO, &tSocketSendEvent);
1069	else
1070		SimpleLinkWaitEvent(HCI_EVNT_SEND, &tSocketSendEvent);
1071
1072	return	(tSocketSendEvent.iNumberOfBytes);
1073}
1074
1075
1076//*****************************************************************************
1077//
1078//!  send
1079//!
1080//!  @param sd       socket handle
1081//!  @param buf      Points to a buffer containing the message to be sent
1082//!  @param len      message size in bytes
1083//!  @param flags    On this version, this parameter is not supported
1084//!
1085//!  @return         Return the number of bytes transmitted, or -1 if an
1086//!                  error occurred
1087//!
1088//!  @brief          Write data to TCP socket
1089//!                  This function is used to transmit a message to another 
1090//!                  socket.
1091//!
1092//!  @Note           On this version, only blocking mode is supported.
1093//!
1094//!  @sa             sendto
1095//
1096//*****************************************************************************
1097
1098INT16 send(INT32 sd, const void *buf, INT32 len, INT32 flags)
1099{
1100	return(simple_link_send(sd, buf, len, flags, NULL, 0, HCI_CMND_SEND));
1101}
1102
1103//*****************************************************************************
1104//
1105//!  sendto
1106//!
1107//!  @param sd       socket handle
1108//!  @param buf      Points to a buffer containing the message to be sent
1109//!  @param len      message size in bytes
1110//!  @param flags    On this version, this parameter is not supported
1111//!  @param to       pointer to an address structure indicating the destination
1112//!                  address: sockaddr. On this version only AF_INET is
1113//!                  supported.
1114//!  @param tolen    destination address structure size
1115//!
1116//!  @return         Return the number of bytes transmitted, or -1 if an
1117//!                  error occurred
1118//!
1119//!  @brief          Write data to TCP socket
1120//!                  This function is used to transmit a message to another 
1121//!                  socket.
1122//!
1123//!  @Note           On this version, only blocking mode is supported.
1124//!
1125//!  @sa             send
1126//
1127//*****************************************************************************
1128
1129INT16 sendto(INT32 sd, const void *buf, INT32 len, INT32 flags, const sockaddr *to,
1130		socklen_t tolen)
1131{
1132	return(simple_link_send(sd, buf, len, flags, to, tolen, HCI_CMND_SENDTO));
1133}
1134
1135//*****************************************************************************
1136//
1137//!  mdnsAdvertiser
1138//!
1139//!  @param[in] mdnsEnabled         flag to enable/disable the mDNS feature
1140//!  @param[in] deviceServiceName   Service name as part of the published
1141//!                                 canonical domain name
1142//!  @param[in] deviceServiceNameLength   Length of the service name - up to 32 chars
1143//!  
1144//!
1145//!  @return   On success, zero is returned, return SOC_ERROR if socket was not 
1146//!            opened successfully, or if an error occurred.
1147//!
1148//!  @brief    Set CC3000 in mDNS advertiser mode in order to advertise itself.
1149//
1150//*****************************************************************************
1151
1152INT16 mdnsAdvertiser(UINT16 mdnsEnabled, CHAR * deviceServiceName, UINT16 deviceServiceNameLength)
1153{
1154	INT8 ret;
1155	UINT8 *pTxBuffer, *pArgs;
1156
1157	if (deviceServiceNameLength > MDNS_DEVICE_SERVICE_MAX_LENGTH)
1158	{
1159		return EFAIL;
1160	}
1161
1162	pTxBuffer = tSLInformation.pucTxCommandBuffer;
1163	pArgs = (pTxBuffer + SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE);
1164
1165	// Fill in HCI packet structure
1166	pArgs = UINT32_TO_STREAM(pArgs, mdnsEnabled);
1167	pArgs = UINT32_TO_STREAM(pArgs, 8);
1168	pArgs = UINT32_TO_STREAM(pArgs, deviceServiceNameLength);
1169	ARRAY_TO_STREAM(pArgs, deviceServiceName, deviceServiceNameLength);
1170
1171	// Initiate a HCI command
1172	hci_command_send(HCI_CMND_MDNS_ADVERTISE, pTxBuffer, SOCKET_MDNS_ADVERTISE_PARAMS_LEN + deviceServiceNameLength);
1173
1174	// Since we are in blocking state - wait for event complete
1175	SimpleLinkWaitEvent(HCI_EVNT_MDNS_ADVERTISE, &ret);
1176
1177	return ret;
1178
1179}
1180
1181
1182//*****************************************************************************
1183//
1184//!  getmssvalue
1185//!
1186//!  @param[in] sd         socket descriptor
1187//!
1188//!  @return   On success, returns the MSS value of a TCP connection
1189//!
1190//!  @brief    Returns the MSS value of a TCP connection according to the socket descriptor
1191//
1192//*****************************************************************************
1193UINT16 getmssvalue (INT32 sd)
1194{
1195	UINT8 *ptr, *args;
1196	UINT16 ret;
1197
1198	ptr = tSLInformation.pucTxCommandBuffer;
1199	args = (ptr + HEADERS_SIZE_CMD);
1200
1201	// Fill in temporary command buffer
1202	args = UINT32_TO_STREAM(args, sd);
1203
1204	// Initiate a HCI command
1205	hci_command_send(HCI_CMND_GETMSSVALUE, ptr, SOCKET_GET_MSS_VALUE_PARAMS_LEN);
1206
1207	// Since we are in blocking state - wait for event complete
1208	SimpleLinkWaitEvent(HCI_EVNT_GETMSSVALUE, &ret);
1209
1210	return ret;
1211}
1212