PageRenderTime 73ms CodeModel.GetById 2ms app.highlight 62ms RepoModel.GetById 1ms app.codeStats 0ms

/libs/network/cc3000/socket.c

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