Exemplo n.º 1
0
//*****************************************************************************
//
//!  recvfrom
//!
//!  @param[in]  sd     socket handle
//!  @param[out] buf    Points to the buffer where the message should be stored
//!  @param[in]  len    Specifies the length in bytes of the buffer pointed to 
//!                     by the buffer argument.
//!  @param[in] flags   Specifies the type of message reception. 
//!                     On this version, this parameter is not supported.
//!  @param[in] from   pointer to an address structure indicating the source
//!                    address: sockaddr. On this version only AF_INET is
//!                    supported.
//!  @param[in] fromlen   source address tructure size
//!
//!  @return         Return the number of bytes received, or -1 if an error
//!                  occurred
//!
//!  @brief         read data from socket
//!                 function receives a message from a connection-mode or
//!                 connectionless-mode socket. Note that raw sockets are not
//!                 supported.
//!
//!  @sa recv
//!
//!  @Note On this version, only blocking mode is supported.
//
//*****************************************************************************
int
recvfrom(long sd, void *buf, long len, long flags, sockaddr *from,
         socklen_t *fromlen)
{
	return(simple_link_recv(sd, buf, len, flags, from, fromlen,
													HCI_CMND_RECVFROM));
}
Exemplo n.º 2
0
    /* wait in busy loop */
    do
    {
        // In case last transmission failed then we will return the last failure
        // reason here.
        // Note that the buffer will not be allocated in this case
        if (tSLInformation.slTransmitDataError != 0)
        {
            errno = tSLInformation.slTransmitDataError;
            tSLInformation.slTransmitDataError = 0;
            return errno;
        }

        if(SOCKET_STATUS_ACTIVE != get_socket_active_status(sd))
            return -1;
    } while(0 == tSLInformation.usNumberOfFreeBuffers);

    tSLInformation.usNumberOfFreeBuffers--;

    return 0;
#else

    // In case last transmission failed then we will return the last failure
    // reason here.
    // Note that the buffer will not be allocated in this case
    if (tSLInformation.slTransmitDataError != 0)
    {
        errno = tSLInformation.slTransmitDataError;
        tSLInformation.slTransmitDataError = 0;
        return errno;
    }
    if(SOCKET_STATUS_ACTIVE != get_socket_active_status(sd))
        return -1;

    //If there are no available buffers, return -2. It is recommended to use
    // select or receive to see if there is any buffer occupied with received data
    // If so, call receive() to release the buffer.
    if(0 == tSLInformation.usNumberOfFreeBuffers)
    {
        return -2;
    }
    else
    {
        tSLInformation.usNumberOfFreeBuffers--;
        return 0;
    }
#endif
}

//*****************************************************************************
//
//! socket
//!
//!  @param  domain    selects the protocol family which will be used for
//!                    communication. On this version only AF_INET is supported
//!  @param  type      specifies the communication semantics. On this version
//!                    only SOCK_STREAM, SOCK_DGRAM, SOCK_RAW are supported
//!  @param  protocol  specifies a particular protocol to be used with the
//!                    socket IPPROTO_TCP, IPPROTO_UDP or IPPROTO_RAW are
//!                    supported.
//!
//!  @return  On success, socket handle that is used for consequent socket
//!           operations. On error, -1 is returned.
//!
//!  @brief  create an endpoint for communication
//!          The socket function creates a socket that is bound to a specific
//!          transport service provider. This function is called by the
//!          application layer to obtain a socket handle.
//
//*****************************************************************************

#ifdef __ENABLE_MULTITHREADED_SUPPORT__
int c_socket(long domain, long type, long protocol)
#else /* __ENABLE_MULTITHREADED_SUPPORT__ */
int socket(long domain, long type, long protocol)
#endif /* __ENABLE_MULTITHREADED_SUPPORT__ */
{
    long ret;
    unsigned char *ptr, *args;

    ret = EFAIL;
    ptr = tSLInformation.pucTxCommandBuffer;
    args = (ptr + HEADERS_SIZE_CMD);

    // Fill in HCI packet structure
    args = UINT32_TO_STREAM(args, domain);
    args = UINT32_TO_STREAM(args, type);
    args = UINT32_TO_STREAM(args, protocol);

    // Initiate a HCI command
    hci_command_send(HCI_CMND_SOCKET, ptr, SOCKET_OPEN_PARAMS_LEN);

    // Since we are in blocking state - wait for event complete
    SimpleLinkWaitEvent(HCI_CMND_SOCKET, &ret);

    // Process the event
    errno = ret;

    set_socket_active_status(ret, SOCKET_STATUS_ACTIVE);

    return(ret);
}

//*****************************************************************************
//
//! closesocket
//!
//!  @param  sd    socket handle.
//!
//!  @return  On success, zero is returned. On error, -1 is returned.
//!
//!  @brief  The socket function closes a created socket.
//
//*****************************************************************************

#ifdef __ENABLE_MULTITHREADED_SUPPORT__
long c_closesocket(long sd)
#else /* __ENABLE_MULTITHREADED_SUPPORT__ */
long closesocket(long sd)
#endif /* __ENABLE_MULTITHREADED_SUPPORT__ */
{
    long ret;
    unsigned char *ptr, *args;

    ret = EFAIL;
    ptr = tSLInformation.pucTxCommandBuffer;
    args = (ptr + HEADERS_SIZE_CMD);

    // Fill in HCI packet structure
    args = UINT32_TO_STREAM(args, sd);

    // Initiate a HCI command
    hci_command_send(HCI_CMND_CLOSE_SOCKET,
                                     ptr, SOCKET_CLOSE_PARAMS_LEN);

    // Since we are in blocking state - wait for event complete
    SimpleLinkWaitEvent(HCI_CMND_CLOSE_SOCKET, &ret);
    errno = ret;

    // since 'close' call may result in either OK (and then it closed) or error
    // mark this socket as invalid
    set_socket_active_status(sd, SOCKET_STATUS_INACTIVE);

    return(ret);
}

//*****************************************************************************
//
//! accept
//!
//!  @param[in]   sd      socket descriptor (handle)
//!  @param[out]  addr    the argument addr is a pointer to a sockaddr structure
//!                       This structure is filled in with the address of the
//!                       peer socket, as known to the communications layer.
//!                       determined. The exact format of the address returned
//!                       addr is by the socket's address sockaddr.
//!                       On this version only AF_INET is supported.
//!                       This argument returns in network order.
//!  @param[out] addrlen  the addrlen argument is a value-result argument:
//!                       it should initially contain the size of the structure
//!                       pointed to by addr.
//!
//!  @return  For socket in blocking mode:
//!                   On success, socket handle. on failure negative
//!               For socket in non-blocking mode:
//!                  - On connection establishment, socket handle
//!                  - On connection pending, SOC_IN_PROGRESS (-2)
//!                - On failure, SOC_ERROR  (-1)
//!
//!  @brief  accept a connection on a socket:
//!          This function is used with connection-based socket types
//!          (SOCK_STREAM). It extracts the first connection request on the
//!          queue of pending connections, creates a new connected socket, and
//!          returns a new file descriptor referring to that socket.
//!          The newly created socket is not in the listening state.
//!          The original socket sd is unaffected by this call.
//!          The argument sd is a socket that has been created with socket(),
//!          bound to a local address with bind(), and is  listening for
//!          connections after a listen(). The argument addr is a pointer
//!          to a sockaddr structure. This structure is filled in with the
//!          address of the peer socket, as known to the communications layer.
//!          The exact format of the address returned addr is determined by the
//!          socket's address family. The addrlen argument is a value-result
//!          argument: it should initially contain the size of the structure
//!          pointed to by addr, on return it will contain the actual
//!          length (in bytes) of the address returned.
//!
//! @sa     socket ; bind ; listen
//
//*****************************************************************************
#ifdef __ENABLE_MULTITHREADED_SUPPORT__
long c_accept(long sd, sockaddr *addr, socklen_t *addrlen)
#else /* __ENABLE_MULTITHREADED_SUPPORT__ */
long accept(long sd, sockaddr *addr, socklen_t *addrlen)
#endif /* __ENABLE_MULTITHREADED_SUPPORT__ */
{
    long ret;
    unsigned char *ptr, *args;
    tBsdReturnParams tAcceptReturnArguments;

    ret = EFAIL;
    ptr = tSLInformation.pucTxCommandBuffer;
    args = (ptr + HEADERS_SIZE_CMD);

    // Fill in temporary command buffer
    args = UINT32_TO_STREAM(args, sd);

    // Initiate a HCI command
    hci_command_send(HCI_CMND_ACCEPT,
                                     ptr, SOCKET_ACCEPT_PARAMS_LEN);

    // Since we are in blocking state - wait for event complete
    SimpleLinkWaitEvent(HCI_CMND_ACCEPT, &tAcceptReturnArguments);


    // need specify return parameters!!!
    memcpy(addr, &tAcceptReturnArguments.tSocketAddress, ASIC_ADDR_LEN);
    *addrlen = ASIC_ADDR_LEN;
    errno = tAcceptReturnArguments.iStatus;
    ret = errno;

    // if succeeded, iStatus = new socket descriptor. otherwise - error number
    if(M_IS_VALID_SD(ret))
    {
        set_socket_active_status(ret, SOCKET_STATUS_ACTIVE);
    }
    else
    {
        set_socket_active_status(sd, SOCKET_STATUS_INACTIVE);
    }

    return(ret);
}

//*****************************************************************************
//
//! bind
//!
//!  @param[in]   sd      socket descriptor (handle)
//!  @param[out]  addr    specifies the destination address. On this version
//!                       only AF_INET is supported.
//!  @param[out] addrlen  contains the size of the structure pointed to by addr.
//!
//!  @return    On success, zero is returned. On error, -1 is returned.
//!
//!  @brief  assign a name to a socket
//!          This function gives the socket the local address addr.
//!          addr is addrlen bytes long. Traditionally, this is called when a
//!          socket is created with socket, it exists in a name space (address
//!          family) but has no name assigned.
//!          It is necessary to assign a local address before a SOCK_STREAM
//!          socket may receive connections.
//!
//! @sa     socket ; accept ; listen
//
//*****************************************************************************
#ifdef __ENABLE_MULTITHREADED_SUPPORT__
long c_bind(long sd, const sockaddr *addr, long addrlen)
#else /* __ENABLE_MULTITHREADED_SUPPORT__ */
long bind(long sd, const sockaddr *addr, long addrlen)
#endif /* __ENABLE_MULTITHREADED_SUPPORT__ */
{
    long ret;
    unsigned char *ptr, *args;

    ret = EFAIL;
    ptr = tSLInformation.pucTxCommandBuffer;
    args = (ptr + HEADERS_SIZE_CMD);

    addrlen = ASIC_ADDR_LEN;

    // Fill in temporary command buffer
    args = UINT32_TO_STREAM(args, sd);
    args = UINT32_TO_STREAM(args, 0x00000008);
    args = UINT32_TO_STREAM(args, addrlen);
    ARRAY_TO_STREAM(args, ((unsigned char *)addr), addrlen);

    // Initiate a HCI command
    hci_command_send(HCI_CMND_BIND,
                                     ptr, SOCKET_BIND_PARAMS_LEN);

    // Since we are in blocking state - wait for event complete
    SimpleLinkWaitEvent(HCI_CMND_BIND, &ret);

    errno = ret;

    return(ret);
}

//*****************************************************************************
//
//! listen
//!
//!  @param[in]   sd      socket descriptor (handle)
//!  @param[in]  backlog  specifies the listen queue depth. On this version
//!                       backlog is not supported.
//!  @return    On success, zero is returned. On error, -1 is returned.
//!
//!  @brief  listen for connections on a socket
//!          The willingness to accept incoming connections and a queue
//!          limit for incoming connections are specified with listen(),
//!          and then the connections are accepted with accept.
//!          The listen() call applies only to sockets of type SOCK_STREAM
//!          The backlog parameter defines the maximum length the queue of
//!          pending connections may grow to.
//!
//! @sa     socket ; accept ; bind
//!
//! @note   On this version, backlog is not supported
//
//*****************************************************************************
#ifdef __ENABLE_MULTITHREADED_SUPPORT__
long c_listen(long sd, long backlog)
#else /* __ENABLE_MULTITHREADED_SUPPORT__ */
long listen(long sd, long backlog)
#endif /* __ENABLE_MULTITHREADED_SUPPORT__ */
{
    long ret;
    unsigned char *ptr, *args;

    ret = EFAIL;
    ptr = tSLInformation.pucTxCommandBuffer;
    args = (ptr + HEADERS_SIZE_CMD);

    // Fill in temporary command buffer
    args = UINT32_TO_STREAM(args, sd);
    args = UINT32_TO_STREAM(args, backlog);

    // Initiate a HCI command
    hci_command_send(HCI_CMND_LISTEN,
                                     ptr, SOCKET_LISTEN_PARAMS_LEN);

    // Since we are in blocking state - wait for event complete
    SimpleLinkWaitEvent(HCI_CMND_LISTEN, &ret);
    errno = ret;

    return(ret);
}

//*****************************************************************************
//
//! gethostbyname
//!
//!  @param[in]   hostname     host name
//!  @param[in]   usNameLen    name length
//!  @param[out]  out_ip_addr  This parameter is filled in with host IP address.
//!                            In case that host name is not resolved,
//!                            out_ip_addr is zero.
//!  @return    On success, positive is returned. On error, negative is returned
//!
//!  @brief  Get host IP by name. Obtain the IP Address of machine on network,
//!          by its name.
//!
//!  @note  On this version, only blocking mode is supported. Also note that
//!          the function requires DNS server to be configured prior to its usage.
//
//*****************************************************************************

#ifndef CC3000_TINY_DRIVER
#ifdef __ENABLE_MULTITHREADED_SUPPORT__
int
c_gethostbyname(char * hostname, unsigned short usNameLen, unsigned long* out_ip_addr)
#else /* __ENABLE_MULTITHREADED_SUPPORT__ */
int
gethostbyname(char * hostname, unsigned short usNameLen, unsigned long* out_ip_addr)
#endif /*__ENABLE_MULTITHREADED_SUPPORT__ */
{
    tBsdGethostbynameParams ret;
    unsigned char *ptr, *args;

    errno = EFAIL;

    if (usNameLen > HOSTNAME_MAX_LENGTH)
    {
        return errno;
    }

    ptr = tSLInformation.pucTxCommandBuffer;
    args = (ptr + SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE);

    // Fill in HCI packet structure
    args = UINT32_TO_STREAM(args, 8);
    args = UINT32_TO_STREAM(args, usNameLen);
    ARRAY_TO_STREAM(args, hostname, usNameLen);

    // Initiate a HCI command
    hci_command_send(HCI_CMND_GETHOSTNAME, ptr, SOCKET_GET_HOST_BY_NAME_PARAMS_LEN
                                     + usNameLen - 1);

    // Since we are in blocking state - wait for event complete
    SimpleLinkWaitEvent(HCI_EVNT_BSD_GETHOSTBYNAME, &ret);

    errno = ret.retVal;

    (*((long*)out_ip_addr)) = ret.outputAddress;

    return (errno);

}
#endif

//*****************************************************************************
//
//! connect
//!
//!  @param[in]   sd       socket descriptor (handle)
//!  @param[in]   addr     specifies the destination addr. On this version
//!                        only AF_INET is supported.
//!  @param[out]  addrlen  contains the size of the structure pointed to by addr
//!  @return    On success, zero is returned. On error, -1 is returned
//!
//!  @brief  initiate a connection on a socket
//!          Function connects the socket referred to by the socket descriptor
//!          sd, to the address specified by addr. The addrlen argument
//!          specifies the size of addr. The format of the address in addr is
//!          determined by the address space of the socket. If it is of type
//!          SOCK_DGRAM, this call specifies the peer with which the socket is
//!          to be associated; this address is that to which datagrams are to be
//!          sent, and the only address from which datagrams are to be received.
//!          If the socket is of type SOCK_STREAM, this call attempts to make a
//!          connection to another socket. The other socket is specified  by
//!          address, which is an address in the communications space of the
//!          socket. Note that the function implements only blocking behavior
//!          thus the caller will be waiting either for the connection
//!          establishment or for the connection establishment failure.
//!
//!  @sa socket
//
//*****************************************************************************
#ifdef __ENABLE_MULTITHREADED_SUPPORT__
long c_connect(long sd, const sockaddr *addr, long addrlen)
#else /* __ENABLE_MULTITHREADED_SUPPORT__ */
long connect(long sd, const sockaddr *addr, long addrlen)
#endif /* __ENABLE_MULTITHREADED_SUPPORT__ */
{
    long int ret;
    unsigned char *ptr, *args;

    ret = EFAIL;
    ptr = tSLInformation.pucTxCommandBuffer;
    args = (ptr + SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE);
    addrlen = 8;

    // Fill in temporary command buffer
    args = UINT32_TO_STREAM(args, sd);
    args = UINT32_TO_STREAM(args, 0x00000008);
    args = UINT32_TO_STREAM(args, addrlen);
    ARRAY_TO_STREAM(args, ((unsigned char *)addr), addrlen);

    // Initiate a HCI command
    hci_command_send(HCI_CMND_CONNECT,
                                     ptr, SOCKET_CONNECT_PARAMS_LEN);

    // Since we are in blocking state - wait for event complete
    SimpleLinkWaitEvent(HCI_CMND_CONNECT, &ret);

    errno = ret;

    return((long)ret);
}


//*****************************************************************************
//
//! select
//!
//!  @param[in]   nfds       the highest-numbered file descriptor in any of the
//!                           three sets, plus 1.
//!  @param[out]   writesds   socket descriptors list for write monitoring
//!  @param[out]   readsds    socket descriptors list for read monitoring
//!  @param[out]   exceptsds  socket descriptors list for exception monitoring
//!  @param[in]   timeout     is an upper bound on the amount of time elapsed
//!                           before select() returns. Null means infinity
//!                           timeout. The minimum timeout is 5 milliseconds,
//!                          less than 5 milliseconds will be set
//!                           automatically to 5 milliseconds.
//!  @return    On success, select() returns the number of file descriptors
//!             contained in the three returned descriptor sets (that is, the
//!             total number of bits that are set in readfds, writefds,
//!             exceptfds) which may be zero if the timeout expires before
//!             anything interesting  happens.
//!             On error, -1 is returned.
//!                   *readsds - return the sockets on which Read request will
//!                              return without delay with valid data.
//!                   *writesds - return the sockets on which Write request
//!                                 will return without delay.
//!                   *exceptsds - return the sockets which closed recently.
//!
//!  @brief  Monitor socket activity
//!          Select allow a program to monitor multiple file descriptors,
//!          waiting until one or more of the file descriptors become
//!         "ready" for some class of I/O operation
//!
//!  @Note   If the timeout value set to less than 5ms it will automatically set
//!          to 5ms to prevent overload of the system
//!
//!  @sa socket
//
//*****************************************************************************
#ifdef __ENABLE_MULTITHREADED_SUPPORT__
int c_select(long nfds, fd_set *readsds, fd_set *writesds,
                    fd_set *exceptsds, struct timeval *timeout)
#else /* __ENABLE_MULTITHREADED_SUPPORT__ */
int select(long nfds, fd_set2 *readsds, fd_set2 *writesds,
                    fd_set2 *exceptsds, struct timeval *timeout)
#endif /* __ENABLE_MULTITHREADED_SUPPORT__ */
{
    unsigned char *ptr, *args;
    tBsdSelectRecvParams tParams;
    unsigned long is_blocking;

    if( timeout == NULL)
    {
        is_blocking = 1; /* blocking , infinity timeout */
    }
    else
    {
        is_blocking = 0; /* no blocking, timeout */
    }

    // Fill in HCI packet structure
    ptr = tSLInformation.pucTxCommandBuffer;
    args = (ptr + HEADERS_SIZE_CMD);

    // Fill in temporary command buffer
    args = UINT32_TO_STREAM(args, nfds);
    args = UINT32_TO_STREAM(args, 0x00000014);
    args = UINT32_TO_STREAM(args, 0x00000014);
    args = UINT32_TO_STREAM(args, 0x00000014);
    args = UINT32_TO_STREAM(args, 0x00000014);
    args = UINT32_TO_STREAM(args, is_blocking);
    args = UINT32_TO_STREAM(args, ((readsds) ? *(unsigned long*)readsds : 0));
    args = UINT32_TO_STREAM(args, ((writesds) ? *(unsigned long*)writesds : 0));
    args = UINT32_TO_STREAM(args, ((exceptsds) ? *(unsigned long*)exceptsds : 0));

    if (timeout)
    {
        if ( 0 == timeout->tv_sec && timeout->tv_usec < SELECT_TIMEOUT_MIN_MICRO_SECONDS)
        {
            timeout->tv_usec = SELECT_TIMEOUT_MIN_MICRO_SECONDS;
        }
        args = UINT32_TO_STREAM(args, timeout->tv_sec);
        args = UINT32_TO_STREAM(args, timeout->tv_usec);
    }

    // Initiate a HCI command
    hci_command_send(HCI_CMND_BSD_SELECT, ptr, SOCKET_SELECT_PARAMS_LEN);

    // Since we are in blocking state - wait for event complete
    SimpleLinkWaitEvent(HCI_EVNT_SELECT, &tParams);

    // Update actually read FD
    if (tParams.iStatus >= 0)
    {
        if (readsds)
        {
            memcpy(readsds, &tParams.uiRdfd, sizeof(tParams.uiRdfd));
        }

        if (writesds)
        {
            memcpy(writesds, &tParams.uiWrfd, sizeof(tParams.uiWrfd));
        }

        if (exceptsds)
        {
            memcpy(exceptsds, &tParams.uiExfd, sizeof(tParams.uiExfd));
        }

        return(tParams.iStatus);

    }
    else
    {
        errno = tParams.iStatus;
        return(-1);
    }
}

//*****************************************************************************
//
//! setsockopt
//!
//!  @param[in]   sd          socket handle
//!  @param[in]   level       defines the protocol level for this option
//!  @param[in]   optname     defines the option name to Interrogate
//!  @param[in]   optval      specifies a value for the option
//!  @param[in]   optlen      specifies the length of the option value
//!  @return    On success, zero is returned. On error, -1 is returned
//!
//!  @brief  set socket options
//!          This function manipulate the options associated with a socket.
//!          Options may exist at multiple protocol levels; they are always
//!          present at the uppermost socket level.
//!          When manipulating socket options the level at which the option
//!          resides and the name of the option must be specified.
//!          To manipulate options at the socket level, level is specified as
//!          SOL_SOCKET. To manipulate options at any other level the protocol
//!          number of the appropriate protocol controlling the option is
//!          supplied. For example, to indicate that an option is to be
//!          interpreted by the TCP protocol, level should be set to the
//!          protocol number of TCP;
//!          The parameters optval and optlen are used to access optval -
//!          use for setsockopt(). For getsockopt() they identify a buffer
//!          in which the value for the requested option(s) are to
//!          be returned. For getsockopt(), optlen is a value-result
//!          parameter, initially containing the size of the buffer
//!          pointed to by option_value, and modified on return to
//!          indicate the actual size of the value returned. If no option
//!          value is to be supplied or returned, option_value may be NULL.
//!
//!  @Note   On this version the following two socket options are enabled:
//!              The only protocol level supported in this version
//!          is SOL_SOCKET (level).
//!            1. SOCKOPT_RECV_TIMEOUT (optname)
//!               SOCKOPT_RECV_TIMEOUT configures recv and recvfrom timeout
//!           in milliseconds.
//!             In that case optval should be pointer to unsigned long.
//!            2. SOCKOPT_NONBLOCK (optname). sets the socket non-blocking mode on
//!           or off.
//!             In that case optval should be SOCK_ON or SOCK_OFF (optval).
//!
//!  @sa getsockopt
//
//*****************************************************************************

#ifndef CC3000_TINY_DRIVER
#ifdef __ENABLE_MULTITHREADED_SUPPORT__
int
c_setsockopt(long sd, long level, long optname, const void *optval, socklen_t optlen)
#else /* __ENABLE_MULTITHREADED_SUPPORT__ */
int
setsockopt(long sd, long level, long optname, const void *optval, socklen_t optlen)
#endif /* __ENABLE_MULTITHREADED_SUPPORT__ */
{
    int ret;
    unsigned char *ptr, *args;

    ptr = tSLInformation.pucTxCommandBuffer;
    args = (ptr + HEADERS_SIZE_CMD);

    // Fill in temporary command buffer
    args = UINT32_TO_STREAM(args, sd);
    args = UINT32_TO_STREAM(args, level);
    args = UINT32_TO_STREAM(args, optname);
    args = UINT32_TO_STREAM(args, 0x00000008);
    args = UINT32_TO_STREAM(args, optlen);
    ARRAY_TO_STREAM(args, ((unsigned char *)optval), optlen);

    // Initiate a HCI command
    hci_command_send(HCI_CMND_SETSOCKOPT,
                                     ptr, SOCKET_SET_SOCK_OPT_PARAMS_LEN  + optlen);

    // Since we are in blocking state - wait for event complete
    SimpleLinkWaitEvent(HCI_CMND_SETSOCKOPT, &ret);

    if (ret >= 0)
    {
        return (0);
    }
    else
    {
        errno = ret;
        return (errno);
    }
}
#endif

//*****************************************************************************
//
//! getsockopt
//!
//!  @param[in]   sd          socket handle
//!  @param[in]   level       defines the protocol level for this option
//!  @param[in]   optname     defines the option name to Interrogate
//!  @param[out]   optval      specifies a value for the option
//!  @param[out]   optlen      specifies the length of the option value
//!  @return    On success, zero is returned. On error, -1 is returned
//!
//!  @brief  set socket options
//!          This function manipulate the options associated with a socket.
//!          Options may exist at multiple protocol levels; they are always
//!          present at the uppermost socket level.
//!          When manipulating socket options the level at which the option
//!          resides and the name of the option must be specified.
//!          To manipulate options at the socket level, level is specified as
//!          SOL_SOCKET. To manipulate options at any other level the protocol
//!          number of the appropriate protocol controlling the option is
//!          supplied. For example, to indicate that an option is to be
//!          interpreted by the TCP protocol, level should be set to the
//!          protocol number of TCP;
//!          The parameters optval and optlen are used to access optval -
//!          use for setsockopt(). For getsockopt() they identify a buffer
//!          in which the value for the requested option(s) are to
//!          be returned. For getsockopt(), optlen is a value-result
//!          parameter, initially containing the size of the buffer
//!          pointed to by option_value, and modified on return to
//!          indicate the actual size of the value returned. If no option
//!          value is to be supplied or returned, option_value may be NULL.
//!
//!  @Note   On this version the following two socket options are enabled:
//!              The only protocol level supported in this version
//!          is SOL_SOCKET (level).
//!            1. SOCKOPT_RECV_TIMEOUT (optname)
//!               SOCKOPT_RECV_TIMEOUT configures recv and recvfrom timeout
//!           in milliseconds.
//!             In that case optval should be pointer to unsigned long.
//!            2. SOCKOPT_NONBLOCK (optname). sets the socket non-blocking mode on
//!           or off.
//!             In that case optval should be SOCK_ON or SOCK_OFF (optval).
//!
//!  @sa setsockopt
//
//*****************************************************************************
#ifdef __ENABLE_MULTITHREADED_SUPPORT__
int c_getsockopt(long sd, long level, long optname, void *optval,
                         socklen_t *optlen)
#else /* __ENABLE_MULTITHREADED_SUPPORT__ */
int getsockopt(long sd, long level, long optname, void *optval,
                         socklen_t *optlen)
#endif /* __ENABLE_MULTITHREADED_SUPPORT__ */
{
    unsigned char *ptr, *args;
    tBsdGetSockOptReturnParams  tRetParams;

    ptr = tSLInformation.pucTxCommandBuffer;
    args = (ptr + HEADERS_SIZE_CMD);

    // Fill in temporary command buffer
    args = UINT32_TO_STREAM(args, sd);
    args = UINT32_TO_STREAM(args, level);
    args = UINT32_TO_STREAM(args, optname);

    // Initiate a HCI command
    hci_command_send(HCI_CMND_GETSOCKOPT,
       ptr, SOCKET_GET_SOCK_OPT_PARAMS_LEN);

    // Since we are in blocking state - wait for event complete
    SimpleLinkWaitEvent(HCI_CMND_GETSOCKOPT, &tRetParams);

    if (((signed char)tRetParams.iStatus) >= 0)
    {
        *optlen = 4;
        memcpy(optval, tRetParams.ucOptValue, 4);
        return (0);
    }
    else
    {
        errno = tRetParams.iStatus;
        return (errno);
    }
}

//*****************************************************************************
//
//!  simple_link_recv
//!
//!  @param sd       socket handle
//!  @param buf      read buffer
//!  @param len      buffer length
//!  @param flags    indicates blocking or non-blocking operation
//!  @param from     pointer to an address structure indicating source address
//!  @param fromlen  source address structure size
//!
//!  @return         Return the number of bytes received, or -1 if an error
//!                  occurred
//!
//!  @brief          Read data from socket
//!                  Return the length of the message on successful completion.
//!                  If a message is too long to fit in the supplied buffer,
//!                  excess bytes may be discarded depending on the type of
//!                  socket the message is received from
//
//*****************************************************************************
static int
simple_link_recv(long sd, void *buf, long len, long flags, sockaddr *from,
                socklen_t *fromlen, long opcode)
{
    unsigned char *ptr, *args;
    tBsdReadReturnParams tSocketReadEvent;

    ptr = tSLInformation.pucTxCommandBuffer;
    args = (ptr + HEADERS_SIZE_CMD);

    // Fill in HCI packet structure
    args = UINT32_TO_STREAM(args, sd);
    args = UINT32_TO_STREAM(args, len);
    args = UINT32_TO_STREAM(args, flags);

    // Generate the read command, and wait for the
    hci_command_send(opcode,  ptr, SOCKET_RECV_FROM_PARAMS_LEN);

    // Since we are in blocking state - wait for event complete
    SimpleLinkWaitEvent(opcode, &tSocketReadEvent);

    // In case the number of bytes is more then zero - read data
    if (tSocketReadEvent.iNumberOfBytes > 0)
    {
        // Wait for the data in a synchronous way. Here we assume that the bug is
        // big enough to store also parameters of receive from too....
        SimpleLinkWaitData(buf, (unsigned char *)from, (unsigned char *)fromlen);
    }

    errno = tSocketReadEvent.iNumberOfBytes;

    return(tSocketReadEvent.iNumberOfBytes);
}

//*****************************************************************************
//
//!  recv
//!
//!  @param[in]  sd     socket handle
//!  @param[out] buf    Points to the buffer where the message should be stored
//!  @param[in]  len    Specifies the length in bytes of the buffer pointed to
//!                     by the buffer argument.
//!  @param[in] flags   Specifies the type of message reception.
//!                     On this version, this parameter is not supported.
//!
//!  @return         Return the number of bytes received, or -1 if an error
//!                  occurred
//!
//!  @brief          function receives a message from a connection-mode socket
//!
//!  @sa recvfrom
//!
//!  @Note On this version, only blocking mode is supported.
//
//*****************************************************************************
#ifdef __ENABLE_MULTITHREADED_SUPPORT__
int c_recv(long sd, void *buf, long len, long flags)
#else /* __ENABLE_MULTITHREADED_SUPPORT__ */
int recv(long sd, void *buf, long len, long flags)
#endif /* __ENABLE_MULTITHREADED_SUPPORT__ */
{
    return(simple_link_recv(sd, buf, len, flags, NULL, NULL, HCI_CMND_RECV));
}

//*****************************************************************************
//
//!  recvfrom
//!
//!  @param[in]  sd     socket handle
//!  @param[out] buf    Points to the buffer where the message should be stored
//!  @param[in]  len    Specifies the length in bytes of the buffer pointed to
//!                     by the buffer argument.
//!  @param[in] flags   Specifies the type of message reception.
//!                     On this version, this parameter is not supported.
//!  @param[in] from   pointer to an address structure indicating the source
//!                    address: sockaddr. On this version only AF_INET is
//!                    supported.
//!  @param[in] fromlen   source address tructure size
//!
//!  @return         Return the number of bytes received, or -1 if an error
//!                  occurred
//!
//!  @brief         read data from socket
//!                 function receives a message from a connection-mode or
//!                 connectionless-mode socket. Note that raw sockets are not
//!                 supported.
//!
//!  @sa recv
//!
//!  @Note On this version, only blocking mode is supported.
//
//*****************************************************************************
#ifdef __ENABLE_MULTITHREADED_SUPPORT__
int c_recvfrom(long sd, void *buf, long len, long flags, sockaddr *from,
                      socklen_t *fromlen)
#else /* __ENABLE_MULTITHREADED_SUPPORT__ */
int recvfrom(long sd, void *buf, long len, long flags, sockaddr *from,
                      socklen_t *fromlen)
#endif /* __ENABLE_MULTITHREADED_SUPPORT__ */
{
    return(simple_link_recv(sd, buf, len, flags, from, fromlen,
           HCI_CMND_RECVFROM));
}
Exemplo n.º 3
0
int
recv(long sd, void *buf, long len, long flags)
{
	return(simple_link_recv(sd, buf, len, flags, NULL, NULL, HCI_CMND_RECV));
}
Exemplo n.º 4
0
    /* wait in busy loop */
    do
    {
        // In case last transmission failed then we will return the last failure
        // reason here.
        // Note that the buffer will not be allocated in this case
        if (tSLInformation.slTransmitDataError != 0)
        {
            errno = tSLInformation.slTransmitDataError;
            tSLInformation.slTransmitDataError = 0;
            return errno;
        }

        if(SOCKET_STATUS_ACTIVE != get_socket_active_status(sd))
            return -1;
    } while(0 == tSLInformation.usNumberOfFreeBuffers);

    tSLInformation.usNumberOfFreeBuffers--;

    return 0;
#else

    // In case last transmission failed then we will return the last failure
    // reason here.
    // Note that the buffer will not be allocated in this case
    if (tSLInformation.slTransmitDataError != 0)
    {
        errno = tSLInformation.slTransmitDataError;
        tSLInformation.slTransmitDataError = 0;
        return errno;
    }
    if(SOCKET_STATUS_ACTIVE != get_socket_active_status(sd))
        return -1;

    //If there are no available buffers, return -2. It is recommended to use
    // select or receive to see if there is any buffer occupied with received data
    // If so, call receive() to release the buffer.
    if(0 == tSLInformation.usNumberOfFreeBuffers)
    {
        return -2;
    }
    else
    {
        tSLInformation.usNumberOfFreeBuffers--;
        return 0;
    }
#endif
}

//*****************************************************************************
//
//! socket
//!
//!  @param  domain    selects the protocol family which will be used for
//!                    communication. On this version only AF_INET is supported
//!  @param  type      specifies the communication semantics. On this version
//!                    only SOCK_STREAM, SOCK_DGRAM, SOCK_RAW are supported
//!  @param  protocol  specifies a particular protocol to be used with the
//!                    socket IPPROTO_TCP, IPPROTO_UDP or IPPROTO_RAW are
//!                    supported.
//!
//!  @return  On success, socket handle that is used for consequent socket
//!           operations. On error, -1 is returned.
//!
//!  @brief  create an endpoint for communication
//!          The socket function creates a socket that is bound to a specific
//!          transport service provider. This function is called by the
//!          application layer to obtain a socket handle.
//
//*****************************************************************************

#ifdef __ENABLE_MULTITHREADED_SUPPORT__
int c_socket(long domain, long type, long protocol)
#else /* __ENABLE_MULTITHREADED_SUPPORT__ */
int socket(long domain, long type, long protocol)
#endif /* __ENABLE_MULTITHREADED_SUPPORT__ */
{
    long ret;
    unsigned char *ptr, *args;

    ret = EFAIL;
    ptr = tSLInformation.pucTxCommandBuffer;
    args = (ptr + HEADERS_SIZE_CMD);

    // Fill in HCI packet structure
    args = UINT32_TO_STREAM(args, domain);
    args = UINT32_TO_STREAM(args, type);
    args = UINT32_TO_STREAM(args, protocol);

    // Initiate a HCI command
    hci_command_send(HCI_CMND_SOCKET, ptr, SOCKET_OPEN_PARAMS_LEN);

    // Since we are in blocking state - wait for event complete
    SimpleLinkWaitEvent(HCI_CMND_SOCKET, &ret);

    // Process the event
    errno = ret;

    set_socket_active_status(ret, SOCKET_STATUS_ACTIVE);

    return(ret);
}

//*****************************************************************************
//
//! closesocket
//!
//!  @param  sd    socket handle.
//!
//!  @return  On success, zero is returned. On error, -1 is returned.
//!
//!  @brief  The socket function closes a created socket.
//
//*****************************************************************************

#ifdef __ENABLE_MULTITHREADED_SUPPORT__
long c_closesocket(long sd)
#else /* __ENABLE_MULTITHREADED_SUPPORT__ */
long closesocket(long sd)
#endif /* __ENABLE_MULTITHREADED_SUPPORT__ */
{
    long ret;
    unsigned char *ptr, *args;

    ret = EFAIL;
    ptr = tSLInformation.pucTxCommandBuffer;
    args = (ptr + HEADERS_SIZE_CMD);

    // Fill in HCI packet structure
    args = UINT32_TO_STREAM(args, sd);

    // Initiate a HCI command
    hci_command_send(HCI_CMND_CLOSE_SOCKET,
                                     ptr, SOCKET_CLOSE_PARAMS_LEN);

    // Since we are in blocking state - wait for event complete
    SimpleLinkWaitEvent(HCI_CMND_CLOSE_SOCKET, &ret);
    errno = ret;

    // since 'close' call may result in either OK (and then it closed) or error
    // mark this socket as invalid
    set_socket_active_status(sd, SOCKET_STATUS_INACTIVE);

    return(ret);
}

//*****************************************************************************
//
//! accept
//!
//!  @param[in]   sd      socket descriptor (handle)
//!  @param[out]  addr    the argument addr is a pointer to a sockaddr structure
//!                       This structure is filled in with the address of the
//!                       peer socket, as known to the communications layer.
//!                       determined. The exact format of the address returned
//!                       addr is by the socket's address sockaddr.
//!                       On this version only AF_INET is supported.
//!                       This argument returns in network order.
//!  @param[out] addrlen  the addrlen argument is a value-result argument:
//!                       it should initially contain the size of the structure
//!                       pointed to by addr.
//!
//!  @return  For socket in blocking mode:
//!                   On success, socket handle. on failure negative
//!               For socket in non-blocking mode:
//!                  - On connection establishment, socket handle
//!                  - On connection pending, SOC_IN_PROGRESS (-2)
//!                - On failure, SOC_ERROR  (-1)
//!
//!  @brief  accept a connection on a socket:
//!          This function is used with connection-based socket types
//!          (SOCK_STREAM). It extracts the first connection request on the
//!          queue of pending connections, creates a new connected socket, and
//!          returns a new file descriptor referring to that socket.
//!          The newly created socket is not in the listening state.
//!          The original socket sd is unaffected by this call.
//!          The argument sd is a socket that has been created with socket(),
//!          bound to a local address with bind(), and is  listening for
//!          connections after a listen(). The argument addr is a pointer
//!          to a sockaddr structure. This structure is filled in with the
//!          address of the peer socket, as known to the communications layer.
//!          The exact format of the address returned addr is determined by the
//!          socket's address family. The addrlen argument is a value-result
//!          argument: it should initially contain the size of the structure
//!          pointed to by addr, on return it will contain the actual
//!          length (in bytes) of the address returned.
//!
//! @sa     socket ; bind ; listen
//
//*****************************************************************************
#ifdef __ENABLE_MULTITHREADED_SUPPORT__
long c_accept(long sd, sockaddr *addr, socklen_t *addrlen)
#else /* __ENABLE_MULTITHREADED_SUPPORT__ */
long accept(long sd, sockaddr *addr, socklen_t *addrlen)
#endif /* __ENABLE_MULTITHREADED_SUPPORT__ */
{
    long ret;
    unsigned char *ptr, *args;
    tBsdReturnParams tAcceptReturnArguments;

    ret = EFAIL;
    ptr = tSLInformation.pucTxCommandBuffer;
    args = (ptr + HEADERS_SIZE_CMD);

    // Fill in temporary command buffer
    args = UINT32_TO_STREAM(args, sd);

    // Initiate a HCI command
    hci_command_send(HCI_CMND_ACCEPT,
                                     ptr, SOCKET_ACCEPT_PARAMS_LEN);

    // Since we are in blocking state - wait for event complete
    SimpleLinkWaitEvent(HCI_CMND_ACCEPT, &tAcceptReturnArguments);


    // need specify return parameters!!!
    memcpy(addr, &tAcceptReturnArguments.tSocketAddress, ASIC_ADDR_LEN);
    *addrlen = ASIC_ADDR_LEN;
    errno = tAcceptReturnArguments.iStatus;
    ret = errno;

    // if succeeded, iStatus = new socket descriptor. otherwise - error number
    if(M_IS_VALID_SD(ret))
    {
        set_socket_active_status(ret, SOCKET_STATUS_ACTIVE);
    }
    else
    {
        set_socket_active_status(sd, SOCKET_STATUS_INACTIVE);
    }

    return(ret);
}

//*****************************************************************************
//
//! bind
//!
//!  @param[in]   sd      socket descriptor (handle)
//!  @param[out]  addr    specifies the destination address. On this version
//!                       only AF_INET is supported.
//!  @param[out] addrlen  contains the size of the structure pointed to by addr.
//!
//!  @return    On success, zero is returned. On error, -1 is returned.
//!
//!  @brief  assign a name to a socket
//!          This function gives the socket the local address addr.
//!          addr is addrlen bytes long. Traditionally, this is called when a
//!          socket is created with socket, it exists in a name space (address
//!          family) but has no name assigned.
//!          It is necessary to assign a local address before a SOCK_STREAM
//!          socket may receive connections.
//!
//! @sa     socket ; accept ; listen
//
//*****************************************************************************
#ifdef __ENABLE_MULTITHREADED_SUPPORT__
long c_bind(long sd, const sockaddr *addr, long addrlen)
#else /* __ENABLE_MULTITHREADED_SUPPORT__ */
long bind(long sd, const sockaddr *addr, long addrlen)
#endif /* __ENABLE_MULTITHREADED_SUPPORT__ */
{
    long ret;
    unsigned char *ptr, *args;

    ret = EFAIL;
    ptr = tSLInformation.pucTxCommandBuffer;
    args = (ptr + HEADERS_SIZE_CMD);

    addrlen = ASIC_ADDR_LEN;

    // Fill in temporary command buffer
    args = UINT32_TO_STREAM(args, sd);
    args = UINT32_TO_STREAM(args, 0x00000008);
    args = UINT32_TO_STREAM(args, addrlen);
    ARRAY_TO_STREAM(args, ((unsigned char *)addr), addrlen);

    // Initiate a HCI command
    hci_command_send(HCI_CMND_BIND,
                                     ptr, SOCKET_BIND_PARAMS_LEN);

    // Since we are in blocking state - wait for event complete
    SimpleLinkWaitEvent(HCI_CMND_BIND, &ret);

    errno = ret;

    return(ret);
}

//*****************************************************************************
//
//! listen
//!
//!  @param[in]   sd      socket descriptor (handle)
//!  @param[in]  backlog  specifies the listen queue depth. On this version
//!                       backlog is not supported.
//!  @return    On success, zero is returned. On error, -1 is returned.
//!
//!  @brief  listen for connections on a socket
//!          The willingness to accept incoming connections and a queue
//!          limit for incoming connections are specified with listen(),
//!          and then the connections are accepted with accept.
//!          The listen() call applies only to sockets of type SOCK_STREAM
//!          The backlog parameter defines the maximum length the queue of
//!          pending connections may grow to.
//!
//! @sa     socket ; accept ; bind
//!
//! @note   On this version, backlog is not supported
//
//*****************************************************************************
#ifdef __ENABLE_MULTITHREADED_SUPPORT__
long c_listen(long sd, long backlog)
#else /* __ENABLE_MULTITHREADED_SUPPORT__ */
long listen(long sd, long backlog)
#endif /* __ENABLE_MULTITHREADED_SUPPORT__ */
{
    long ret;
    unsigned char *ptr, *args;

    ret = EFAIL;
    ptr = tSLInformation.pucTxCommandBuffer;
    args = (ptr + HEADERS_SIZE_CMD);

    // Fill in temporary command buffer
    args = UINT32_TO_STREAM(args, sd);
    args = UINT32_TO_STREAM(args, backlog);

    // Initiate a HCI command
    hci_command_send(HCI_CMND_LISTEN,
                                     ptr, SOCKET_LISTEN_PARAMS_LEN);

    // Since we are in blocking state - wait for event complete
    SimpleLinkWaitEvent(HCI_CMND_LISTEN, &ret);
    errno = ret;

    return(ret);
}

//*****************************************************************************
//
//! gethostbyname
//!
//!  @param[in]   hostname     host name
//!  @param[in]   usNameLen    name length
//!  @param[out]  out_ip_addr  This parameter is filled in with host IP address.
//!                            In case that host name is not resolved,
//!                            out_ip_addr is zero.
//!  @return    On success, positive is returned. On error, negative is returned
//!
//!  @brief  Get host IP by name. Obtain the IP Address of machine on network,
//!          by its name.
//!
//!  @note  On this version, only blocking mode is supported. Also note that
//!          the function requires DNS server to be configured prior to its usage.
//
//*****************************************************************************

#ifndef CC3000_TINY_DRIVER
#ifdef __ENABLE_MULTITHREADED_SUPPORT__
int
c_gethostbyname(char * hostname, unsigned short usNameLen, unsigned long* out_ip_addr)
#else /* __ENABLE_MULTITHREADED_SUPPORT__ */
int
gethostbyname(char * hostname, unsigned short usNameLen, unsigned long* out_ip_addr)
#endif /*__ENABLE_MULTITHREADED_SUPPORT__ */
{
    tBsdGethostbynameParams ret;
    unsigned char *ptr, *args;

    errno = EFAIL;

    if (usNameLen > HOSTNAME_MAX_LENGTH)
    {
        return errno;
    }

    ptr = tSLInformation.pucTxCommandBuffer;
    args = (ptr + SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE);

    // Fill in HCI packet structure
    args = UINT32_TO_STREAM(args, 8);
    args = UINT32_TO_STREAM(args, usNameLen);
    ARRAY_TO_STREAM(args, hostname, usNameLen);

    // Initiate a HCI command
    hci_command_send(HCI_CMND_GETHOSTNAME, ptr, SOCKET_GET_HOST_BY_NAME_PARAMS_LEN
                                     + usNameLen - 1);

    // Since we are in blocking state - wait for event complete
    SimpleLinkWaitEvent(HCI_EVNT_BSD_GETHOSTBYNAME, &ret);

    errno = ret.retVal;

    (*((long*)out_ip_addr)) = ret.outputAddress;

    return (errno);

}
#endif

//*****************************************************************************
//
//! connect
//!
//!  @param[in]   sd       socket descriptor (handle)
//!  @param[in]   addr     specifies the destination addr. On this version
//!                        only AF_INET is supported.
//!  @param[out]  addrlen  contains the size of the structure pointed to by addr
//!  @return    On success, zero is returned. On error, -1 is returned
//!
//!  @brief  initiate a connection on a socket
//!          Function connects the socket referred to by the socket descriptor
//!          sd, to the address specified by addr. The addrlen argument
//!          specifies the size of addr. The format of the address in addr is
//!          determined by the address space of the socket. If it is of type
//!          SOCK_DGRAM, this call specifies the peer with which the socket is
//!          to be associated; this address is that to which datagrams are to be
//!          sent, and the only address from which datagrams are to be received.
//!          If the socket is of type SOCK_STREAM, this call attempts to make a
//!          connection to another socket. The other socket is specified  by
//!          address, which is an address in the communications space of the
//!          socket. Note that the function implements only blocking behavior
//!          thus the caller will be waiting either for the connection
//!          establishment or for the connection establishment failure.
//!
//!  @sa socket
//
//*****************************************************************************
#ifdef __ENABLE_MULTITHREADED_SUPPORT__
long c_connect(long sd, const sockaddr *addr, long addrlen)
#else /* __ENABLE_MULTITHREADED_SUPPORT__ */
long connect(long sd, const sockaddr *addr, long addrlen)
#endif /* __ENABLE_MULTITHREADED_SUPPORT__ */
{
    long int ret;
    unsigned char *ptr, *args;

    ret = EFAIL;
    ptr = tSLInformation.pucTxCommandBuffer;
    args = (ptr + SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE);
    addrlen = 8;

    // Fill in temporary command buffer
    args = UINT32_TO_STREAM(args, sd);
    args = UINT32_TO_STREAM(args, 0x00000008);
    args = UINT32_TO_STREAM(args, addrlen);
    ARRAY_TO_STREAM(args, ((unsigned char *)addr), addrlen);

    // Initiate a HCI command
    hci_command_send(HCI_CMND_CONNECT,
                                     ptr, SOCKET_CONNECT_PARAMS_LEN);

    // Since we are in blocking state - wait for event complete
    SimpleLinkWaitEvent(HCI_CMND_CONNECT, &ret);

    errno = ret;

    return((long)ret);
}


//*****************************************************************************
//
//! select
//!
//!  @param[in]   nfds       the highest-numbered file descriptor in any of the
//!                           three sets, plus 1.
//!  @param[out]   writesds   socket descriptors list for write monitoring
//!  @param[out]   readsds    socket descriptors list for read monitoring
//!  @param[out]   exceptsds  socket descriptors list for exception monitoring
//!  @param[in]   timeout     is an upper bound on the amount of time elapsed
//!                           before select() returns. Null means infinity
//!                           timeout. The minimum timeout is 5 milliseconds,
//!                          less than 5 milliseconds will be set
//!                           automatically to 5 milliseconds.
//!  @return    On success, select() returns the number of file descriptors
//!             contained in the three returned descriptor sets (that is, the
//!             total number of bits that are set in readfds, writefds,
//!             exceptfds) which may be zero if the timeout expires before
//!             anything interesting  happens.
//!             On error, -1 is returned.
//!                   *readsds - return the sockets on which Read request will
//!                              return without delay with valid data.
//!                   *writesds - return the sockets on which Write request
//!                                 will return without delay.
//!                   *exceptsds - return the sockets which closed recently.
//!
//!  @brief  Monitor socket activity
//!          Select allow a program to monitor multiple file descriptors,
//!          waiting until one or more of the file descriptors become
//!         "ready" for some class of I/O operation
//!
//!  @Note   If the timeout value set to less than 5ms it will automatically set
//!          to 5ms to prevent overload of the system
//!
//!  @sa socket
//
//*****************************************************************************
#ifdef __ENABLE_MULTITHREADED_SUPPORT__
int c_select(long nfds, fd_set *readsds, fd_set *writesds,
                    fd_set *exceptsds, struct timeval *timeout)
#else /* __ENABLE_MULTITHREADED_SUPPORT__ */
int select(long nfds, fd_set2 *readsds, fd_set2 *writesds,
                    fd_set2 *exceptsds, struct timeval *timeout)
#endif /* __ENABLE_MULTITHREADED_SUPPORT__ */
{
    unsigned char *ptr, *args;
    tBsdSelectRecvParams tParams;
    unsigned long is_blocking;

    if( timeout == NULL)
    {
        is_blocking = 1; /* blocking , infinity timeout */
    }
    else
    {
        is_blocking = 0; /* no blocking, timeout */
    }

    // Fill in HCI packet structure
    ptr = tSLInformation.pucTxCommandBuffer;
    args = (ptr + HEADERS_SIZE_CMD);

    // Fill in temporary command buffer
    args = UINT32_TO_STREAM(args, nfds);
    args = UINT32_TO_STREAM(args, 0x00000014);
    args = UINT32_TO_STREAM(args, 0x00000014);
    args = UINT32_TO_STREAM(args, 0x00000014);
    args = UINT32_TO_STREAM(args, 0x00000014);
    args = UINT32_TO_STREAM(args, is_blocking);
    args = UINT32_TO_STREAM(args, ((readsds) ? *(unsigned long*)readsds : 0));
    args = UINT32_TO_STREAM(args, ((writesds) ? *(unsigned long*)writesds : 0));
    args = UINT32_TO_STREAM(args, ((exceptsds) ? *(unsigned long*)exceptsds : 0));

    if (timeout)
    {
        if ( 0 == timeout->tv_sec && timeout->tv_usec < SELECT_TIMEOUT_MIN_MICRO_SECONDS)
        {
            timeout->tv_usec = SELECT_TIMEOUT_MIN_MICRO_SECONDS;
        }
        args = UINT32_TO_STREAM(args, timeout->tv_sec);
        args = UINT32_TO_STREAM(args, timeout->tv_usec);
    }

    // Initiate a HCI command
    hci_command_send(HCI_CMND_BSD_SELECT, ptr, SOCKET_SELECT_PARAMS_LEN);

    // Since we are in blocking state - wait for event complete
    SimpleLinkWaitEvent(HCI_EVNT_SELECT, &tParams);

    // Update actually read FD
    if (tParams.iStatus >= 0)
    {
        if (readsds)
        {
            memcpy(readsds, &tParams.uiRdfd, sizeof(tParams.uiRdfd));
        }

        if (writesds)
        {
            memcpy(writesds, &tParams.uiWrfd, sizeof(tParams.uiWrfd));
        }

        if (exceptsds)
        {
            memcpy(exceptsds, &tParams.uiExfd, sizeof(tParams.uiExfd));
        }

        return(tParams.iStatus);

    }
    else
    {
        errno = tParams.iStatus;
        return(-1);
    }
}

//*****************************************************************************
//
//! setsockopt
//!
//!  @param[in]   sd          socket handle
//!  @param[in]   level       defines the protocol level for this option
//!  @param[in]   optname     defines the option name to Interrogate
//!  @param[in]   optval      specifies a value for the option
//!  @param[in]   optlen      specifies the length of the option value
//!  @return    On success, zero is returned. On error, -1 is returned
//!
//!  @brief  set socket options
//!          This function manipulate the options associated with a socket.
//!          Options may exist at multiple protocol levels; they are always
//!          present at the uppermost socket level.
//!          When manipulating socket options the level at which the option
//!          resides and the name of the option must be specified.
//!          To manipulate options at the socket level, level is specified as
//!          SOL_SOCKET. To manipulate options at any other level the protocol
//!          number of the appropriate protocol controlling the option is
//!          supplied. For example, to indicate that an option is to be
//!          interpreted by the TCP protocol, level should be set to the
//!          protocol number of TCP;
//!          The parameters optval and optlen are used to access optval -
//!          use for setsockopt(). For getsockopt() they identify a buffer
//!          in which the value for the requested option(s) are to
//!          be returned. For getsockopt(), optlen is a value-result
//!          parameter, initially containing the size of the buffer
//!          pointed to by option_value, and modified on return to
//!          indicate the actual size of the value returned. If no option
//!          value is to be supplied or returned, option_value may be NULL.
//!
//!  @Note   On this version the following two socket options are enabled:
//!              The only protocol level supported in this version
//!          is SOL_SOCKET (level).
//!            1. SOCKOPT_RECV_TIMEOUT (optname)
//!               SOCKOPT_RECV_TIMEOUT configures recv and recvfrom timeout
//!           in milliseconds.
//!             In that case optval should be pointer to unsigned long.
//!            2. SOCKOPT_NONBLOCK (optname). sets the socket non-blocking mode on
//!           or off.
//!             In that case optval should be SOCK_ON or SOCK_OFF (optval).
//!
//!  @sa getsockopt
//
//*****************************************************************************

#ifndef CC3000_TINY_DRIVER
#ifdef __ENABLE_MULTITHREADED_SUPPORT__
int
c_setsockopt(long sd, long level, long optname, const void *optval, socklen_t optlen)
#else /* __ENABLE_MULTITHREADED_SUPPORT__ */
int
setsockopt(long sd, long level, long optname, const void *optval, socklen_t optlen)
#endif /* __ENABLE_MULTITHREADED_SUPPORT__ */
{
    int ret;
    unsigned char *ptr, *args;

    ptr = tSLInformation.pucTxCommandBuffer;
    args = (ptr + HEADERS_SIZE_CMD);

    // Fill in temporary command buffer
    args = UINT32_TO_STREAM(args, sd);
    args = UINT32_TO_STREAM(args, level);
    args = UINT32_TO_STREAM(args, optname);
    args = UINT32_TO_STREAM(args, 0x00000008);
    args = UINT32_TO_STREAM(args, optlen);
    ARRAY_TO_STREAM(args, ((unsigned char *)optval), optlen);

    // Initiate a HCI command
    hci_command_send(HCI_CMND_SETSOCKOPT,
                                     ptr, SOCKET_SET_SOCK_OPT_PARAMS_LEN  + optlen);

    // Since we are in blocking state - wait for event complete
    SimpleLinkWaitEvent(HCI_CMND_SETSOCKOPT, &ret);

    if (ret >= 0)
    {
        return (0);
    }
    else
    {
        errno = ret;
        return (errno);
    }
}
#endif

//*****************************************************************************
//
//! getsockopt
//!
//!  @param[in]   sd          socket handle
//!  @param[in]   level       defines the protocol level for this option
//!  @param[in]   optname     defines the option name to Interrogate
//!  @param[out]   optval      specifies a value for the option
//!  @param[out]   optlen      specifies the length of the option value
//!  @return    On success, zero is returned. On error, -1 is returned
//!
//!  @brief  set socket options
//!          This function manipulate the options associated with a socket.
//!          Options may exist at multiple protocol levels; they are always
//!          present at the uppermost socket level.
//!          When manipulating socket options the level at which the option
//!          resides and the name of the option must be specified.
//!          To manipulate options at the socket level, level is specified as
//!          SOL_SOCKET. To manipulate options at any other level the protocol
//!          number of the appropriate protocol controlling the option is
//!          supplied. For example, to indicate that an option is to be
//!          interpreted by the TCP protocol, level should be set to the
//!          protocol number of TCP;
//!          The parameters optval and optlen are used to access optval -
//!          use for setsockopt(). For getsockopt() they identify a buffer
//!          in which the value for the requested option(s) are to
//!          be returned. For getsockopt(), optlen is a value-result
//!          parameter, initially containing the size of the buffer
//!          pointed to by option_value, and modified on return to
//!          indicate the actual size of the value returned. If no option
//!          value is to be supplied or returned, option_value may be NULL.
//!
//!  @Note   On this version the following two socket options are enabled:
//!              The only protocol level supported in this version
//!          is SOL_SOCKET (level).
//!            1. SOCKOPT_RECV_TIMEOUT (optname)
//!               SOCKOPT_RECV_TIMEOUT configures recv and recvfrom timeout
//!           in milliseconds.
//!             In that case optval should be pointer to unsigned long.
//!            2. SOCKOPT_NONBLOCK (optname). sets the socket non-blocking mode on
//!           or off.
//!             In that case optval should be SOCK_ON or SOCK_OFF (optval).
//!
//!  @sa setsockopt
//
//*****************************************************************************
#ifdef __ENABLE_MULTITHREADED_SUPPORT__
int c_getsockopt(long sd, long level, long optname, void *optval,
                         socklen_t *optlen)
#else /* __ENABLE_MULTITHREADED_SUPPORT__ */
int getsockopt(long sd, long level, long optname, void *optval,
                         socklen_t *optlen)
#endif /* __ENABLE_MULTITHREADED_SUPPORT__ */
{
    unsigned char *ptr, *args;
    tBsdGetSockOptReturnParams  tRetParams;

    ptr = tSLInformation.pucTxCommandBuffer;
    args = (ptr + HEADERS_SIZE_CMD);

    // Fill in temporary command buffer
    args = UINT32_TO_STREAM(args, sd);
    args = UINT32_TO_STREAM(args, level);
    args = UINT32_TO_STREAM(args, optname);

    // Initiate a HCI command
    hci_command_send(HCI_CMND_GETSOCKOPT,
       ptr, SOCKET_GET_SOCK_OPT_PARAMS_LEN);

    // Since we are in blocking state - wait for event complete
    SimpleLinkWaitEvent(HCI_CMND_GETSOCKOPT, &tRetParams);

    if (((signed char)tRetParams.iStatus) >= 0)
    {
        *optlen = 4;
        memcpy(optval, tRetParams.ucOptValue, 4);
        return (0);
    }
    else
    {
        errno = tRetParams.iStatus;
        return (errno);
    }
}

//*****************************************************************************
//
//!  simple_link_recv
//!
//!  @param sd       socket handle
//!  @param buf      read buffer
//!  @param len      buffer length
//!  @param flags    indicates blocking or non-blocking operation
//!  @param from     pointer to an address structure indicating source address
//!  @param fromlen  source address structure size
//!
//!  @return         Return the number of bytes received, or -1 if an error
//!                  occurred
//!
//!  @brief          Read data from socket
//!                  Return the length of the message on successful completion.
//!                  If a message is too long to fit in the supplied buffer,
//!                  excess bytes may be discarded depending on the type of
//!                  socket the message is received from
//
//*****************************************************************************
static int
simple_link_recv(long sd, void *buf, long len, long flags, sockaddr *from,
                socklen_t *fromlen, long opcode)
{
    unsigned char *ptr, *args;
    tBsdReadReturnParams tSocketReadEvent;

    ptr = tSLInformation.pucTxCommandBuffer;
    args = (ptr + HEADERS_SIZE_CMD);

    // Fill in HCI packet structure
    args = UINT32_TO_STREAM(args, sd);
    args = UINT32_TO_STREAM(args, len);
    args = UINT32_TO_STREAM(args, flags);

    // Generate the read command, and wait for the
    hci_command_send(opcode,  ptr, SOCKET_RECV_FROM_PARAMS_LEN);

    // Since we are in blocking state - wait for event complete
    SimpleLinkWaitEvent(opcode, &tSocketReadEvent);

    // In case the number of bytes is more then zero - read data
    if (tSocketReadEvent.iNumberOfBytes > 0)
    {
        // Wait for the data in a synchronous way. Here we assume that the bug is
        // big enough to store also parameters of receive from too....
        SimpleLinkWaitData(buf, (unsigned char *)from, (unsigned char *)fromlen);
    }

    errno = tSocketReadEvent.iNumberOfBytes;

    return(tSocketReadEvent.iNumberOfBytes);
}

//*****************************************************************************
//
//!  recv
//!
//!  @param[in]  sd     socket handle
//!  @param[out] buf    Points to the buffer where the message should be stored
//!  @param[in]  len    Specifies the length in bytes of the buffer pointed to
//!                     by the buffer argument.
//!  @param[in] flags   Specifies the type of message reception.
//!                     On this version, this parameter is not supported.
//!
//!  @return         Return the number of bytes received, or -1 if an error
//!                  occurred
//!
//!  @brief          function receives a message from a connection-mode socket
//!
//!  @sa recvfrom
//!
//!  @Note On this version, only blocking mode is supported.
//
//*****************************************************************************
#ifdef __ENABLE_MULTITHREADED_SUPPORT__
int c_recv(long sd, void *buf, long len, long flags)
#else /* __ENABLE_MULTITHREADED_SUPPORT__ */
int recv(long sd, void *buf, long len, long flags)
#endif /* __ENABLE_MULTITHREADED_SUPPORT__ */
{
    return(simple_link_recv(sd, buf, len, flags, NULL, NULL, HCI_CMND_RECV));
}
Exemplo n.º 5
0
//*****************************************************************************
//
//!  recvfrom
//!
//!  @param[in]  sd     socket handle
//!  @param[out] buf    Points to the buffer where the message should be stored
//!  @param[in]  len    Specifies the length in bytes of the buffer pointed to 
//!                     by the buffer argument.
//!  @param[in] flags   Specifies the type of message reception. 
//!                     On this version, this parameter is not supported.
//!  @param[in] from   pointer to an address structure indicating the source
//!                    address: sockaddr. On this version only AF_INET is
//!                    supported.
//!  @param[in] fromlen   source address tructure size
//!
//!  @return         Return the number of bytes received, or -1 if an error
//!                  occurred
//!
//!  @brief         read data from socket
//!                 function receives a message from a connection-mode or
//!                 connectionless-mode socket. Note that raw sockets are not
//!                 supported.
//!
//!  @sa recv
//!
//!  @Note On this version, only blocking mode is supported.
//
//*****************************************************************************
INT16 recvfrom(INT32 sd, void *buf, INT32 len, INT32 flags, sockaddr *from,
		socklen_t *fromlen)
{
	return(simple_link_recv(sd, buf, len, flags, from, fromlen,
			HCI_CMND_RECVFROM));
}
Exemplo n.º 6
0
INT16 recv(INT32 sd, void *buf, INT32 len, INT32 flags)
{
	return(simple_link_recv(sd, buf, len, flags, NULL, NULL, HCI_CMND_RECV));
}