PageRenderTime 12ms CodeModel.GetById 3ms app.highlight 27ms RepoModel.GetById 1ms app.codeStats 1ms

/libraries/SimplelinkWifi/utility/socket.c

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