version_2.0

Dependents:   cc3000_ping_demo_try_2

Fork of cc3000_hostdriver_mbedsocket by Martin Kojtal

Revision:
20:30b6ed7bf8fd
Parent:
16:f3676ae62f96
Child:
42:bd2c631a031a
diff -r 9fdf8b4e41bf -r 30b6ed7bf8fd cc3000_socket.cpp
--- a/cc3000_socket.cpp	Thu Oct 03 09:49:03 2013 +0200
+++ b/cc3000_socket.cpp	Thu Oct 03 17:15:45 2013 +0200
@@ -1,603 +1,603 @@
-/*****************************************************************************
-*
-*  C++ interface/implementation created by Martin Kojtal (0xc0170). Thanks to
-*  Jim Carver and Frank Vannieuwkerke for their inital cc3000 mbed port and
-*  provided help.
-*
-*  This version of "host driver" uses CC3000 Host Driver Implementation. Thus
-*  read the following copyright:
-*
-*  Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
-*
-*  Redistribution and use in source and binary forms, with or without
-*  modification, are permitted provided that the following conditions
-*  are met:
-*
-*    Redistributions of source code must retain the above copyright
-*    notice, this list of conditions and the following disclaimer.
-*
-*    Redistributions in binary form must reproduce the above copyright
-*    notice, this list of conditions and the following disclaimer in the
-*    documentation and/or other materials provided with the
-*    distribution.
-*
-*    Neither the name of Texas Instruments Incorporated nor the names of
-*    its contributors may be used to endorse or promote products derived
-*    from this software without specific prior written permission.
-*
-*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-*  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-*  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-*  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-*  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-*  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-*  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-*  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-*  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*
-*****************************************************************************/
-#include "cc3000.h"
-#include "cc3000_socket.h"
-#include "cc3000_event.h" //TODO - remove this
-#include "cc3000_common.h"
-
-namespace mbed_cc3000 {
-
-cc3000_socket::cc3000_socket(cc3000_simple_link &simplelink, cc3000_hci &hci, cc3000_event &event)
-    : _simple_link(simplelink), _hci(hci), _event(event)
-{
-
-}
-
-cc3000_socket::~cc3000_socket()
-{
-
-}
-
-int32_t cc3000_socket::HostFlowControlConsumeBuff(int32_t sd) {
-#ifndef SEND_NON_BLOCKING
-    /* wait in busy loop */
-    do
-    {
-        // When the last transmission failed, return the last failure reason.
-        // Note that the buffer will not be allocated in this case
-        if (_simple_link.get_transmit_error() != 0)
-        {
-            errno = _simple_link.get_transmit_error();
-            _simple_link.set_transmit_error(0);
-            return errno;
-        }
-
-        if(SOCKET_STATUS_ACTIVE != _event.get_socket_active_status(sd))
-            return -1;
-    } while(0 == _simple_link.get_number_free_buffers());
-
-    uint16_t free_buffer = _simple_link.get_number_free_buffers();
-    free_buffer--;
-    _simple_link.set_number_free_buffers(free_buffer);
-
-    return 0;
-#else
-
-    // When the last transmission failed, return the last failure reason.
-    // Note that the buffer will not be allocated in this case
-    if (_simple_link.get_transmit_error() != 0)
-    {
-        errno = _simple_link.get_transmit_error();
-        _simple_link.set_transmit_error(0);
-        return errno;
-    }
-    if(SOCKET_STATUS_ACTIVE != _event.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 == _simple_link.get_number_free_buffers())
-    {
-        return -2;
-    }
-    else
-    {
-        uint16_t free_buffer = _simple_link.get_number_free_buffers();
-        free_buffer--;
-        _simple_link.set_number_free_buffers(free_buffer);
-        return 0;
-    }
-#endif
-}
-
-int32_t cc3000_socket::socket(int32_t domain, int32_t type, int32_t protocol) {
-    int32_t ret;
-    uint8_t *ptr, *args;
-
-    ret = EFAIL;
-    ptr = _simple_link.get_transmit_buffer();
-    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
-    _event.simplelink_wait_event(HCI_CMND_SOCKET, &ret);
-
-    // Process the event
-    errno = ret;
-
-    _event.set_socket_active_status(ret, SOCKET_STATUS_ACTIVE);
-
-    return(ret);
-}
-
-int32_t cc3000_socket::closesocket(int32_t sd) {
-    int32_t ret;
-    uint8_t *ptr, *args;
-
-    while(_simple_link.get_number_free_buffers() != SOCKET_MAX_FREE_BUFFERS);
-    ret = EFAIL;
-    ptr = _simple_link.get_transmit_buffer();
-    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
-    _event.simplelink_wait_event(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
-    _event.set_socket_active_status(sd, SOCKET_STATUS_INACTIVE);
-
-    return(ret);
-}
-
-int32_t cc3000_socket::accept(int32_t sd, sockaddr *addr, socklen_t *addrlen) {
-    int32_t ret;
-    uint8_t *ptr, *args;
-    tBsdReturnParams tAcceptReturnArguments;
-
-    ret = EFAIL;
-    ptr = _simple_link.get_transmit_buffer();
-    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
-    _event.simplelink_wait_event(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))
-    {
-        _event.set_socket_active_status(ret, SOCKET_STATUS_ACTIVE);
-    }
-    else
-    {
-        _event.set_socket_active_status(sd, SOCKET_STATUS_INACTIVE);
-    }
-
-    return(ret);
-}
-
-int32_t cc3000_socket::bind(int32_t sd, const sockaddr *addr, int32_t addrlen) {
-    int32_t ret;
-    uint8_t *ptr, *args;
-
-    ret = EFAIL;
-    ptr = _simple_link.get_transmit_buffer();
-    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, ((uint8_t *)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
-    _event.simplelink_wait_event(HCI_CMND_BIND, &ret);
-
-    errno = ret;
-
-    return(ret);
-}
-
-int32_t cc3000_socket::listen(int32_t sd, int32_t backlog) {
-    int32_t ret;
-    uint8_t *ptr, *args;
-
-    ret = EFAIL;
-    ptr = _simple_link.get_transmit_buffer();
-    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
-    _event.simplelink_wait_event(HCI_CMND_LISTEN, &ret);
-    errno = ret;
-
-    return(ret);
-}
-
-int32_t cc3000_socket::connect(int32_t sd, const sockaddr *addr, int32_t addrlen) {
-    int32_t ret;
-    uint8_t *ptr, *args;
-
-    ret = EFAIL;
-    ptr = _simple_link.get_transmit_buffer();
-    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, ((uint8_t *)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
-    _event.simplelink_wait_event(HCI_CMND_CONNECT, &ret);
-
-    errno = ret;
-
-    return((int32_t)ret);
-}
-
-int32_t cc3000_socket::select(int32_t nfds, fd_set *readsds, fd_set *writesds, fd_set *exceptsds, struct timeval *timeout) {
-    uint8_t *ptr, *args;
-    tBsdSelectRecvParams tParams;
-    uint32_t is_blocking;
-
-    if( timeout == NULL)
-    {
-        is_blocking = 1; /* blocking , infinity timeout */
-    }
-    else
-    {
-        is_blocking = 0; /* no blocking, timeout */
-    }
-
-    // Fill in HCI packet structure
-    ptr = _simple_link.get_transmit_buffer();
-    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) ? *(uint32_t*)readsds : 0));
-    args = UINT32_TO_STREAM(args, ((writesds) ? *(uint32_t*)writesds : 0));
-    args = UINT32_TO_STREAM(args, ((exceptsds) ? *(uint32_t*)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
-    _event.simplelink_wait_event(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);
-    }
-}
-
-int32_t cc3000_socket::getsockopt (int32_t sd, int32_t level, int32_t optname, void *optval, socklen_t *optlen) {
-    uint8_t *ptr, *args;
-    tBsdGetSockOptReturnParams  tRetParams;
-
-    ptr = _simple_link.get_transmit_buffer();
-    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
-    _event.simplelink_wait_event(HCI_CMND_GETSOCKOPT, &tRetParams);
-
-    if (((int8_t)tRetParams.iStatus) >= 0)
-    {
-        *optlen = 4;
-        memcpy(optval, tRetParams.ucOptValue, 4);
-        return (0);
-    }
-    else
-    {
-        errno = tRetParams.iStatus;
-        return errno;
-    }
-}
-
-int32_t cc3000_socket::simple_link_recv(int32_t sd, void *buf, int32_t len, int32_t flags, sockaddr *from, socklen_t *fromlen, int32_t opcode) {
-    uint8_t *ptr, *args;
-    tBsdReadReturnParams tSocketReadEvent;
-
-    ptr = _simple_link.get_transmit_buffer();
-    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
-    _event.simplelink_wait_event(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....
-        _event.simplelink_wait_data((uint8_t *)buf, (uint8_t *)from, (uint8_t *)fromlen);
-    }
-
-    errno = tSocketReadEvent.iNumberOfBytes;
-
-    return(tSocketReadEvent.iNumberOfBytes);
-}
-
-int32_t cc3000_socket::recv(int32_t sd, void *buf, int32_t len, int32_t flags) {
-    return(simple_link_recv(sd, buf, len, flags, NULL, NULL, HCI_CMND_RECV));
-}
-
-int32_t cc3000_socket::recvfrom(int32_t sd, void *buf, int32_t len, int32_t flags, sockaddr *from, socklen_t *fromlen) {
-    return(simple_link_recv(sd, buf, len, flags, from, fromlen, HCI_CMND_RECVFROM));
-}
-
-int32_t cc3000_socket::simple_link_send(int32_t sd, const void *buf, int32_t len, int32_t flags, const sockaddr *to, int32_t tolen, int32_t opcode) {
-    uint8_t uArgSize = 0x00,  addrlen = 0x00;
-    uint8_t *ptr, *pDataPtr = NULL, *args;
-    uint32_t addr_offset = 0x00;
-    int32_t res;
-    tBsdReadReturnParams tSocketSendEvent;
-
-    // Check the bsd_arguments
-    if (0 != (res = HostFlowControlConsumeBuff(sd)))
-    {
-        return res;
-    }
-
-    //Update the number of sent packets
-    uint16_t sent_packets = _simple_link.get_sent_packets();
-    sent_packets++;
-    _simple_link.set_sent_packets(sent_packets);
-
-    // Allocate a buffer and construct a packet and send it over spi
-    ptr = _simple_link.get_transmit_buffer();
-    args = (ptr + HEADERS_SIZE_DATA);
-
-    // Update the offset of data and parameters according to the command
-    switch(opcode)
-    {
-    case HCI_CMND_SENDTO:
-        {
-            addr_offset = len + sizeof(len) + sizeof(len);
-            addrlen = 8;
-            uArgSize = SOCKET_SENDTO_PARAMS_LEN;
-            pDataPtr = ptr + HEADERS_SIZE_DATA + SOCKET_SENDTO_PARAMS_LEN;
-            break;
-        }
-
-    case HCI_CMND_SEND:
-        {
-            tolen = 0;
-            to = NULL;
-            uArgSize = HCI_CMND_SEND_ARG_LENGTH;
-            pDataPtr = ptr + HEADERS_SIZE_DATA + HCI_CMND_SEND_ARG_LENGTH;
-            break;
-        }
-
-    default:
-        {
-            break;
-        }
-    }
-
-    // Fill in temporary command buffer
-    args = UINT32_TO_STREAM(args, sd);
-    args = UINT32_TO_STREAM(args, uArgSize - sizeof(sd));
-    args = UINT32_TO_STREAM(args, len);
-    args = UINT32_TO_STREAM(args, flags);
-
-    if (opcode == HCI_CMND_SENDTO)
-    {
-        args = UINT32_TO_STREAM(args, addr_offset);
-        args = UINT32_TO_STREAM(args, addrlen);
-    }
-
-    // Copy the data received from user into the TX Buffer
-    ARRAY_TO_STREAM(pDataPtr, ((uint8_t *)buf), len);
-
-    // In case we are using SendTo, copy the to parameters
-    if (opcode == HCI_CMND_SENDTO)
-    {
-        ARRAY_TO_STREAM(pDataPtr, ((uint8_t *)to), tolen);
-    }
-
-    // Initiate a HCI command
-    _hci.data_send(opcode, ptr, uArgSize, len,(uint8_t*)to, tolen);
-    if (opcode == HCI_CMND_SENDTO)
-       _event.simplelink_wait_event(HCI_EVNT_SENDTO, &tSocketSendEvent);
-    else
-       _event.simplelink_wait_event(HCI_EVNT_SEND, &tSocketSendEvent);
-
-    return (len);
-}
-
-int32_t cc3000_socket::send(int32_t sd, const void *buf, int32_t len, int32_t flags) {
-    return(simple_link_send(sd, buf, len, flags, NULL, 0, HCI_CMND_SEND));
-}
-
-int32_t cc3000_socket::sendto(int32_t sd, const void *buf, int32_t len, int32_t flags, const sockaddr *to, socklen_t tolen) {
-    return(simple_link_send(sd, buf, len, flags, to, tolen, HCI_CMND_SENDTO));
-}
-
-int32_t cc3000_socket::mdns_advertiser(uint16_t mdns_enabled, uint8_t *device_service_name, uint16_t device_service_name_length) {
-    int32_t ret;
-     uint8_t *pTxBuffer, *pArgs;
-
-    if (device_service_name_length > MDNS_DEVICE_SERVICE_MAX_LENGTH)
-    {
-        return EFAIL;
-    }
-
-    pTxBuffer = _simple_link.get_transmit_buffer();
-    pArgs = (pTxBuffer + SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE);
-
-    // Fill in HCI packet structure
-    pArgs = UINT32_TO_STREAM(pArgs, mdns_enabled);
-    pArgs = UINT32_TO_STREAM(pArgs, 8);
-    pArgs = UINT32_TO_STREAM(pArgs, device_service_name_length);
-    ARRAY_TO_STREAM(pArgs, device_service_name, device_service_name_length);
-
-    // Initiate a HCI command
-    _hci.command_send(HCI_CMND_MDNS_ADVERTISE, pTxBuffer, SOCKET_MDNS_ADVERTISE_PARAMS_LEN + device_service_name_length);
-
-    // Since we are in blocking state - wait for event complete
-    _event.simplelink_wait_event(HCI_EVNT_MDNS_ADVERTISE, &ret);
-
-    return ret;
-}
-
-
-#ifndef CC3000_TINY_DRIVER
-int32_t cc3000_socket::gethostbyname(uint8_t *hostname, uint16_t name_length, uint32_t *out_ip_addr) {
-    tBsdGethostbynameParams ret;
-    uint8_t *ptr, *args;
-
-    errno = EFAIL;
-
-    if (name_length > HOSTNAME_MAX_LENGTH)
-    {
-        return errno;
-    }
-
-    ptr = _simple_link.get_transmit_buffer();
-    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, name_length);
-    ARRAY_TO_STREAM(args, hostname, name_length);
-
-    // Initiate a HCI command
-    _hci.command_send(HCI_CMND_GETHOSTNAME, ptr, SOCKET_GET_HOST_BY_NAME_PARAMS_LEN + name_length - 1);
-
-    // Since we are in blocking state - wait for event complete
-    _event.simplelink_wait_event(HCI_EVNT_BSD_GETHOSTBYNAME, &ret);
-
-    errno = ret.retVal;
-
-    (*((int32_t*)out_ip_addr)) = ret.outputAddress;
-
-    return (errno);
-}
-
-int32_t cc3000_socket::setsockopt(int32_t sd, int32_t level, int32_t optname, const void *optval, socklen_t optlen) {
-    int32_t ret;
-    uint8_t *ptr, *args;
-
-    ptr = _simple_link.get_transmit_buffer();
-    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, ((uint8_t *)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
-    _event.simplelink_wait_event(HCI_CMND_SETSOCKOPT, &ret);
-
-    if (ret >= 0)
-    {
-        return (0);
-    }
-    else
-    {
-        errno = ret;
-        return ret;
-    }
-}
-
-#endif
-
-} /* end of cc3000 namespace */
+/*****************************************************************************
+*
+*  C++ interface/implementation created by Martin Kojtal (0xc0170). Thanks to
+*  Jim Carver and Frank Vannieuwkerke for their inital cc3000 mbed port and
+*  provided help.
+*
+*  This version of "host driver" uses CC3000 Host Driver Implementation. Thus
+*  read the following copyright:
+*
+*  Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+*
+*  Redistribution and use in source and binary forms, with or without
+*  modification, are permitted provided that the following conditions
+*  are met:
+*
+*    Redistributions of source code must retain the above copyright
+*    notice, this list of conditions and the following disclaimer.
+*
+*    Redistributions in binary form must reproduce the above copyright
+*    notice, this list of conditions and the following disclaimer in the
+*    documentation and/or other materials provided with the
+*    distribution.
+*
+*    Neither the name of Texas Instruments Incorporated nor the names of
+*    its contributors may be used to endorse or promote products derived
+*    from this software without specific prior written permission.
+*
+*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+*  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+*  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+*  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+*  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+*  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+*  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+*  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+*  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+*****************************************************************************/
+#include "cc3000.h"
+#include "cc3000_socket.h"
+#include "cc3000_event.h" //TODO - remove this
+#include "cc3000_common.h"
+
+namespace mbed_cc3000 {
+
+cc3000_socket::cc3000_socket(cc3000_simple_link &simplelink, cc3000_hci &hci, cc3000_event &event)
+    : _simple_link(simplelink), _hci(hci), _event(event)
+{
+
+}
+
+cc3000_socket::~cc3000_socket()
+{
+
+}
+
+int32_t cc3000_socket::HostFlowControlConsumeBuff(int32_t sd) {
+#ifndef SEND_NON_BLOCKING
+    /* wait in busy loop */
+    do
+    {
+        // When the last transmission failed, return the last failure reason.
+        // Note that the buffer will not be allocated in this case
+        if (_simple_link.get_transmit_error() != 0)
+        {
+            errno = _simple_link.get_transmit_error();
+            _simple_link.set_transmit_error(0);
+            return errno;
+        }
+
+        if(SOCKET_STATUS_ACTIVE != _event.get_socket_active_status(sd))
+            return -1;
+    } while(0 == _simple_link.get_number_free_buffers());
+
+    uint16_t free_buffer = _simple_link.get_number_free_buffers();
+    free_buffer--;
+    _simple_link.set_number_free_buffers(free_buffer);
+
+    return 0;
+#else
+
+    // When the last transmission failed, return the last failure reason.
+    // Note that the buffer will not be allocated in this case
+    if (_simple_link.get_transmit_error() != 0)
+    {
+        errno = _simple_link.get_transmit_error();
+        _simple_link.set_transmit_error(0);
+        return errno;
+    }
+    if(SOCKET_STATUS_ACTIVE != _event.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 == _simple_link.get_number_free_buffers())
+    {
+        return -2;
+    }
+    else
+    {
+        uint16_t free_buffer = _simple_link.get_number_free_buffers();
+        free_buffer--;
+        _simple_link.set_number_free_buffers(free_buffer);
+        return 0;
+    }
+#endif
+}
+
+int32_t cc3000_socket::socket(int32_t domain, int32_t type, int32_t protocol) {
+    int32_t ret;
+    uint8_t *ptr, *args;
+
+    ret = EFAIL;
+    ptr = _simple_link.get_transmit_buffer();
+    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
+    _event.simplelink_wait_event(HCI_CMND_SOCKET, &ret);
+
+    // Process the event
+    errno = ret;
+
+    _event.set_socket_active_status(ret, SOCKET_STATUS_ACTIVE);
+
+    return(ret);
+}
+
+int32_t cc3000_socket::closesocket(int32_t sd) {
+    int32_t ret;
+    uint8_t *ptr, *args;
+
+    while(_simple_link.get_number_free_buffers() != SOCKET_MAX_FREE_BUFFERS);
+    ret = EFAIL;
+    ptr = _simple_link.get_transmit_buffer();
+    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
+    _event.simplelink_wait_event(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
+    _event.set_socket_active_status(sd, SOCKET_STATUS_INACTIVE);
+
+    return(ret);
+}
+
+int32_t cc3000_socket::accept(int32_t sd, sockaddr *addr, socklen_t *addrlen) {
+    int32_t ret;
+    uint8_t *ptr, *args;
+    tBsdReturnParams tAcceptReturnArguments;
+
+    ret = EFAIL;
+    ptr = _simple_link.get_transmit_buffer();
+    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
+    _event.simplelink_wait_event(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))
+    {
+        _event.set_socket_active_status(ret, SOCKET_STATUS_ACTIVE);
+    }
+    else
+    {
+        _event.set_socket_active_status(sd, SOCKET_STATUS_INACTIVE);
+    }
+
+    return(ret);
+}
+
+int32_t cc3000_socket::bind(int32_t sd, const sockaddr *addr, int32_t addrlen) {
+    int32_t ret;
+    uint8_t *ptr, *args;
+
+    ret = EFAIL;
+    ptr = _simple_link.get_transmit_buffer();
+    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, ((uint8_t *)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
+    _event.simplelink_wait_event(HCI_CMND_BIND, &ret);
+
+    errno = ret;
+
+    return(ret);
+}
+
+int32_t cc3000_socket::listen(int32_t sd, int32_t backlog) {
+    int32_t ret;
+    uint8_t *ptr, *args;
+
+    ret = EFAIL;
+    ptr = _simple_link.get_transmit_buffer();
+    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
+    _event.simplelink_wait_event(HCI_CMND_LISTEN, &ret);
+    errno = ret;
+
+    return(ret);
+}
+
+int32_t cc3000_socket::connect(int32_t sd, const sockaddr *addr, int32_t addrlen) {
+    int32_t ret;
+    uint8_t *ptr, *args;
+
+    ret = EFAIL;
+    ptr = _simple_link.get_transmit_buffer();
+    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, ((uint8_t *)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
+    _event.simplelink_wait_event(HCI_CMND_CONNECT, &ret);
+
+    errno = ret;
+
+    return((int32_t)ret);
+}
+
+int32_t cc3000_socket::select(int32_t nfds, fd_set *readsds, fd_set *writesds, fd_set *exceptsds, struct timeval *timeout) {
+    uint8_t *ptr, *args;
+    tBsdSelectRecvParams tParams;
+    uint32_t is_blocking;
+
+    if( timeout == NULL)
+    {
+        is_blocking = 1; /* blocking , infinity timeout */
+    }
+    else
+    {
+        is_blocking = 0; /* no blocking, timeout */
+    }
+
+    // Fill in HCI packet structure
+    ptr = _simple_link.get_transmit_buffer();
+    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) ? *(uint32_t*)readsds : 0));
+    args = UINT32_TO_STREAM(args, ((writesds) ? *(uint32_t*)writesds : 0));
+    args = UINT32_TO_STREAM(args, ((exceptsds) ? *(uint32_t*)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
+    _event.simplelink_wait_event(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);
+    }
+}
+
+int32_t cc3000_socket::getsockopt (int32_t sd, int32_t level, int32_t optname, void *optval, socklen_t *optlen) {
+    uint8_t *ptr, *args;
+    tBsdGetSockOptReturnParams  tRetParams;
+
+    ptr = _simple_link.get_transmit_buffer();
+    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
+    _event.simplelink_wait_event(HCI_CMND_GETSOCKOPT, &tRetParams);
+
+    if (((int8_t)tRetParams.iStatus) >= 0)
+    {
+        *optlen = 4;
+        memcpy(optval, tRetParams.ucOptValue, 4);
+        return (0);
+    }
+    else
+    {
+        errno = tRetParams.iStatus;
+        return errno;
+    }
+}
+
+int32_t cc3000_socket::simple_link_recv(int32_t sd, void *buf, int32_t len, int32_t flags, sockaddr *from, socklen_t *fromlen, int32_t opcode) {
+    uint8_t *ptr, *args;
+    tBsdReadReturnParams tSocketReadEvent;
+
+    ptr = _simple_link.get_transmit_buffer();
+    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
+    _event.simplelink_wait_event(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....
+        _event.simplelink_wait_data((uint8_t *)buf, (uint8_t *)from, (uint8_t *)fromlen);
+    }
+
+    errno = tSocketReadEvent.iNumberOfBytes;
+
+    return(tSocketReadEvent.iNumberOfBytes);
+}
+
+int32_t cc3000_socket::recv(int32_t sd, void *buf, int32_t len, int32_t flags) {
+    return(simple_link_recv(sd, buf, len, flags, NULL, NULL, HCI_CMND_RECV));
+}
+
+int32_t cc3000_socket::recvfrom(int32_t sd, void *buf, int32_t len, int32_t flags, sockaddr *from, socklen_t *fromlen) {
+    return(simple_link_recv(sd, buf, len, flags, from, fromlen, HCI_CMND_RECVFROM));
+}
+
+int32_t cc3000_socket::simple_link_send(int32_t sd, const void *buf, int32_t len, int32_t flags, const sockaddr *to, int32_t tolen, int32_t opcode) {
+    uint8_t uArgSize = 0x00,  addrlen = 0x00;
+    uint8_t *ptr, *pDataPtr = NULL, *args;
+    uint32_t addr_offset = 0x00;
+    int32_t res;
+    tBsdReadReturnParams tSocketSendEvent;
+
+    // Check the bsd_arguments
+    if (0 != (res = HostFlowControlConsumeBuff(sd)))
+    {
+        return res;
+    }
+
+    //Update the number of sent packets
+    uint16_t sent_packets = _simple_link.get_sent_packets();
+    sent_packets++;
+    _simple_link.set_sent_packets(sent_packets);
+
+    // Allocate a buffer and construct a packet and send it over spi
+    ptr = _simple_link.get_transmit_buffer();
+    args = (ptr + HEADERS_SIZE_DATA);
+
+    // Update the offset of data and parameters according to the command
+    switch(opcode)
+    {
+    case HCI_CMND_SENDTO:
+        {
+            addr_offset = len + sizeof(len) + sizeof(len);
+            addrlen = 8;
+            uArgSize = SOCKET_SENDTO_PARAMS_LEN;
+            pDataPtr = ptr + HEADERS_SIZE_DATA + SOCKET_SENDTO_PARAMS_LEN;
+            break;
+        }
+
+    case HCI_CMND_SEND:
+        {
+            tolen = 0;
+            to = NULL;
+            uArgSize = HCI_CMND_SEND_ARG_LENGTH;
+            pDataPtr = ptr + HEADERS_SIZE_DATA + HCI_CMND_SEND_ARG_LENGTH;
+            break;
+        }
+
+    default:
+        {
+            break;
+        }
+    }
+
+    // Fill in temporary command buffer
+    args = UINT32_TO_STREAM(args, sd);
+    args = UINT32_TO_STREAM(args, uArgSize - sizeof(sd));
+    args = UINT32_TO_STREAM(args, len);
+    args = UINT32_TO_STREAM(args, flags);
+
+    if (opcode == HCI_CMND_SENDTO)
+    {
+        args = UINT32_TO_STREAM(args, addr_offset);
+        args = UINT32_TO_STREAM(args, addrlen);
+    }
+
+    // Copy the data received from user into the TX Buffer
+    ARRAY_TO_STREAM(pDataPtr, ((uint8_t *)buf), len);
+
+    // In case we are using SendTo, copy the to parameters
+    if (opcode == HCI_CMND_SENDTO)
+    {
+        ARRAY_TO_STREAM(pDataPtr, ((uint8_t *)to), tolen);
+    }
+
+    // Initiate a HCI command
+    _hci.data_send(opcode, ptr, uArgSize, len,(uint8_t*)to, tolen);
+    if (opcode == HCI_CMND_SENDTO)
+       _event.simplelink_wait_event(HCI_EVNT_SENDTO, &tSocketSendEvent);
+    else
+       _event.simplelink_wait_event(HCI_EVNT_SEND, &tSocketSendEvent);
+
+    return (len);
+}
+
+int32_t cc3000_socket::send(int32_t sd, const void *buf, int32_t len, int32_t flags) {
+    return(simple_link_send(sd, buf, len, flags, NULL, 0, HCI_CMND_SEND));
+}
+
+int32_t cc3000_socket::sendto(int32_t sd, const void *buf, int32_t len, int32_t flags, const sockaddr *to, socklen_t tolen) {
+    return(simple_link_send(sd, buf, len, flags, to, tolen, HCI_CMND_SENDTO));
+}
+
+int32_t cc3000_socket::mdns_advertiser(uint16_t mdns_enabled, uint8_t *device_service_name, uint16_t device_service_name_length) {
+    int32_t ret;
+     uint8_t *pTxBuffer, *pArgs;
+
+    if (device_service_name_length > MDNS_DEVICE_SERVICE_MAX_LENGTH)
+    {
+        return EFAIL;
+    }
+
+    pTxBuffer = _simple_link.get_transmit_buffer();
+    pArgs = (pTxBuffer + SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE);
+
+    // Fill in HCI packet structure
+    pArgs = UINT32_TO_STREAM(pArgs, mdns_enabled);
+    pArgs = UINT32_TO_STREAM(pArgs, 8);
+    pArgs = UINT32_TO_STREAM(pArgs, device_service_name_length);
+    ARRAY_TO_STREAM(pArgs, device_service_name, device_service_name_length);
+
+    // Initiate a HCI command
+    _hci.command_send(HCI_CMND_MDNS_ADVERTISE, pTxBuffer, SOCKET_MDNS_ADVERTISE_PARAMS_LEN + device_service_name_length);
+
+    // Since we are in blocking state - wait for event complete
+    _event.simplelink_wait_event(HCI_EVNT_MDNS_ADVERTISE, &ret);
+
+    return ret;
+}
+
+
+#ifndef CC3000_TINY_DRIVER
+int32_t cc3000_socket::gethostbyname(uint8_t *hostname, uint16_t name_length, uint32_t *out_ip_addr) {
+    tBsdGethostbynameParams ret;
+    uint8_t *ptr, *args;
+
+    errno = EFAIL;
+
+    if (name_length > HOSTNAME_MAX_LENGTH)
+    {
+        return errno;
+    }
+
+    ptr = _simple_link.get_transmit_buffer();
+    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, name_length);
+    ARRAY_TO_STREAM(args, hostname, name_length);
+
+    // Initiate a HCI command
+    _hci.command_send(HCI_CMND_GETHOSTNAME, ptr, SOCKET_GET_HOST_BY_NAME_PARAMS_LEN + name_length - 1);
+
+    // Since we are in blocking state - wait for event complete
+    _event.simplelink_wait_event(HCI_EVNT_BSD_GETHOSTBYNAME, &ret);
+
+    errno = ret.retVal;
+
+    (*((int32_t*)out_ip_addr)) = ret.outputAddress;
+
+    return (errno);
+}
+
+int32_t cc3000_socket::setsockopt(int32_t sd, int32_t level, int32_t optname, const void *optval, socklen_t optlen) {
+    int32_t ret;
+    uint8_t *ptr, *args;
+
+    ptr = _simple_link.get_transmit_buffer();
+    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, ((uint8_t *)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
+    _event.simplelink_wait_event(HCI_CMND_SETSOCKOPT, &ret);
+
+    if (ret >= 0)
+    {
+        return (0);
+    }
+    else
+    {
+        errno = ret;
+        return ret;
+    }
+}
+
+#endif
+
+} /* end of cc3000 namespace */