David Fletcher / Mbed 2 deprecated CC3000WebServer

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers socket.cpp Source File

socket.cpp

00001 /*****************************************************************************
00002 *
00003 *  socket.c  - CC3000 Host Driver Implementation.
00004 *  Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
00005 *
00006 *  Redistribution and use in source and binary forms, with or without
00007 *  modification, are permitted provided that the following conditions
00008 *  are met:
00009 *
00010 *    Redistributions of source code must retain the above copyright
00011 *    notice, this list of conditions and the following disclaimer.
00012 *
00013 *    Redistributions in binary form must reproduce the above copyright
00014 *    notice, this list of conditions and the following disclaimer in the
00015 *    documentation and/or other materials provided with the   
00016 *    distribution.
00017 *
00018 *    Neither the name of Texas Instruments Incorporated nor the names of
00019 *    its contributors may be used to endorse or promote products derived
00020 *    from this software without specific prior written permission.
00021 *
00022 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
00023 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
00024 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00025 *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
00026 *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
00027 *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
00028 *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00029 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00030 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
00031 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
00032 *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00033 *
00034 *****************************************************************************/
00035 
00036 //*****************************************************************************
00037 //
00038 //! \addtogroup socket_api
00039 //! @{
00040 //
00041 //*****************************************************************************
00042 
00043 #include <stdio.h>
00044 #include <string.h>
00045 #include <stdlib.h>
00046 #include "hci.h"
00047 #include "socket.h"
00048 #include "evnt_handler.h"
00049 #include "netapp.h"
00050 
00051 
00052 
00053 //Enable this flag if and only if you must comply with BSD socket 
00054 //close() function
00055 #ifdef _API_USE_BSD_CLOSE
00056    #define close(sd) closesocket(sd)
00057 #endif
00058 
00059 //Enable this flag if and only if you must comply with BSD socket read() and 
00060 //write() functions
00061 #ifdef _API_USE_BSD_READ_WRITE
00062               #define read(sd, buf, len, flags) recv(sd, buf, len, flags)
00063               #define write(sd, buf, len, flags) send(sd, buf, len, flags)
00064 #endif
00065 
00066 #define SOCKET_OPEN_PARAMS_LEN              (12)
00067 #define SOCKET_CLOSE_PARAMS_LEN             (4)
00068 #define SOCKET_ACCEPT_PARAMS_LEN            (4)
00069 #define SOCKET_BIND_PARAMS_LEN              (20)
00070 #define SOCKET_LISTEN_PARAMS_LEN            (8)
00071 #define SOCKET_GET_HOST_BY_NAME_PARAMS_LEN  (9)
00072 #define SOCKET_CONNECT_PARAMS_LEN           (20)
00073 #define SOCKET_SELECT_PARAMS_LEN            (44)
00074 #define SOCKET_SET_SOCK_OPT_PARAMS_LEN      (20)
00075 #define SOCKET_GET_SOCK_OPT_PARAMS_LEN      (12)
00076 #define SOCKET_RECV_FROM_PARAMS_LEN         (12)
00077 #define SOCKET_SENDTO_PARAMS_LEN            (24)
00078 #define SOCKET_MDNS_ADVERTISE_PARAMS_LEN    (12)
00079 
00080 
00081 // The legnth of arguments for the SEND command: sd + buff_offset + len + flags, 
00082 // while size of each parameter is 32 bit - so the total length is 16 bytes;
00083 
00084 #define HCI_CMND_SEND_ARG_LENGTH    (16)
00085 
00086 
00087 #define SELECT_TIMEOUT_MIN_MICRO_SECONDS  5000
00088 
00089 #define HEADERS_SIZE_DATA       (SPI_HEADER_SIZE + 5)
00090 
00091 #define SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE  (SPI_HEADER_SIZE + SIMPLE_LINK_HCI_CMND_HEADER_SIZE)
00092 
00093 #define MDNS_DEVICE_SERVICE_MAX_LENGTH  (32)
00094 
00095 
00096 //*****************************************************************************
00097 //
00098 //! HostFlowControlConsumeBuff
00099 //!
00100 //!  @param  sd  socket descriptor
00101 //!
00102 //!  @return 0 in case there are buffers available, 
00103 //!          -1 in case of bad socket
00104 //!          -2 if there are no free buffers present (only when 
00105 //!          SEND_NON_BLOCKING is enabled)
00106 //!
00107 //!  @brief  if SEND_NON_BLOCKING not define - block until have free buffer 
00108 //!          becomes available, else return immediately  with correct status 
00109 //!          regarding the buffers available.
00110 //
00111 //*****************************************************************************
00112 int
00113 HostFlowControlConsumeBuff(int sd)
00114 {
00115 #ifndef SEND_NON_BLOCKING
00116     /* wait in busy loop */
00117     do
00118     {
00119         // In case last transmission failed then we will return the last failure 
00120         // reason here.
00121         // Note that the buffer will not be allocated in this case
00122         if (tSLInformation.slTransmitDataError != 0)
00123         {
00124             errno = tSLInformation.slTransmitDataError;
00125             tSLInformation.slTransmitDataError = 0;
00126             return errno;
00127         }
00128         
00129         if(SOCKET_STATUS_ACTIVE != get_socket_active_status(sd))
00130             return -1;
00131     } while(0 == tSLInformation.usNumberOfFreeBuffers);
00132     
00133     tSLInformation.usNumberOfFreeBuffers--;
00134     
00135     return 0;
00136 #else
00137     
00138     // In case last transmission failed then we will return the last failure 
00139     // reason here.
00140     // Note that the buffer will not be allocated in this case
00141     if (tSLInformation.slTransmitDataError != 0)
00142     {
00143         errno = tSLInformation.slTransmitDataError;
00144         tSLInformation.slTransmitDataError = 0;
00145         return errno;
00146     }
00147     if(SOCKET_STATUS_ACTIVE != get_socket_active_status(sd))
00148         return -1;
00149     
00150     //If there are no available buffers, return -2. It is recommended to use  
00151     // select or receive to see if there is any buffer occupied with received data
00152     // If so, call receive() to release the buffer.
00153     if(0 == tSLInformation.usNumberOfFreeBuffers)
00154     {
00155         return -2;
00156     }
00157     else
00158     {
00159         tSLInformation.usNumberOfFreeBuffers--;
00160         return 0;
00161     }
00162 #endif
00163 }
00164 
00165 //*****************************************************************************
00166 //
00167 //! socket
00168 //!
00169 //!  @param  domain    selects the protocol family which will be used for 
00170 //!                    communication. On this version only AF_INET is supported
00171 //!  @param  type      specifies the communication semantics. On this version 
00172 //!                    only SOCK_STREAM, SOCK_DGRAM, SOCK_RAW are supported
00173 //!  @param  protocol  specifies a particular protocol to be used with the 
00174 //!                    socket IPPROTO_TCP, IPPROTO_UDP or IPPROTO_RAW are 
00175 //!                    supported.
00176 //!
00177 //!  @return  On success, socket handle that is used for consequent socket 
00178 //!           operations. On error, -1 is returned.
00179 //!
00180 //!  @brief  create an endpoint for communication
00181 //!          The socket function creates a socket that is bound to a specific 
00182 //!          transport service provider. This function is called by the 
00183 //!          application layer to obtain a socket handle.
00184 //
00185 //*****************************************************************************
00186 
00187 int
00188 socket(long domain, long type, long protocol)
00189 {
00190     long ret;
00191     unsigned char *ptr, *args;
00192     
00193     ret = EFAIL;
00194     ptr = tSLInformation.pucTxCommandBuffer;
00195     args = (ptr + HEADERS_SIZE_CMD);
00196     
00197     // Fill in HCI packet structure
00198     args = UINT32_TO_STREAM(args, domain);
00199     args = UINT32_TO_STREAM(args, type);
00200     args = UINT32_TO_STREAM(args, protocol);
00201     
00202     // Initiate a HCI command
00203     hci_command_send(HCI_CMND_SOCKET, ptr, SOCKET_OPEN_PARAMS_LEN);
00204     
00205     // Since we are in blocking state - wait for event complete
00206     SimpleLinkWaitEvent(HCI_CMND_SOCKET, &ret);
00207     
00208     // Process the event 
00209     errno = ret;
00210     
00211     set_socket_active_status(ret, SOCKET_STATUS_ACTIVE);
00212     
00213     return(ret);
00214 }
00215 
00216 //*****************************************************************************
00217 //
00218 //! closesocket
00219 //!
00220 //!  @param  sd    socket handle.
00221 //!
00222 //!  @return  On success, zero is returned. On error, -1 is returned.
00223 //!
00224 //!  @brief  The socket function closes a created socket.
00225 //
00226 //*****************************************************************************
00227 
00228 long
00229 closesocket(long sd)
00230 {
00231     long ret;
00232     unsigned char *ptr, *args;
00233     
00234     ret = EFAIL;
00235     ptr = tSLInformation.pucTxCommandBuffer;
00236     args = (ptr + HEADERS_SIZE_CMD);
00237     
00238     // Fill in HCI packet structure
00239     args = UINT32_TO_STREAM(args, sd);
00240     
00241     // Initiate a HCI command
00242     hci_command_send(HCI_CMND_CLOSE_SOCKET,
00243                                      ptr, SOCKET_CLOSE_PARAMS_LEN);
00244     
00245     // Since we are in blocking state - wait for event complete
00246     SimpleLinkWaitEvent(HCI_CMND_CLOSE_SOCKET, &ret);
00247     errno = ret;
00248     
00249     // since 'close' call may result in either OK (and then it closed) or error 
00250     // mark this socket as invalid 
00251     set_socket_active_status(sd, SOCKET_STATUS_INACTIVE);
00252     
00253     return(ret);
00254 }
00255 
00256 //*****************************************************************************
00257 //
00258 //! accept
00259 //!
00260 //!  @param[in]   sd      socket descriptor (handle)              
00261 //!  @param[out]  addr    the argument addr is a pointer to a sockaddr structure
00262 //!                       This structure is filled in with the address of the  
00263 //!                       peer socket, as known to the communications layer.        
00264 //!                       determined. The exact format of the address returned             
00265 //!                       addr is by the socket's address sockaddr. 
00266 //!                       On this version only AF_INET is supported.
00267 //!                       This argument returns in network order.
00268 //!  @param[out] addrlen  the addrlen argument is a value-result argument: 
00269 //!                       it should initially contain the size of the structure
00270 //!                       pointed to by addr.
00271 //!
00272 //!  @return  For socket in blocking mode:
00273 //!                   On success, socket handle. on failure negative
00274 //!               For socket in non-blocking mode:
00275 //!                  - On connection establishment, socket handle
00276 //!                  - On connection pending, SOC_IN_PROGRESS (-2)
00277 //!                - On failure, SOC_ERROR  (-1)
00278 //!
00279 //!  @brief  accept a connection on a socket:
00280 //!          This function is used with connection-based socket types 
00281 //!          (SOCK_STREAM). It extracts the first connection request on the 
00282 //!          queue of pending connections, creates a new connected socket, and
00283 //!          returns a new file descriptor referring to that socket.
00284 //!          The newly created socket is not in the listening state. 
00285 //!          The original socket sd is unaffected by this call. 
00286 //!          The argument sd is a socket that has been created with socket(),
00287 //!          bound to a local address with bind(), and is  listening for 
00288 //!          connections after a listen(). The argument addr is a pointer 
00289 //!          to a sockaddr structure. This structure is filled in with the 
00290 //!          address of the peer socket, as known to the communications layer.
00291 //!          The exact format of the address returned addr is determined by the 
00292 //!          socket's address family. The addrlen argument is a value-result
00293 //!          argument: it should initially contain the size of the structure
00294 //!          pointed to by addr, on return it will contain the actual 
00295 //!          length (in bytes) of the address returned.
00296 //!
00297 //! @sa     socket ; bind ; listen
00298 //
00299 //*****************************************************************************
00300 
00301 long
00302 accept(long sd, sockaddr *addr, socklen_t *addrlen)
00303 {
00304     long ret;
00305     unsigned char *ptr, *args;
00306     tBsdReturnParams tAcceptReturnArguments;
00307     
00308     ret = EFAIL;
00309     ptr = tSLInformation.pucTxCommandBuffer;
00310     args = (ptr + HEADERS_SIZE_CMD);
00311     
00312     // Fill in temporary command buffer
00313     args = UINT32_TO_STREAM(args, sd);
00314     
00315     // Initiate a HCI command
00316     hci_command_send(HCI_CMND_ACCEPT,
00317                                      ptr, SOCKET_ACCEPT_PARAMS_LEN);
00318     
00319     // Since we are in blocking state - wait for event complete
00320     SimpleLinkWaitEvent(HCI_CMND_ACCEPT, &tAcceptReturnArguments);
00321     
00322     
00323     // need specify return parameters!!!
00324     memcpy(addr, &tAcceptReturnArguments.tSocketAddress, ASIC_ADDR_LEN);
00325     *addrlen = ASIC_ADDR_LEN;
00326     errno = tAcceptReturnArguments.iStatus; 
00327     ret = errno;
00328     
00329     // if succeeded, iStatus = new socket descriptor. otherwise - error number 
00330     if(M_IS_VALID_SD(ret))
00331     {
00332         set_socket_active_status(ret, SOCKET_STATUS_ACTIVE);
00333     }
00334     else
00335     {
00336         set_socket_active_status(sd, SOCKET_STATUS_INACTIVE);
00337     }
00338     
00339     return(ret);
00340 }
00341 
00342 //*****************************************************************************
00343 //
00344 //! bind
00345 //!
00346 //!  @param[in]   sd      socket descriptor (handle)              
00347 //!  @param[out]  addr    specifies the destination address. On this version 
00348 //!                       only AF_INET is supported.
00349 //!  @param[out] addrlen  contains the size of the structure pointed to by addr.
00350 //!
00351 //!  @return    On success, zero is returned. On error, -1 is returned.
00352 //!
00353 //!  @brief  assign a name to a socket
00354 //!          This function gives the socket the local address addr.
00355 //!          addr is addrlen bytes long. Traditionally, this is called when a 
00356 //!          socket is created with socket, it exists in a name space (address 
00357 //!          family) but has no name assigned.
00358 //!          It is necessary to assign a local address before a SOCK_STREAM
00359 //!          socket may receive connections.
00360 //!
00361 //! @sa     socket ; accept ; listen
00362 //
00363 //*****************************************************************************
00364 
00365 long
00366 bind(long sd, const sockaddr *addr, long addrlen)
00367 {
00368     long ret;
00369     unsigned char *ptr, *args;
00370     
00371     ret = EFAIL;
00372     ptr = tSLInformation.pucTxCommandBuffer;
00373     args = (ptr + HEADERS_SIZE_CMD);
00374     
00375     addrlen = ASIC_ADDR_LEN;
00376     
00377     // Fill in temporary command buffer
00378     args = UINT32_TO_STREAM(args, sd);
00379     args = UINT32_TO_STREAM(args, 0x00000008);
00380     args = UINT32_TO_STREAM(args, addrlen);
00381     ARRAY_TO_STREAM(args, ((unsigned char *)addr), addrlen);
00382     
00383     // Initiate a HCI command
00384     hci_command_send(HCI_CMND_BIND,
00385                                      ptr, SOCKET_BIND_PARAMS_LEN);
00386     
00387     // Since we are in blocking state - wait for event complete
00388     SimpleLinkWaitEvent(HCI_CMND_BIND, &ret);
00389     
00390     errno = ret;
00391   
00392     return(ret);
00393 }
00394 
00395 //*****************************************************************************
00396 //
00397 //! listen
00398 //!
00399 //!  @param[in]   sd      socket descriptor (handle)              
00400 //!  @param[in]  backlog  specifies the listen queue depth. On this version
00401 //!                       backlog is not supported.
00402 //!  @return    On success, zero is returned. On error, -1 is returned.
00403 //!
00404 //!  @brief  listen for connections on a socket
00405 //!          The willingness to accept incoming connections and a queue
00406 //!          limit for incoming connections are specified with listen(),
00407 //!          and then the connections are accepted with accept.
00408 //!          The listen() call applies only to sockets of type SOCK_STREAM
00409 //!          The backlog parameter defines the maximum length the queue of
00410 //!          pending connections may grow to. 
00411 //!
00412 //! @sa     socket ; accept ; bind
00413 //!
00414 //! @note   On this version, backlog is not supported
00415 //
00416 //*****************************************************************************
00417 
00418 long
00419 listen(long sd, long backlog)
00420 {
00421     long ret;
00422     unsigned char *ptr, *args;
00423     
00424     ret = EFAIL;
00425     ptr = tSLInformation.pucTxCommandBuffer;
00426     args = (ptr + HEADERS_SIZE_CMD);
00427     
00428     // Fill in temporary command buffer
00429     args = UINT32_TO_STREAM(args, sd);
00430     args = UINT32_TO_STREAM(args, backlog);
00431     
00432     // Initiate a HCI command
00433     hci_command_send(HCI_CMND_LISTEN,
00434                                      ptr, SOCKET_LISTEN_PARAMS_LEN);
00435     
00436     // Since we are in blocking state - wait for event complete
00437     SimpleLinkWaitEvent(HCI_CMND_LISTEN, &ret);
00438     errno = ret;
00439     
00440     return(ret);
00441 }
00442 
00443 //*****************************************************************************
00444 //
00445 //! gethostbyname
00446 //!
00447 //!  @param[in]   hostname     host name              
00448 //!  @param[in]   usNameLen    name length 
00449 //!  @param[out]  out_ip_addr  This parameter is filled in with host IP address. 
00450 //!                            In case that host name is not resolved, 
00451 //!                            out_ip_addr is zero.                  
00452 //!  @return    On success, positive is returned. On error, negative is returned
00453 //!
00454 //!  @brief  Get host IP by name. Obtain the IP Address of machine on network, 
00455 //!          by its name.
00456 //!
00457 //!  @note  On this version, only blocking mode is supported. Also note that
00458 //!          the function requires DNS server to be configured prior to its usage.
00459 //
00460 //*****************************************************************************
00461 
00462 #ifndef CC3000_TINY_DRIVER
00463 int 
00464 gethostbyname(char * hostname, unsigned short usNameLen, 
00465                             unsigned long* out_ip_addr)
00466 {
00467     tBsdGethostbynameParams ret;
00468     unsigned char *ptr, *args;
00469     
00470     errno = EFAIL;
00471     
00472     if (usNameLen > HOSTNAME_MAX_LENGTH)
00473     {
00474         return errno;
00475     }
00476     
00477     ptr = tSLInformation.pucTxCommandBuffer;
00478     args = (ptr + SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE);
00479     
00480     // Fill in HCI packet structure
00481     args = UINT32_TO_STREAM(args, 8);
00482     args = UINT32_TO_STREAM(args, usNameLen);
00483     ARRAY_TO_STREAM(args, hostname, usNameLen);
00484     
00485     // Initiate a HCI command
00486     hci_command_send(HCI_CMND_GETHOSTNAME, ptr, SOCKET_GET_HOST_BY_NAME_PARAMS_LEN
00487                                      + usNameLen - 1);
00488     
00489     // Since we are in blocking state - wait for event complete
00490     SimpleLinkWaitEvent(HCI_EVNT_BSD_GETHOSTBYNAME, &ret);
00491     
00492     errno = ret.retVal;
00493     
00494     (*((long*)out_ip_addr)) = ret.outputAddress;
00495     
00496     return (errno);
00497     
00498 }
00499 #endif
00500 
00501 //*****************************************************************************
00502 //
00503 //! connect
00504 //!
00505 //!  @param[in]   sd       socket descriptor (handle)         
00506 //!  @param[in]   addr     specifies the destination addr. On this version
00507 //!                        only AF_INET is supported.
00508 //!  @param[out]  addrlen  contains the size of the structure pointed to by addr    
00509 //!  @return    On success, zero is returned. On error, -1 is returned
00510 //!
00511 //!  @brief  initiate a connection on a socket 
00512 //!          Function connects the socket referred to by the socket descriptor 
00513 //!          sd, to the address specified by addr. The addrlen argument 
00514 //!          specifies the size of addr. The format of the address in addr is 
00515 //!          determined by the address space of the socket. If it is of type 
00516 //!          SOCK_DGRAM, this call specifies the peer with which the socket is 
00517 //!          to be associated; this address is that to which datagrams are to be
00518 //!          sent, and the only address from which datagrams are to be received.  
00519 //!          If the socket is of type SOCK_STREAM, this call attempts to make a 
00520 //!          connection to another socket. The other socket is specified  by 
00521 //!          address, which is an address in the communications space of the
00522 //!          socket. Note that the function implements only blocking behavior 
00523 //!          thus the caller will be waiting either for the connection 
00524 //!          establishment or for the connection establishment failure.
00525 //!
00526 //!  @sa socket
00527 //
00528 //*****************************************************************************
00529 
00530 long
00531 connect(long sd, const sockaddr *addr, long addrlen)
00532 {
00533     long int ret;
00534     unsigned char *ptr, *args;
00535     
00536     ret = EFAIL;
00537     ptr = tSLInformation.pucTxCommandBuffer;
00538     args = (ptr + SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE);
00539     addrlen = 8;
00540     
00541     // Fill in temporary command buffer
00542     args = UINT32_TO_STREAM(args, sd);
00543     args = UINT32_TO_STREAM(args, 0x00000008);
00544     args = UINT32_TO_STREAM(args, addrlen);
00545     ARRAY_TO_STREAM(args, ((unsigned char *)addr), addrlen);
00546     
00547     // Initiate a HCI command
00548     hci_command_send(HCI_CMND_CONNECT,
00549                                      ptr, SOCKET_CONNECT_PARAMS_LEN);
00550     
00551     // Since we are in blocking state - wait for event complete
00552     SimpleLinkWaitEvent(HCI_CMND_CONNECT, &ret);
00553     
00554     errno = ret;
00555     
00556     return((long)ret);
00557 }
00558 
00559 
00560 //*****************************************************************************
00561 //
00562 //! select
00563 //!
00564 //!  @param[in]   nfds       the highest-numbered file descriptor in any of the
00565 //!                           three sets, plus 1.     
00566 //!  @param[out]   writesds   socket descriptors list for write monitoring
00567 //!  @param[out]   readsds    socket descriptors list for read monitoring  
00568 //!  @param[out]   exceptsds  socket descriptors list for exception monitoring
00569 //!  @param[in]   timeout     is an upper bound on the amount of time elapsed
00570 //!                           before select() returns. Null means infinity 
00571 //!                           timeout. The minimum timeout is 5 milliseconds,
00572 //!                          less than 5 milliseconds will be set
00573 //!                           automatically to 5 milliseconds.
00574 //!  @return    On success, select() returns the number of file descriptors
00575 //!             contained in the three returned descriptor sets (that is, the
00576 //!             total number of bits that are set in readfds, writefds,
00577 //!             exceptfds) which may be zero if the timeout expires before
00578 //!             anything interesting  happens.
00579 //!             On error, -1 is returned.
00580 //!                   *readsds - return the sockets on which Read request will
00581 //!                              return without delay with valid data.
00582 //!                   *writesds - return the sockets on which Write request 
00583 //!                                 will return without delay.
00584 //!                   *exceptsds - return the sockets which closed recently.
00585 //!
00586 //!  @brief  Monitor socket activity  
00587 //!          Select allow a program to monitor multiple file descriptors,
00588 //!          waiting until one or more of the file descriptors become 
00589 //!         "ready" for some class of I/O operation 
00590 //!
00591 //!  @Note   If the timeout value set to less than 5ms it will automatically set
00592 //!          to 5ms to prevent overload of the system
00593 //!
00594 //!  @sa socket
00595 //
00596 //*****************************************************************************
00597 
00598 int
00599 select(long nfds, fd_set *readsds, fd_set *writesds, fd_set *exceptsds, 
00600        struct timeval *timeout)
00601 {
00602     unsigned char *ptr, *args;
00603     tBsdSelectRecvParams tParams;
00604     unsigned long is_blocking;
00605     
00606     if( timeout == NULL)
00607     {
00608         is_blocking = 1; /* blocking , infinity timeout */
00609     }
00610     else
00611     {
00612         is_blocking = 0; /* no blocking, timeout */
00613     }
00614     
00615     // Fill in HCI packet structure
00616     ptr = tSLInformation.pucTxCommandBuffer;
00617     args = (ptr + HEADERS_SIZE_CMD);
00618     
00619     // Fill in temporary command buffer
00620     args = UINT32_TO_STREAM(args, nfds);
00621     args = UINT32_TO_STREAM(args, 0x00000014);
00622     args = UINT32_TO_STREAM(args, 0x00000014);
00623     args = UINT32_TO_STREAM(args, 0x00000014);
00624     args = UINT32_TO_STREAM(args, 0x00000014);
00625     args = UINT32_TO_STREAM(args, is_blocking);
00626     args = UINT32_TO_STREAM(args, ((readsds) ? *(unsigned long*)readsds : 0));
00627     args = UINT32_TO_STREAM(args, ((writesds) ? *(unsigned long*)writesds : 0));
00628     args = UINT32_TO_STREAM(args, ((exceptsds) ? *(unsigned long*)exceptsds : 0));
00629     
00630     if (timeout)
00631     {
00632         if ( 0 == timeout->tv_sec && timeout->tv_usec < 
00633                 SELECT_TIMEOUT_MIN_MICRO_SECONDS)
00634         {
00635             timeout->tv_usec = SELECT_TIMEOUT_MIN_MICRO_SECONDS;
00636         }
00637         args = UINT32_TO_STREAM(args, timeout->tv_sec);
00638         args = UINT32_TO_STREAM(args, timeout->tv_usec);
00639     }
00640     
00641     // Initiate a HCI command
00642     hci_command_send(HCI_CMND_BSD_SELECT, ptr, SOCKET_SELECT_PARAMS_LEN);
00643     
00644     // Since we are in blocking state - wait for event complete
00645     SimpleLinkWaitEvent(HCI_EVNT_SELECT, &tParams);
00646     
00647     // Update actually read FD
00648     if (tParams.iStatus >= 0)
00649     {
00650         if (readsds)
00651         {
00652             memcpy(readsds, &tParams.uiRdfd, sizeof(tParams.uiRdfd));
00653         }
00654         
00655         if (writesds)
00656         {
00657             memcpy(writesds, &tParams.uiWrfd, sizeof(tParams.uiWrfd)); 
00658         }
00659         
00660         if (exceptsds)
00661         {
00662             memcpy(exceptsds, &tParams.uiExfd, sizeof(tParams.uiExfd)); 
00663         }
00664         
00665         return(tParams.iStatus);
00666         
00667     }
00668     else
00669     {
00670         errno = tParams.iStatus;
00671         return(-1);
00672     }
00673 }
00674 
00675 //*****************************************************************************
00676 //
00677 //! setsockopt
00678 //!
00679 //!  @param[in]   sd          socket handle
00680 //!  @param[in]   level       defines the protocol level for this option
00681 //!  @param[in]   optname     defines the option name to Interrogate
00682 //!  @param[in]   optval      specifies a value for the option
00683 //!  @param[in]   optlen      specifies the length of the option value
00684 //!  @return    On success, zero is returned. On error, -1 is returned
00685 //!
00686 //!  @brief  set socket options
00687 //!          This function manipulate the options associated with a socket.
00688 //!          Options may exist at multiple protocol levels; they are always
00689 //!          present at the uppermost socket level.
00690 //!          When manipulating socket options the level at which the option 
00691 //!          resides and the name of the option must be specified.  
00692 //!          To manipulate options at the socket level, level is specified as 
00693 //!          SOL_SOCKET. To manipulate options at any other level the protocol 
00694 //!          number of the appropriate protocol controlling the option is 
00695 //!          supplied. For example, to indicate that an option is to be 
00696 //!          interpreted by the TCP protocol, level should be set to the 
00697 //!          protocol number of TCP; 
00698 //!          The parameters optval and optlen are used to access optval - 
00699 //!          use for setsockopt(). For getsockopt() they identify a buffer
00700 //!          in which the value for the requested option(s) are to 
00701 //!          be returned. For getsockopt(), optlen is a value-result 
00702 //!          parameter, initially containing the size of the buffer 
00703 //!          pointed to by option_value, and modified on return to 
00704 //!          indicate the actual size of the value returned. If no option 
00705 //!          value is to be supplied or returned, option_value may be NULL.
00706 //!
00707 //!  @Note   On this version the following two socket options are enabled:
00708 //!              The only protocol level supported in this version
00709 //!          is SOL_SOCKET (level).
00710 //!            1. SOCKOPT_RECV_TIMEOUT (optname)
00711 //!               SOCKOPT_RECV_TIMEOUT configures recv and recvfrom timeout 
00712 //!           in milliseconds.
00713 //!             In that case optval should be pointer to unsigned long.
00714 //!            2. SOCKOPT_NONBLOCK (optname). sets the socket non-blocking mode on 
00715 //!           or off.
00716 //!             In that case optval should be SOCK_ON or SOCK_OFF (optval).
00717 //!
00718 //!  @sa getsockopt
00719 //
00720 //*****************************************************************************
00721 
00722 #ifndef CC3000_TINY_DRIVER
00723 int
00724 setsockopt(long sd, long level, long optname, const void *optval,
00725                      socklen_t optlen)
00726 {
00727     int ret;
00728     unsigned char *ptr, *args;
00729     
00730     ptr = tSLInformation.pucTxCommandBuffer;
00731     args = (ptr + HEADERS_SIZE_CMD);
00732     
00733     // Fill in temporary command buffer
00734     args = UINT32_TO_STREAM(args, sd);
00735     args = UINT32_TO_STREAM(args, level);
00736     args = UINT32_TO_STREAM(args, optname);
00737     args = UINT32_TO_STREAM(args, 0x00000008);
00738     args = UINT32_TO_STREAM(args, optlen);
00739     ARRAY_TO_STREAM(args, ((unsigned char *)optval), optlen);
00740     
00741     // Initiate a HCI command
00742     hci_command_send(HCI_CMND_SETSOCKOPT,
00743                                      ptr, SOCKET_SET_SOCK_OPT_PARAMS_LEN  + optlen);
00744     
00745     // Since we are in blocking state - wait for event complete
00746     SimpleLinkWaitEvent(HCI_CMND_SETSOCKOPT, &ret);
00747     
00748     if (ret >= 0)
00749     {
00750         return (0);
00751     }
00752     else
00753     {
00754         errno = ret;
00755         return (errno);
00756     }
00757 }
00758 #endif
00759 
00760 //*****************************************************************************
00761 //
00762 //! getsockopt
00763 //!
00764 //!  @param[in]   sd          socket handle
00765 //!  @param[in]   level       defines the protocol level for this option
00766 //!  @param[in]   optname     defines the option name to Interrogate
00767 //!  @param[out]   optval      specifies a value for the option
00768 //!  @param[out]   optlen      specifies the length of the option value
00769 //!  @return    On success, zero is returned. On error, -1 is returned
00770 //!
00771 //!  @brief  set socket options
00772 //!          This function manipulate the options associated with a socket.
00773 //!          Options may exist at multiple protocol levels; they are always
00774 //!          present at the uppermost socket level.
00775 //!          When manipulating socket options the level at which the option 
00776 //!          resides and the name of the option must be specified.  
00777 //!          To manipulate options at the socket level, level is specified as 
00778 //!          SOL_SOCKET. To manipulate options at any other level the protocol 
00779 //!          number of the appropriate protocol controlling the option is 
00780 //!          supplied. For example, to indicate that an option is to be 
00781 //!          interpreted by the TCP protocol, level should be set to the 
00782 //!          protocol number of TCP; 
00783 //!          The parameters optval and optlen are used to access optval - 
00784 //!          use for setsockopt(). For getsockopt() they identify a buffer
00785 //!          in which the value for the requested option(s) are to 
00786 //!          be returned. For getsockopt(), optlen is a value-result 
00787 //!          parameter, initially containing the size of the buffer 
00788 //!          pointed to by option_value, and modified on return to 
00789 //!          indicate the actual size of the value returned. If no option 
00790 //!          value is to be supplied or returned, option_value may be NULL.
00791 //!
00792 //!  @Note   On this version the following two socket options are enabled:
00793 //!              The only protocol level supported in this version
00794 //!          is SOL_SOCKET (level).
00795 //!            1. SOCKOPT_RECV_TIMEOUT (optname)
00796 //!               SOCKOPT_RECV_TIMEOUT configures recv and recvfrom timeout 
00797 //!           in milliseconds.
00798 //!             In that case optval should be pointer to unsigned long.
00799 //!            2. SOCKOPT_NONBLOCK (optname). sets the socket non-blocking mode on 
00800 //!           or off.
00801 //!             In that case optval should be SOCK_ON or SOCK_OFF (optval).
00802 //!
00803 //!  @sa setsockopt
00804 //
00805 //*****************************************************************************
00806 
00807 int
00808 getsockopt (long sd, long level, long optname, void *optval, socklen_t *optlen)
00809 {
00810     unsigned char *ptr, *args;
00811     tBsdGetSockOptReturnParams  tRetParams;
00812     
00813     ptr = tSLInformation.pucTxCommandBuffer;
00814     args = (ptr + HEADERS_SIZE_CMD);
00815     
00816     // Fill in temporary command buffer
00817     args = UINT32_TO_STREAM(args, sd);
00818     args = UINT32_TO_STREAM(args, level);
00819     args = UINT32_TO_STREAM(args, optname);
00820     
00821     // Initiate a HCI command
00822     hci_command_send(HCI_CMND_GETSOCKOPT,
00823                                      ptr, SOCKET_GET_SOCK_OPT_PARAMS_LEN);
00824     
00825     // Since we are in blocking state - wait for event complete
00826     SimpleLinkWaitEvent(HCI_CMND_GETSOCKOPT, &tRetParams);
00827     
00828     if (((signed char)tRetParams.iStatus) >= 0)
00829     {
00830         *optlen = 4;
00831         memcpy(optval, tRetParams.ucOptValue, 4);
00832         return (0);
00833     }
00834     else
00835     {
00836         errno = tRetParams.iStatus;
00837         return (errno);
00838     }
00839 }
00840 
00841 //*****************************************************************************
00842 //
00843 //!  simple_link_recv
00844 //!
00845 //!  @param sd       socket handle
00846 //!  @param buf      read buffer
00847 //!  @param len      buffer length
00848 //!  @param flags    indicates blocking or non-blocking operation
00849 //!  @param from     pointer to an address structure indicating source address
00850 //!  @param fromlen  source address structure size
00851 //!
00852 //!  @return         Return the number of bytes received, or -1 if an error
00853 //!                  occurred
00854 //!
00855 //!  @brief          Read data from socket
00856 //!                  Return the length of the message on successful completion.
00857 //!                  If a message is too long to fit in the supplied buffer,
00858 //!                  excess bytes may be discarded depending on the type of
00859 //!                  socket the message is received from
00860 //
00861 //*****************************************************************************
00862 int
00863 simple_link_recv(long sd, void *buf, long len, long flags, sockaddr *from,
00864                 socklen_t *fromlen, long opcode)
00865 {
00866     unsigned char *ptr, *args;
00867     tBsdReadReturnParams tSocketReadEvent;
00868     
00869     ptr = tSLInformation.pucTxCommandBuffer;
00870     args = (ptr + HEADERS_SIZE_CMD);
00871     
00872     // Fill in HCI packet structure
00873     args = UINT32_TO_STREAM(args, sd);
00874     args = UINT32_TO_STREAM(args, len);
00875     args = UINT32_TO_STREAM(args, flags);
00876     
00877     // Generate the read command, and wait for the 
00878     hci_command_send(opcode,  ptr, SOCKET_RECV_FROM_PARAMS_LEN);
00879     
00880     // Since we are in blocking state - wait for event complete
00881     SimpleLinkWaitEvent(opcode, &tSocketReadEvent);
00882     
00883     // In case the number of bytes is more then zero - read data
00884     if (tSocketReadEvent.iNumberOfBytes > 0)
00885     {
00886         // Wait for the data in a synchronous way. Here we assume that the bug is 
00887         // big enough to store also parameters of receive from too....
00888         SimpleLinkWaitData((unsigned char *)buf, (unsigned char *)from, (unsigned char *)fromlen);
00889     }
00890     
00891     errno = tSocketReadEvent.iNumberOfBytes;
00892     
00893     return(tSocketReadEvent.iNumberOfBytes);
00894 }
00895 
00896 //*****************************************************************************
00897 //
00898 //!  recv
00899 //!
00900 //!  @param[in]  sd     socket handle
00901 //!  @param[out] buf    Points to the buffer where the message should be stored
00902 //!  @param[in]  len    Specifies the length in bytes of the buffer pointed to 
00903 //!                     by the buffer argument.
00904 //!  @param[in] flags   Specifies the type of message reception. 
00905 //!                     On this version, this parameter is not supported.
00906 //!
00907 //!  @return         Return the number of bytes received, or -1 if an error
00908 //!                  occurred
00909 //!
00910 //!  @brief          function receives a message from a connection-mode socket
00911 //!
00912 //!  @sa recvfrom
00913 //!
00914 //!  @Note On this version, only blocking mode is supported.
00915 //
00916 //*****************************************************************************
00917 
00918 int
00919 recv(long sd, void *buf, long len, long flags)
00920 {
00921     return(simple_link_recv(sd, buf, len, flags, NULL, NULL, HCI_CMND_RECV));
00922 }
00923 
00924 //*****************************************************************************
00925 //
00926 //!  recvfrom
00927 //!
00928 //!  @param[in]  sd     socket handle
00929 //!  @param[out] buf    Points to the buffer where the message should be stored
00930 //!  @param[in]  len    Specifies the length in bytes of the buffer pointed to 
00931 //!                     by the buffer argument.
00932 //!  @param[in] flags   Specifies the type of message reception. 
00933 //!                     On this version, this parameter is not supported.
00934 //!  @param[in] from   pointer to an address structure indicating the source
00935 //!                    address: sockaddr. On this version only AF_INET is
00936 //!                    supported.
00937 //!  @param[in] fromlen   source address tructure size
00938 //!
00939 //!  @return         Return the number of bytes received, or -1 if an error
00940 //!                  occurred
00941 //!
00942 //!  @brief         read data from socket
00943 //!                 function receives a message from a connection-mode or
00944 //!                 connectionless-mode socket. Note that raw sockets are not
00945 //!                 supported.
00946 //!
00947 //!  @sa recv
00948 //!
00949 //!  @Note On this version, only blocking mode is supported.
00950 //
00951 //*****************************************************************************
00952 int
00953 recvfrom(long sd, void *buf, long len, long flags, sockaddr *from,
00954          socklen_t *fromlen)
00955 {
00956     return(simple_link_recv(sd, buf, len, flags, from, fromlen,
00957                                                     HCI_CMND_RECVFROM));
00958 }
00959 
00960 //*****************************************************************************
00961 //
00962 //!  simple_link_send
00963 //!
00964 //!  @param sd       socket handle
00965 //!  @param buf      write buffer
00966 //!  @param len      buffer length
00967 //!  @param flags    On this version, this parameter is not supported
00968 //!  @param to       pointer to an address structure indicating destination
00969 //!                  address
00970 //!  @param tolen    destination address structure size
00971 //!
00972 //!  @return         Return the number of bytes transmitted, or -1 if an error
00973 //!                  occurred, or -2 in case there are no free buffers available
00974 //!                 (only when SEND_NON_BLOCKING is enabled)
00975 //!
00976 //!  @brief          This function is used to transmit a message to another
00977 //!                  socket
00978 //
00979 //*****************************************************************************
00980 int
00981 simple_link_send(long sd, const void *buf, long len, long flags,
00982               const sockaddr *to, long tolen, long opcode)
00983 {    
00984     unsigned char uArgSize,  addrlen;
00985     unsigned char *ptr, *pDataPtr, *args;
00986     unsigned long addr_offset;
00987     int res;
00988         tBsdReadReturnParams tSocketSendEvent;
00989     
00990     // Check the bsd_arguments
00991     if (0 != (res = HostFlowControlConsumeBuff(sd)))
00992     {
00993         return res;
00994     }
00995     
00996     //Update the number of sent packets
00997     tSLInformation.NumberOfSentPackets++;
00998     
00999     // Allocate a buffer and construct a packet and send it over spi
01000     ptr = tSLInformation.pucTxCommandBuffer;
01001     args = (ptr + HEADERS_SIZE_DATA);
01002     
01003     // Update the offset of data and parameters according to the command
01004     switch(opcode)
01005     { 
01006     case HCI_CMND_SENDTO:
01007         {
01008             addr_offset = len + sizeof(len) + sizeof(len);
01009             addrlen = 8;
01010             uArgSize = SOCKET_SENDTO_PARAMS_LEN;
01011             pDataPtr = ptr + HEADERS_SIZE_DATA + SOCKET_SENDTO_PARAMS_LEN;
01012             break;
01013         }
01014         
01015     case HCI_CMND_SEND:
01016         {
01017             tolen = 0;
01018             to = NULL;
01019             uArgSize = HCI_CMND_SEND_ARG_LENGTH;
01020             pDataPtr = ptr + HEADERS_SIZE_DATA + HCI_CMND_SEND_ARG_LENGTH;
01021             break;
01022         }
01023         
01024     default:
01025         {
01026             break;
01027         }
01028     }
01029     
01030     // Fill in temporary command buffer
01031     args = UINT32_TO_STREAM(args, sd);
01032     args = UINT32_TO_STREAM(args, uArgSize - sizeof(sd));
01033     args = UINT32_TO_STREAM(args, len);
01034     args = UINT32_TO_STREAM(args, flags);
01035     
01036     if (opcode == HCI_CMND_SENDTO)
01037     {
01038         args = UINT32_TO_STREAM(args, addr_offset);
01039         args = UINT32_TO_STREAM(args, addrlen);
01040     }
01041     
01042     // Copy the data received from user into the TX Buffer
01043     ARRAY_TO_STREAM(pDataPtr, ((unsigned char *)buf), len);
01044     
01045     // In case we are using SendTo, copy the to parameters
01046     if (opcode == HCI_CMND_SENDTO)
01047     {   
01048         ARRAY_TO_STREAM(pDataPtr, ((unsigned char *)to), tolen);
01049     }
01050     
01051     // Initiate a HCI command
01052     hci_data_send(opcode, ptr, uArgSize, len,(unsigned char*)to, tolen);
01053         
01054          if (opcode == HCI_CMND_SENDTO)
01055             SimpleLinkWaitEvent(HCI_EVNT_SENDTO, &tSocketSendEvent);
01056          else
01057             SimpleLinkWaitEvent(HCI_EVNT_SEND, &tSocketSendEvent);
01058     
01059     return  (len);
01060 }
01061 
01062 
01063 //*****************************************************************************
01064 //
01065 //!  send
01066 //!
01067 //!  @param sd       socket handle
01068 //!  @param buf      Points to a buffer containing the message to be sent
01069 //!  @param len      message size in bytes
01070 //!  @param flags    On this version, this parameter is not supported
01071 //!
01072 //!  @return         Return the number of bytes transmitted, or -1 if an
01073 //!                  error occurred
01074 //!
01075 //!  @brief          Write data to TCP socket
01076 //!                  This function is used to transmit a message to another 
01077 //!                  socket.
01078 //!
01079 //!  @Note           On this version, only blocking mode is supported.
01080 //!
01081 //!  @sa             sendto
01082 //
01083 //*****************************************************************************
01084 
01085 int
01086 send(long sd, const void *buf, long len, long flags)
01087 {
01088     return(simple_link_send(sd, buf, len, flags, NULL, 0, HCI_CMND_SEND));
01089 }
01090 
01091 //*****************************************************************************
01092 //
01093 //!  sendto
01094 //!
01095 //!  @param sd       socket handle
01096 //!  @param buf      Points to a buffer containing the message to be sent
01097 //!  @param len      message size in bytes
01098 //!  @param flags    On this version, this parameter is not supported
01099 //!  @param to       pointer to an address structure indicating the destination
01100 //!                  address: sockaddr. On this version only AF_INET is
01101 //!                  supported.
01102 //!  @param tolen    destination address structure size
01103 //!
01104 //!  @return         Return the number of bytes transmitted, or -1 if an
01105 //!                  error occurred
01106 //!
01107 //!  @brief          Write data to TCP socket
01108 //!                  This function is used to transmit a message to another 
01109 //!                  socket.
01110 //!
01111 //!  @Note           On this version, only blocking mode is supported.
01112 //!
01113 //!  @sa             send
01114 //
01115 //*****************************************************************************
01116 
01117 int
01118 sendto(long sd, const void *buf, long len, long flags, const sockaddr *to,
01119        socklen_t tolen)
01120 {
01121     return(simple_link_send(sd, buf, len, flags, to, tolen, HCI_CMND_SENDTO));
01122 }
01123 
01124 //*****************************************************************************
01125 //
01126 //!  mdnsAdvertiser
01127 //!
01128 //!  @param[in] mdnsEnabled         flag to enable/disable the mDNS feature
01129 //!  @param[in] deviceServiceName   Service name as part of the published
01130 //!                                 canonical domain name
01131 //!  @param[in] deviceServiceNameLength   Length of the service name
01132 //!  
01133 //!
01134 //!  @return   On success, zero is returned, return SOC_ERROR if socket was not 
01135 //!            opened successfully, or if an error occurred.
01136 //!
01137 //!  @brief    Set CC3000 in mDNS advertiser mode in order to advertise itself.
01138 //
01139 //*****************************************************************************
01140 
01141 int
01142 mdnsAdvertiser(unsigned short mdnsEnabled, char * deviceServiceName, unsigned short deviceServiceNameLength)
01143 {
01144     int ret;
01145     unsigned char *pTxBuffer, *pArgs;
01146     
01147     if (deviceServiceNameLength > MDNS_DEVICE_SERVICE_MAX_LENGTH)
01148     {
01149         return EFAIL;
01150     }
01151     
01152     pTxBuffer = tSLInformation.pucTxCommandBuffer;
01153     pArgs = (pTxBuffer + SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE);
01154     
01155     // Fill in HCI packet structure
01156     pArgs = UINT32_TO_STREAM(pArgs, mdnsEnabled);
01157     pArgs = UINT32_TO_STREAM(pArgs, 8);
01158     pArgs = UINT32_TO_STREAM(pArgs, deviceServiceNameLength);
01159     ARRAY_TO_STREAM(pArgs, deviceServiceName, deviceServiceNameLength);
01160     
01161     // Initiate a HCI command
01162     hci_command_send(HCI_CMND_MDNS_ADVERTISE, pTxBuffer, SOCKET_MDNS_ADVERTISE_PARAMS_LEN + deviceServiceNameLength);
01163     
01164     // Since we are in blocking state - wait for event complete
01165     SimpleLinkWaitEvent(HCI_EVNT_MDNS_ADVERTISE, &ret);
01166     
01167     return ret;
01168     
01169 }
01170