diff --git a/drivers/wireless/cc3000/Make.defs b/drivers/wireless/cc3000/Make.defs index 9eea9e018c7..15a83e04c02 100644 --- a/drivers/wireless/cc3000/Make.defs +++ b/drivers/wireless/cc3000/Make.defs @@ -38,7 +38,7 @@ ifeq ($(CONFIG_WL_CC3000),y) # Include cc3000 drivers CSRCS += cc3000.c cc3000_common.c evnt_handler.c hci.c netapp.c nvmem.c -CSRCS += security.c socket.c spi.c wlan.c +CSRCS += security.c socket.c socket_imp.c spi.c wlan.c # Include wireless devices build support diff --git a/drivers/wireless/cc3000/cc3000.c b/drivers/wireless/cc3000/cc3000.c index 6d3d1dd2213..c74c9dcc1f5 100644 --- a/drivers/wireless/cc3000/cc3000.c +++ b/drivers/wireless/cc3000/cc3000.c @@ -74,6 +74,7 @@ #include #include #include +#include "cc3000_socket.h" #include "cc3000.h" @@ -90,6 +91,8 @@ #endif #define NUMBER_OF_MSGS 2 +#define FREE_SLOT -1 + /**************************************************************************** * Private Types ****************************************************************************/ @@ -444,6 +447,96 @@ static void cc3000_notify(FAR struct cc3000_dev_s *priv) #endif } +/**************************************************************************** + * Name: cc3000_worker + ****************************************************************************/ + +static void * select_thread_func(FAR void *arg) +{ + FAR struct cc3000_dev_s *priv = (FAR struct cc3000_dev_s *)arg; + struct timeval timeout; + TICC3000fd_set readsds; + int ret = 0; + int maxFD = 0; + int s = 0; + + memset(&timeout, 0, sizeof(struct timeval)); + timeout.tv_sec = 0; + timeout.tv_usec = (500 * 1000); /* 500 msecs */ + + while (1) + { + sem_wait(&priv->selectsem); + + /* Increase the count back by one to be decreased by the original caller */ + + sem_post(&priv->selectsem); + + CC3000_FD_ZERO(&readsds); + + /* Ping correct socket descriptor param for select */ + + for (s = 0; s < CONFIG_WL_MAX_SOCKETS; s++) + { + if (priv->sockets[s].sd != FREE_SLOT) + { + CC3000_FD_SET(priv->sockets[s].sd, &readsds); + if (maxFD <= priv->sockets[s].sd) + { + maxFD = priv->sockets[s].sd + 1; + } + } + } + + /* Polling instead of blocking here to process "accept" below */ + + ret = cc3000_select(maxFD, (fd_set *) &readsds, NULL, NULL, &timeout); + if (priv->selecttid == -1) + { + /* driver close will terminate the thread and by that all sync + * objects owned by it will be released + */ + + return OK; + } + + if (ret > 0) + { + for (s = 0; s < CONFIG_WL_MAX_SOCKETS; s++) + { + if (priv->sockets[s].sd != FREE_SLOT && /* Check that the socket is valid */ + priv->sockets[s].sd != priv->accepting_socket.acc.sd && /* Verify this is not an accept socket */ + C3000_FD_ISSET(priv->sockets[s].sd, &readsds)) /* and has pending data */ + { + sem_post(&priv->sockets[s].semwait); /* release the semaphore */ + } + } + } + + if (priv->accepting_socket.acc.sd != FREE_SLOT) /* if accept polling in needed */ + { + ret = cc3000_do_accept(priv->accepting_socket.acc.sd, + &priv->accepting_socket.addr, + &priv->accepting_socket.addrlen); + if (ret != CC3000_SOC_IN_PROGRESS) + { + priv->accepting_socket.acc.sd = FREE_SLOT; + priv->accepting_socket.acc.status = ret; + if (ret != CC3000_SOC_ERROR) + { + /* New Socket */ + + cc3000_add_socket(ret,priv->minor); + } + + sem_post(&priv->accepting_socket.acc.semwait); /* release the semaphore */ + } + } + } + + return OK; +} + /**************************************************************************** * Name: cc3000_worker ****************************************************************************/ @@ -549,7 +642,7 @@ static void * cc3000_worker(FAR void *arg) cc3000_devgive(priv); nllvdbg("Wait On Completion\n"); - sem_wait(&priv->wrkwaitsem); + sem_wait(priv->wrkwaitsem); nllvdbg("Completed S:%d irq :%d\n",priv->state,priv->config->irq_read(priv->config)); sem_getvalue(&priv->irqsem, &count); @@ -574,8 +667,10 @@ static void * cc3000_worker(FAR void *arg) } /* end switch */ } /* end if */ - cc3000_devgive(priv); - } /* while(1) */ + cc3000_devgive(priv); + } /* while(1) */ + + return OK; } /**************************************************************************** @@ -690,7 +785,8 @@ static int cc3000_open(FAR struct file *filep) param.sched_priority = SCHED_PRIORITY_MAX; pthread_attr_setschedparam(&tattr, ¶m); - ret = pthread_create(&priv->workertid, &tattr, cc3000_worker, (pthread_addr_t)priv); + ret = pthread_create(&priv->workertid, &tattr, cc3000_worker, + (pthread_addr_t)priv); if (ret < 0) { mq_close(priv->queue); @@ -699,6 +795,23 @@ static int cc3000_open(FAR struct file *filep) goto errout_with_sem; } + pthread_attr_init(&tattr); + param.sched_priority = SCHED_PRIORITY_DEFAULT+10; + pthread_attr_setschedparam(&tattr, ¶m); + ret = pthread_create(&priv->selecttid, &tattr, select_thread_func, + (pthread_addr_t)priv); + if (ret < 0) + { + pthread_t workertid = priv->workertid; + priv->workertid = -1; + pthread_cancel(workertid); + pthread_join(workertid,NULL); + mq_close(priv->queue); + priv->queue = 0; + ret = -errno; + goto errout_with_sem; + } + priv->state = eSPI_STATE_POWERUP; priv->config->irq_clear(priv->config); @@ -735,7 +848,7 @@ static int cc3000_close(FAR struct file *filep) inode = filep->f_inode; DEBUGASSERT(inode && inode->i_private); - priv = (FAR struct cc3000_dev_s *)inode->i_private; + priv = (FAR struct cc3000_dev_s *)inode->i_private; nllvdbg("crefs: %d\n", priv->crefs); @@ -760,13 +873,20 @@ static int cc3000_close(FAR struct file *filep) if (tmp == 1) { + pthread_t id = priv->selecttid; + priv->selecttid = -1; + pthread_cancel(id); + pthread_join(id, NULL); + priv->config->irq_enable(priv->config, false); priv->config->irq_clear(priv->config); priv->config->power_enable(priv->config, false); - pthread_t workertid = priv->workertid; + + id = priv->workertid; priv->workertid = -1; - pthread_cancel(workertid); - pthread_join(workertid,NULL); + pthread_cancel(id); + pthread_join(id, NULL); + mq_close(priv->queue); priv->queue = 0; } @@ -778,6 +898,7 @@ static int cc3000_close(FAR struct file *filep) /**************************************************************************** * Name: cc3000_read ****************************************************************************/ + static ssize_t cc3000_read(FAR struct file *filep, FAR char *buffer, size_t len) { FAR struct inode *inode; @@ -963,19 +1084,26 @@ static ssize_t cc3000_write(FAR struct file *filep, FAR const char *buffer, size tx_len += SPI_HEADER_SIZE; - /* The first write transaction to occur after release of the shutdown has slightly different timing than the others. - * The normal Master SPI write sequence is nCS low, followed by IRQ low (CC3000 host), indicating that - * the CC3000 core device is ready to accept data. However, after power up the sequence is slightly different, - * as shown in the following Figure: http://processors.wiki.ti.com/index.php/File:CC3000_Master_SPI_Write_Sequence_After_Power_Up.png - * The following is a sequence of operations: - * The master detects the IRQ line low: in this case the detection of - * IRQ low does not indicate the intention of the CC3000 device to communicate with the - * master but rather CC3000 readiness after power up. - * The master asserts nCS. - * The master introduces a delay of at least 50 μs before starting actual transmission of data. - * The master transmits the first 4 bytes of the SPI header. - * The master introduces a delay of at least an additional 50 μs. - * The master transmits the rest of the packet. + /* The first write transaction to occur after release of the shutdown has + * slightly different timing than the others. The normal Master SPI + * write sequence is nCS low, followed by IRQ low (CC3000 host), + * indicating that the CC3000 core device is ready to accept data. + * However, after power up the sequence is slightly different, as shown + * in the following Figure: + * + * http://processors.wiki.ti.com/index.php/File:CC3000_Master_SPI_Write_Sequence_After_Power_Up.png + * + * The following is a sequence of operations: + * - The master detects the IRQ line low: in this case the detection of + * IRQ low does not indicate the intention of the CC3000 device to + * communicate with the master but rather CC3000 readiness after power + * up. + * - The master asserts nCS. + * - The master introduces a delay of at least 50 μs before starting + * actual transmission of data. + * - The master transmits the first 4 bytes of the SPI header. + * - The master introduces a delay of at least an additional 50 μs. + * - The master transmits the rest of the packet. */ if (priv->state == eSPI_STATE_POWERUP) @@ -1044,7 +1172,7 @@ static int cc3000_ioctl(FAR struct file *filep, int cmd, unsigned long arg) inode = filep->f_inode; DEBUGASSERT(inode && inode->i_private); - priv = (FAR struct cc3000_dev_s *)inode->i_private; + priv = (FAR struct cc3000_dev_s *)inode->i_private; /* Get exclusive access to the driver data structure */ @@ -1061,14 +1189,7 @@ static int cc3000_ioctl(FAR struct file *filep, int cmd, unsigned long arg) ret = OK; switch (cmd) { - case CC3000IOC_COMPLETE: /* arg: Pointer to uint32_t frequency value */ - { - DEBUGASSERT(priv->config); - sem_post(&priv->wrkwaitsem); - } - break; - - case CC3000IOC_GETQUEID: + case CC3000IOC_GETQUESEMID: { FAR int *pid = (FAR int *)(arg); DEBUGASSERT(pid != NULL); @@ -1176,10 +1297,6 @@ errout: } #endif -/**************************************************************************** - * Public Functions - ****************************************************************************/ - /**************************************************************************** * Public Functions ****************************************************************************/ @@ -1207,7 +1324,11 @@ int cc3000_register(FAR struct spi_dev_s *spi, FAR struct cc3000_config_s *config, int minor) { FAR struct cc3000_dev_s *priv; - char devname[DEV_NAMELEN]; + char drvname[DEV_NAMELEN]; + char semname[SEM_NAMELEN]; +#ifdef CONFIG_CC3000_MT + int s; +#endif #ifdef CONFIG_CC3000_MULTIPLE irqstate_t flags; @@ -1245,7 +1366,20 @@ int cc3000_register(FAR struct spi_dev_s *spi, sem_init(&priv->waitsem, 0, 0); /* Initialize event wait semaphore */ sem_init(&priv->irqsem, 0, 0); /* Initialize IRQ Ready semaphore */ sem_init(&priv->readysem, 0, 0); /* Initialize Device Ready semaphore */ - sem_init(&priv->wrkwaitsem, 0, 0); /* Initialize Worker Wait semaphore */ + + (void)snprintf(semname, SEM_NAMELEN, SEM_FORMAT, minor); + priv->wrkwaitsem = sem_open(semname,O_CREAT,0,0); /* Initialize Worker Wait semaphore */ + +#ifdef CONFIG_CC3000_MT + pthread_mutex_init(&g_cc3000_mut, NULL); + priv->accepting_socket.acc.sd = FREE_SLOT; + sem_init(&priv->accepting_socket.acc.semwait, 0, 0); + for (s = 0; s < CONFIG_WL_MAX_SOCKETS; s++) + { + priv->sockets[s].sd = FREE_SLOT; + sem_init(&priv->sockets[s].semwait, 0, 0); + } +#endif /* Make sure that interrupts are disabled */ @@ -1263,10 +1397,10 @@ int cc3000_register(FAR struct spi_dev_s *spi, /* Register the device as an input device */ - (void)snprintf(devname, DEV_NAMELEN, DEV_FORMAT, minor); - nllvdbg("Registering %s\n", devname); + (void)snprintf(drvname, DEV_NAMELEN, DEV_FORMAT, minor); + nllvdbg("Registering %s\n", drvname); - ret = register_driver(devname, &cc3000_fops, 0666, priv); + ret = register_driver(drvname, &cc3000_fops, 0666, priv); if (ret < 0) { idbg("register_driver() failed: %d\n", ret); @@ -1290,8 +1424,220 @@ int cc3000_register(FAR struct spi_dev_s *spi, errout_with_priv: sem_destroy(&priv->devsem); + sem_destroy(&priv->waitsem); + sem_destroy(&priv->irqsem); + sem_destroy(&priv->readysem); + sem_close(priv->wrkwaitsem); + sem_unlink(semname); +#ifdef CONFIG_CC3000_MT + pthread_mutex_destroy(&g_cc3000_mut); + sem_destroy(&priv->accepting_socket.acc.semwait); + for (s = 0; s < CONFIG_WL_MAX_SOCKETS; s++) + { + sem_destroy(&priv->sockets[s].semwait); + } +#endif + #ifdef CONFIG_CC3000_MULTIPLE kfree(priv); #endif return ret; } + +/**************************************************************************** + * Name: cc3000_accept_socket + * + * Description: + * Adds this socket for monitoring for the accept operation + * + * Input Parameters: + * sd cc3000 socket handle or -1 tp remove it + * minor - The input device minor number + * + * Returned Value: + * Zero is returned on success. Otherwise, a -1 value is + * returned to indicate socket not found. + * + ****************************************************************************/ + +int cc3000_wait_data(int sockfd, int minor) +{ + FAR struct cc3000_dev_s *priv; + int s; + +#ifndef CONFIG_CC3000_MULTIPLE + priv = &g_cc3000; +#else + for (priv = g_cc3000list; + priv && priv->minor != minor; + priv = priv->flink); + + ASSERT(priv != NULL); +#endif + + for (s = 0; s < CONFIG_WL_MAX_SOCKETS; s++) + { + if (priv->sockets[s].sd == sockfd) + { + sem_post(&priv->selectsem); /* Wake select thread if need be */ + sem_wait(&priv->sockets[s].semwait); /* Wait caller on select to finish */ + sem_wait(&priv->selectsem); /* Sleep select thread */ + break; + } + } + + return (s >= CONFIG_WL_MAX_SOCKETS || priv->selecttid == -1) ? -1 : OK; +} + +/**************************************************************************** + * Name: cc3000_accept_socket + * + * Description: + * Adds this socket for monitoring for the accept operation + * + * Input Parameters: + * sd cc3000 socket handle or -1 tp remove it + * minor - The input device minor number + * + * Returned Value: + * Zero is returned on success. Otherwise, a -1 value is + * returned to indicate socket not found. + * + ****************************************************************************/ + +int cc3000_accept_socket(int sd, int minor, struct sockaddr *addr, + socklen_t *addrlen) +{ + FAR struct cc3000_dev_s *priv; + +#ifndef CONFIG_CC3000_MULTIPLE + priv = &g_cc3000; +#else + for (priv = g_cc3000list; + priv && priv->minor != minor; + priv = priv->flink); + + ASSERT(priv != NULL); +#endif + + priv->accepting_socket.acc.status = CC3000_SOC_ERROR; + priv->accepting_socket.acc.sd = sd; + sem_post(&priv->selectsem); /* Wake select thread if need be */ + sem_wait(&priv->accepting_socket.acc.semwait); /* Wait caller on select to finish */ + sem_wait(&priv->selectsem); /* Sleep select thread */ + if (priv->accepting_socket.acc.status != CC3000_SOC_ERROR) + { + *addr = priv->accepting_socket.addr; + *addrlen = priv->accepting_socket.addrlen; + } + + return priv->accepting_socket.acc.status; +} + +/**************************************************************************** + * Name: cc3000_add_socket + * + * Description: + * Adds a socket to the list for monitoring for long operation + * + * Input Parameters: + * sd cc3000 socket handle + * minor - The input device minor number + * + * Returned Value: + * Zero is returned on success. Otherwise, a -1 value is + * returned to indicate socket not found. + * + ****************************************************************************/ + +int cc3000_add_socket(int sd, int minor) +{ + FAR struct cc3000_dev_s *priv; + irqstate_t flags; + int s; + + if (sd < 0) + { + return sd; + } + +#ifndef CONFIG_CC3000_MULTIPLE + priv = &g_cc3000; +#else + for (priv = g_cc3000list; + priv && priv->minor != minor; + priv = priv->flink); + + ASSERT(priv != NULL); +#endif + + flags = irqsave(); + for (s = 0; s < CONFIG_WL_MAX_SOCKETS; s++) + { + if (priv->sockets[s].sd == FREE_SLOT) + { + priv->sockets[s].sd = sd; + break; + } + } + + irqrestore(flags); + return s >= CONFIG_WL_MAX_SOCKETS ? -1 : OK; +} + +/**************************************************************************** + * Name: cc3000_remove_socket + * + * Description: + * Removes a socket from the list of monitoring for long operation + * + * Input Parameters: + * sd cc3000 socket handle + * minor - The input device minor number + * + * Returned Value: + * Zero is returned on success. Otherwise, a -1 value is + * returned to indicate socket not found. + * + ****************************************************************************/ + +int cc3000_remove_socket(int sd, int minor) +{ + FAR struct cc3000_dev_s *priv; + irqstate_t flags; + int s; + + if (sd < 0) + { + return sd; + } + +#ifndef CONFIG_CC3000_MULTIPLE + priv = &g_cc3000; +#else + for (priv = g_cc3000list; + priv && priv->minor != minor; + priv = priv->flink); + + ASSERT(priv != NULL); +#endif + + flags = irqsave(); + if (priv->accepting_socket.acc.sd == sd) + { + priv->accepting_socket.acc.sd = FREE_SLOT; + priv->accepting_socket.addrlen = 0; + } + + for (s = 0; s < CONFIG_WL_MAX_SOCKETS; s++) + { + if (priv->sockets[s].sd == sd) + { + priv->sockets[s].sd = FREE_SLOT; + break; + } + } + + irqrestore(flags); + return s >= CONFIG_WL_MAX_SOCKETS ? -1 : OK; +} diff --git a/drivers/wireless/cc3000/cc3000.h b/drivers/wireless/cc3000/cc3000.h index f3f831efedb..3ec39107394 100644 --- a/drivers/wireless/cc3000/cc3000.h +++ b/drivers/wireless/cc3000/cc3000.h @@ -47,20 +47,29 @@ /**************************************************************************** * Included Files ****************************************************************************/ + #include #include #include +#include #include #include #include #include +#include #include "spi.h" /**************************************************************************** * Pre-Processor Definitions ****************************************************************************/ +#define CONFIG_CC3000_MT /* Indicate multi threaded version */ + +#ifdef CONFIG_CC3000_MT +# define CONFIG_WL_MAX_SOCKETS 5 +#endif + /* CC3000 Interfaces ********************************************************/ /* Driver support ***********************************************************/ @@ -82,8 +91,26 @@ * Public Types ****************************************************************************/ +#ifdef CONFIG_CC3000_MT +/* lock to serialze access to driver (spi protocol is window size 1) */ +extern pthread_mutex_t g_cc3000_mut; /* This structure describes the state of one CC3000 driver instance */ +typedef struct cc3000_socket_ent +{ + int sd; + long status; + sem_t semwait; +} cc3000_socket_ent; + +typedef struct cc3000_accept_ent +{ + cc3000_socket_ent acc; + struct sockaddr addr; + socklen_t addrlen; +} cc3000_accept_ent; +#endif + typedef enum { eSPI_STATE_POWERUP = 0, @@ -107,7 +134,7 @@ struct cc3000_dev_s uint8_t nwaiters; /* Number of threads waiting for CC3000 data */ uint8_t minor; /* minor */ sem_t devsem; /* Manages exclusive access to this structure */ - sem_t wrkwaitsem; /* Suspend and resume the delivery of messages */ + sem_t *wrkwaitsem; /* Suspend and resume the delivery of messages */ sem_t waitsem; /* Used to wait for the availability of data */ sem_t irqsem; /* Used to signal irq from cc3000 */ sem_t readysem; /* Used to wait for Ready Condition from the cc3000 */ @@ -122,6 +149,15 @@ struct cc3000_dev_s uint8_t tx_buffer[CC3000_TX_BUFFER_SIZE]; ssize_t tx_buffer_len; + /* The following is a list if socket structures of threads waiting + * long operations to finish; + */ +#ifdef CONFIG_CC3000_MT + pthread_t selecttid; /* Handle for the select thread */ + sem_t selectsem; /* Used to sleep the select thread */ + cc3000_socket_ent sockets[CONFIG_WL_MAX_SOCKETS]; + cc3000_accept_ent accepting_socket; +#endif /* The following is a list if poll structures of threads waiting for * driver events. The 'struct pollfd' reference for each open is also * retained in the f_priv field of the 'struct file'. @@ -143,6 +179,28 @@ extern "C" { #define EXTERN extern #endif +static inline void cc3000_lib_lock(void) +{ +#ifdef CONFIG_CC3000_MT + int status = pthread_mutex_lock(&g_cc3000_mut); + DEBUGASSERT(status == 0); +#endif +} + +static inline void cc3000_lib_unlock(void) +{ +#ifdef CONFIG_CC3000_MT + int status = pthread_mutex_unlock(&g_cc3000_mut); + DEBUGASSERT(status == 0); +#endif +} + +int cc3000_do_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); +int cc3000_wait_data(int sockfd, int minor); +int cc3000_accept_socket(int sd, int minor, struct sockaddr *addr, socklen_t *addrlen); +int cc3000_add_socket(int sd, int minor); +int cc3000_remove_socket(int sd, int minor); + #undef EXTERN #ifdef __cplusplus } diff --git a/drivers/wireless/cc3000/cc3000_common.c b/drivers/wireless/cc3000/cc3000_common.c index c65daa26833..b23ea46bb65 100644 --- a/drivers/wireless/cc3000/cc3000_common.c +++ b/drivers/wireless/cc3000/cc3000_common.c @@ -38,11 +38,6 @@ #include #include -#include -#include -#include -#include - /***************************************************************************** * Name:__error__ * diff --git a/drivers/wireless/cc3000/cc3000_socket.h b/drivers/wireless/cc3000/cc3000_socket.h new file mode 100644 index 00000000000..0e3f969b0ff --- /dev/null +++ b/drivers/wireless/cc3000/cc3000_socket.h @@ -0,0 +1,660 @@ +/***************************************************************************** + * drivers/wireless/cc3000_socket.h - CC3000 Host Driver Implementation. + * 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. + * + *****************************************************************************/ + +#ifndef __DRIVERS_WIRELESS_CC3000_SOCKET_H +#define __DRIVERS_WIRELESS_CC3000_SOCKET_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +/***************************************************************************** + * Pre-processor Definitions + *****************************************************************************/ + +#define CC3000_HOSTNAME_MAX_LENGTH (230) /* 230 bytes + header shouldn't exceed 8 + * bit value */ + +/*--------- Address Families --------*/ + +#define CC3000_AF_INET 2 +#define CC3000_AF_INET6 23 + + +/*------------ Socket Types ------------*/ + +#define CC3000_SOCK_STREAM 1 +#define CC3000_SOCK_DGRAM 2 +#define CC3000_SOCK_RAW 3 /* Raw sockets allow new IPv4 + * protocols to be implemented in + * user space. A raw socket receives + * or sends the raw datagram not + * including link level headers */ +#define CC3000_SOCK_RDM 4 +#define CC3000_SOCK_SEQPACKET 5 + +/*----------- Socket Protocol ----------*/ + +#define CC3000_IPPROTO_IP 0 /* Dummy for IP */ +#define CC3000_IPPROTO_ICMP 1 /* Control message protocol */ +#define CC3000_IPPROTO_IPV4 CC3000_IPPROTO_IP /* IP inside IP */ +#define CC3000_IPPROTO_TCP 6 /* TCP */ +#define CC3000_IPPROTO_UDP 17 /* User datagram protocol */ +#define CC3000_IPPROTO_IPV6 41 /* IPv6 in IPv6 */ +#define CC3000_IPPROTO_NONE 59 /* No next header */ +#define CC3000_IPPROTO_RAW 255 /* Raw IP packet */ +#define CC3000_IPPROTO_MAX 256 + +/*----------- Socket retunr codes -----------*/ + +#define CC3000_SOC_ERROR (-1) /* Error */ +#define CC3000_SOC_IN_PROGRESS (-2) /* Socket in progress */ + +/*----------- Socket Options -----------*/ +#define CC3000_SOL_SOCKET 0xffff /* Socket level */ +#define CC3000_SOCKOPT_RECV_NONBLOCK 0 /* recv non block mode, set SOCK_ON or + * SOCK_OFF (default block mode) */ +#define CC3000_SOCKOPT_RECV_TIMEOUT 1 /* optname to configure recv and recvfromtimeout */ +#define CC3000_SOCKOPT_ACCEPT_NONBLOCK 2 /* accept non block mode, set SOCK_ON or SOCK_OFF + * (default block mode) */ +#define CC3000_SOCK_ON 0 /* socket non-blocking mode is enabled */ +#define CC3000_SOCK_OFF 1 /* socket blocking mode is enabled */ + +#define CC3000_TCP_NODELAY 0x0001 +#define CC3000_TCP_BSDURGENT 0x7000 + +#define CC3000_MAX_PACKET_SIZE 1500 +#define CC3000_MAX_LISTEN_QUEUE 4 + +#define CC3000_IOCTL_SOCKET_EVENTMASK + +#define CC3000_FD_SETSIZE 32 + +#define CC3000_ASIC_ADDR_LEN 8 + +#define CC3000_NO_QUERY_RECIVED -3 + +/* It's easier to assume 8-bit bytes than to get CHAR_BIT. */ + +#define __NFDBITS (8 * sizeof (__fd_mask)) +#define __FDELT(d) ((d) / __NFDBITS) +#define __FDMASK(d) ((__fd_mask) 1 << ((d) % __NFDBITS)) + +#define __FDS_BITS(set) ((set)->fds_bits) + +/* We don't use `memset' because this would require a prototype and + * the array isn't too big. + */ + +#define __FD_ZERO(set) \ + do { \ + unsigned int __i; \ + TICC3000fd_set *__arr = (set); \ + for (__i = 0; __i < sizeof (TICC3000fd_set) / sizeof (__fd_mask); ++__i) \ + __FDS_BITS (__arr)[__i] = 0; \ + } while (0) +#define __FD_SET(d, set) (__FDS_BITS (set)[__FDELT (d)] |= __FDMASK (d)) +#define __FD_CLR(d, set) (__FDS_BITS (set)[__FDELT (d)] &= ~__FDMASK (d)) +#define __FD_ISSET(d, set) (__FDS_BITS (set)[__FDELT (d)] & __FDMASK (d)) + +/* Access macros for 'TICC3000fd_set' */ + +#define CC3000_FD_SET(fd, fdsetp) __FD_SET (fd, fdsetp) +#define CC3000_FD_CLR(fd, fdsetp) __FD_CLR (fd, fdsetp) +#define CC3000_FD_ISSET(fd, fdsetp) __FD_ISSET (fd, fdsetp) +#define CC3000_FD_ZERO(fdsetp) __FD_ZERO (fdsetp) + + +/* mDNS port - 5353 mDNS multicast address - 224.0.0.251 */ + +#define SET_mDNS_ADD(sockaddr) sockaddr.sa_data[0] = 0x14; \ + sockaddr.sa_data[1] = 0xe9; \ + sockaddr.sa_data[2] = 0xe0; \ + sockaddr.sa_data[3] = 0x0; \ + sockaddr.sa_data[4] = 0x0; \ + sockaddr.sa_data[5] = 0xfb; + +/***************************************************************************** + * Public Types + *****************************************************************************/ + +/* The fd_set member is required to be an array of longs. */ + +typedef long int __fd_mask; + +/* fd_set for select and pselect. */ + +typedef struct +{ + __fd_mask fds_bits[CC3000_FD_SETSIZE / __NFDBITS]; +} TICC3000fd_set; + +/***************************************************************************** + * Public Data + *****************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +/***************************************************************************** + * Public Function Prototypes + *****************************************************************************/ + +/***************************************************************************** + * Name: cc3000_socket_impl + * + * Decription: + * 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. + * + * Input Parameters: + * domain selects the protocol family which will be used for + * communication. On this version only AF_INET is supported + * type specifies the communication semantics. On this version + * only SOCK_STREAM, SOCK_DGRAM, SOCK_RAW are supported + * protocol specifies a particular protocol to be used with the + * socket IPPROTO_TCP, IPPROTO_UDP or IPPROTO_RAW are + * supported. + * + * Returned Value: + * On success, socket handle that is used for consequent socket + * operations. On error, -1 is returned. + * + *****************************************************************************/ + +int cc3000_socket_impl(long domain, long type, long protocol); + +/***************************************************************************** + * Name: cc3000_closesocket_impl + * + * Decription: + * The socket function closes a created socket. + * + * Input Parameters: + * sd socket handle. + * + * Returned Value: + * On success, zero is returned. On error, -1 is returned. + * + *****************************************************************************/ + +long cc3000_closesocket_impl(long sd); + +/***************************************************************************** + * Name: cc3000_accept_impl + * + * Decription: + * 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. + * + * Input Parameters: + * sd socket descriptor (handle) + * 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. + * addrlen The addrlen argument is a value-result argument: + * it should initially contain the size of the structure + * pointed to by addr. + * + * Returned Value: + * 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) + * + *****************************************************************************/ + +long cc3000_accept_impl(long sd, struct sockaddr *addr, socklen_t *addrlen); + +/***************************************************************************** + * Name: cc3000_bind_impl + * + * Decription: + * 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. + * + * Input Parameters: + * sd socket descriptor (handle) + * addr specifies the destination address. On this version + * only AF_INET is supported. + * addrlen contains the size of the structure pointed to by addr. + * + * Returned Value: + * On success, zero is returned. On error, -1 is returned. + * + *****************************************************************************/ + +long cc3000_bind_impl(long sd, FAR const struct sockaddr *addr, socklen_t addrlen); + +/***************************************************************************** + * Name: cc3000_listen_impl + * + * Decription: + * 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. + * + * NOTE: On this version, backlog is not supported + * + * Input Parameters: + * sd socket descriptor (handle) + * backlog specifies the listen queue depth. On this version + * backlog is not supported. + * + * Returned Value: + * On success, zero is returned. On error, -1 is returned. + * + *****************************************************************************/ + +long cc3000_listen_impl(long sd, long backlog); + +/***************************************************************************** + * Name: cc3000_connect_impl + * + * Decription: + * 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. + * + * Input Parameters: + * sd socket descriptor (handle) + * addr specifies the destination addr. On this version + * only AF_INET is supported. + * addrlen contains the size of the structure pointed to by addr + * + * Returned Value: + * On success, zero is returned. On error, -1 is returned + * + *****************************************************************************/ + +long cc3000_connect_impl(long sd, FAR const struct sockaddr *addr, socklen_t addrlen); + +/***************************************************************************** + * Name: cc3000_select_impl + * + * Decription: + * 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 + * + * Input Parameters: + * nfds the highest-numbered file descriptor in any of the + * three sets, plus 1. + * readfds socket descriptors list for read monitoring + * writefds socket descriptors list for write monitoring + * exceptfds socket descriptors list for exception monitoring + * 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. + * + * Returned Value: + * 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. + * *readfds - return the sockets on which Read request will + * return without delay with valid data. + * *writefds - return the sockets on which Write request + * will return without delay. + * *exceptfds - return the sockets which closed recently. + * + *****************************************************************************/ + +int cc3000_select_impl(long nfds, TICC3000fd_set *readfds, TICC3000fd_set *writefds,TICC3000fd_set *exceptfds, + struct timeval *timeout); + +int cc3000_select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout); + + +#ifndef CC3000_TINY_DRIVER +/***************************************************************************** + * Name: cc3000_setsockopt_impl + * + * Decription: + * 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). + * + * Input Parameters: + * sd socket handle + * level defines the protocol level for this option + * optname defines the option name to Interrogate + * optval specifies a value for the option + * optlen specifies the length of the option value + * + * Returned Value: + * On success, zero is returned. On error, -1 is returned + * + *****************************************************************************/ + +int cc3000_setsockopt_impl(long sd, long level, long optname, const void *optval, socklen_t optlen); +#endif + +/***************************************************************************** + * Name: cc3000_getsockopt_impl + * + * Decription: + * 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). + * + * Input Parameters: + * sd socket handle + * level defines the protocol level for this option + * optname defines the option name to Interrogate + * optval specifies a value for the option + * optlen specifies the length of the option value + * + * Returned Value: + * On success, zero is returned. On error, -1 is returned + * + *****************************************************************************/ + +int cc3000_getsockopt_impl(long sd, long level, long optname, void *optval, socklen_t *optlen); + + +/***************************************************************************** + * Name: cc3000_recv_impl + * + * Decription: + * function receives a message from a connection-mode socket + * + * NOTE: On this version, only blocking mode is supported. + * + * Input Parameters: + * sd socket handle + * buf Points to the buffer where the message should be stored + * len Specifies the length in bytes of the buffer pointed to + * by the buffer argument. + * flags Specifies the type of message reception. + * On this version, this parameter is not supported. + * + * Returned Value: + * Return the number of bytes received, or -1 if an error + * occurred + * + *****************************************************************************/ + +int cc3000_recv_impl(long sd, void *buf, long len, long flags); + +/***************************************************************************** + * Name: cc3000_recvfrom_impl + * + * Decription: + * read data from socket + * function receives a message from a connection-mode or + * connectionless-mode socket. Note that raw sockets are not + * supported. + * + * NOTE: On this version, only blocking mode is supported. + * + * Input Parameters: + * sd socket handle + * buf Points to the buffer where the message should be stored + * len Specifies the length in bytes of the buffer pointed to + * by the buffer argument. + * flags Specifies the type of message reception. + * On this version, this parameter is not supported. + * from pointer to an address structure indicating the source + * address: sockaddr. On this version only AF_INET is + * supported. + * fromlen source address tructure size + * + * Returned Value: + * Return the number of bytes received, or -1 if an error + * occurred + * + *****************************************************************************/ + +int cc3000_recvfrom_impl(long sd, void *buf, long len, long flags, + struct sockaddr *from, socklen_t *fromlen); + +/***************************************************************************** + * Name: cc3000_send_impl + * + * Decription: + * Write data to TCP socket + * This function is used to transmit a message to another + * socket. + * + * NOTE: On this version, only blocking mode is supported. + * + * Input Parameters: + * sd socket handle + * buf Points to a buffer containing the message to be sent + * len message size in bytes + * flags On this version, this parameter is not supported + * + * Returned Value: + * Return the number of bytes transmitted, or -1 if an + * error occurred + * + *****************************************************************************/ + +int cc3000_send_impl(long sd, const void *buf, long len, long flags); + +/***************************************************************************** + * Name: cc3000_sendto_impl + * + * Decription: + * Write data to TCP socket + * This function is used to transmit a message to another + * socket. + * + * NOTE: On this version, only blocking mode is supported. + * + * Input Parameters: + * sd socket handle + * buf Points to a buffer containing the message to be sent + * len message size in bytes + * flags On this version, this parameter is not supported + * to pointer to an address structure indicating the destination + * address: sockaddr. On this version only AF_INET is + * supported. + * tolen destination address structure size + * + * Returned Value: + * Return the number of bytes transmitted, or -1 if an + * error occurred + * + *****************************************************************************/ + +int cc3000_sendto_impl(long sd, FAR const void *buf, long len, long flags, + FAR const struct sockaddr *to, socklen_t tolen); + +#ifndef CC3000_TINY_DRIVER +/***************************************************************************** + * Name: cc3000_gethostbyname_impl + * + * Decription: + * 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. + * + * Input Parameters: + * hostname host name + * usNameLen name length + * 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. + * + * Returned Value: + * On success, positive is returned. On error, negative is returned + * + *****************************************************************************/ + +//struct hostent *gethostbyname(const char *name); +int cc3000_gethostbyname_impl(char * hostname, uint16_t usNameLen, unsigned long* out_ip_addr); +#endif + +/***************************************************************************** + * Name: cc3000_mdnsAdvertiser_impl + * + * Decription: + * Set CC3000 in mDNS advertiser mode in order to advertise itself. + * + * Input Parameters: + * mdnsEnabled flag to enable/disable the mDNS feature + * deviceServiceName Service name as part of the published + * canonical domain name + * deviceServiceNameLength Length of the service name + * + * Returned Value: + * On success, zero is returned, return SOC_ERROR if socket was not + * opened successfully, or if an error occurred. + * + *****************************************************************************/ + +int cc3000_mdnsadvertiser_impl(uint16_t mdnsEnabled, char * deviceServiceName, + uint16_t deviceServiceNameLength); + +#ifdef __cplusplus +} +#endif // __cplusplus + +#endif // __DRIVERS_WIRELESS_CC3000_SOCKET_H diff --git a/drivers/wireless/cc3000/evnt_handler.c b/drivers/wireless/cc3000/evnt_handler.c index f97541e3d22..952d6e3956e 100644 --- a/drivers/wireless/cc3000/evnt_handler.c +++ b/drivers/wireless/cc3000/evnt_handler.c @@ -37,6 +37,7 @@ ******************************************************************************/ #include + #include #include #include @@ -46,7 +47,7 @@ #include #include #include -#include +#include "cc3000_socket.h" #include #include "spi.h" @@ -344,7 +345,7 @@ uint8_t *hci_event_handler(void *pRetParams, uint8_t *from, uint8_t *fromlen) memcpy((uint8_t *)pRetParams, pucReceivedParams + ACCEPT_ADDRESS__OFFSET, - sizeof(sockaddr)); + sizeof(struct sockaddr)); } break; @@ -910,21 +911,22 @@ void SimpleLinkWaitEvent(uint16_t usOpcode, void *pRetParams) do { + nllvdbg("SpiWait\n"); tSLInformation.pucReceivedData = SpiWait(); tSLInformation.usEventOrDataReceived = 1; STREAM_TO_UINT16((char *)tSLInformation.pucReceivedData, HCI_EVENT_OPCODE_OFFSET,event_type); if (*tSLInformation.pucReceivedData == HCI_TYPE_EVNT) { - nllvdbg("Evtn:0x%x\n",event_type); - } + nllvdbg("Evtn:0x%x\n",event_type); + } if (event_type != usOpcode) { - if (hci_unsolicited_event_handler() == 1) - { - nllvdbg("Processed Event 0x%x want 0x%x\n",event_type, usOpcode); - } + if (hci_unsolicited_event_handler() == 1) + { + nllvdbg("Processed Event 0x%x want 0x%x\n",event_type, usOpcode); + } } else { diff --git a/drivers/wireless/cc3000/hci.c b/drivers/wireless/cc3000/hci.c index 37daf054406..22aa34e542a 100644 --- a/drivers/wireless/cc3000/hci.c +++ b/drivers/wireless/cc3000/hci.c @@ -36,7 +36,11 @@ * Included Files ******************************************************************************/ +#include + +#include #include + #include #include #include "spi.h" @@ -74,6 +78,7 @@ uint16_t hci_command_send(uint16_t usOpcode, uint8_t *pucBuff, uint8_t ucArgsLen stream = (pucBuff + SPI_HEADER_SIZE); + nllvdbg("Send 0x%x\n",usOpcode); UINT8_TO_STREAM(stream, HCI_TYPE_CMND); stream = UINT16_TO_STREAM(stream, usOpcode); UINT8_TO_STREAM(stream, ucArgsLength); @@ -81,6 +86,7 @@ uint16_t hci_command_send(uint16_t usOpcode, uint8_t *pucBuff, uint8_t ucArgsLen /* Update the opcode of the event we will be waiting for */ SpiWrite(pucBuff, ucArgsLength + SIMPLE_LINK_HCI_CMND_HEADER_SIZE); + nllvdbg("Send of 0x%x Completed\n",usOpcode); return 0; } diff --git a/drivers/wireless/cc3000/netapp.c b/drivers/wireless/cc3000/netapp.c index 02b4ffa2d9e..aa83d30cb14 100644 --- a/drivers/wireless/cc3000/netapp.c +++ b/drivers/wireless/cc3000/netapp.c @@ -37,12 +37,15 @@ ******************************************************************************/ #include + #include #include -#include #include #include +#include "cc3000.h" +#include "cc3000_socket.h" + /****************************************************************************** * Pre-processor Definitions ******************************************************************************/ @@ -118,6 +121,8 @@ long netapp_dhcp(unsigned long *aucIP, unsigned long *aucSubnetMask, uint8_t *ptr; uint8_t *args; + cc3000_lib_lock(); + scRet = EFAIL; ptr = tSLInformation.pucTxCommandBuffer; args = (ptr + HEADERS_SIZE_CMD); @@ -138,6 +143,8 @@ long netapp_dhcp(unsigned long *aucIP, unsigned long *aucSubnetMask, SimpleLinkWaitEvent(HCI_NETAPP_DHCP, &scRet); + cc3000_lib_unlock(); + return(scRet); } @@ -200,6 +207,8 @@ long netapp_timeout_values(unsigned long *aucDHCP, unsigned long *aucARP, uint8_t *ptr; uint8_t *args; + cc3000_lib_lock(); + scRet = EFAIL; ptr = tSLInformation.pucTxCommandBuffer; args = (ptr + HEADERS_SIZE_CMD); @@ -226,11 +235,12 @@ long netapp_timeout_values(unsigned long *aucDHCP, unsigned long *aucARP, SimpleLinkWaitEvent(HCI_NETAPP_SET_TIMERS, &scRet); + cc3000_lib_unlock(); + return scRet; } #endif - /****************************************************************************** * Name: netapp_ping_send * @@ -262,6 +272,8 @@ long netapp_ping_send(unsigned long *ip, unsigned long ulPingAttempts, int8_t scRet; uint8_t *ptr, *args; + cc3000_lib_lock(); + scRet = EFAIL; ptr = tSLInformation.pucTxCommandBuffer; args = (ptr + HEADERS_SIZE_CMD); @@ -281,6 +293,8 @@ long netapp_ping_send(unsigned long *ip, unsigned long ulPingAttempts, SimpleLinkWaitEvent(HCI_NETAPP_PING_SEND, &scRet); + cc3000_lib_unlock(); + return scRet; } #endif @@ -319,6 +333,8 @@ void netapp_ping_report(void) ptr = tSLInformation.pucTxCommandBuffer; int8_t scRet; + cc3000_lib_lock(); + scRet = EFAIL; /* Initiate a HCI command */ @@ -328,6 +344,8 @@ void netapp_ping_report(void) /* Wait for command complete event */ SimpleLinkWaitEvent(HCI_NETAPP_PING_REPORT, &scRet); + + cc3000_lib_unlock(); } #endif @@ -351,6 +369,8 @@ long netapp_ping_stop(void) int8_t scRet; uint8_t *ptr; + cc3000_lib_lock(); + scRet = EFAIL; ptr = tSLInformation.pucTxCommandBuffer; @@ -362,6 +382,8 @@ long netapp_ping_stop(void) SimpleLinkWaitEvent(HCI_NETAPP_PING_STOP, &scRet); + cc3000_lib_unlock(); + return(scRet); } #endif @@ -401,6 +423,8 @@ void netapp_ipconfig(tNetappIpconfigRetArgs * ipconfig) { uint8_t *ptr; + cc3000_lib_lock(); + ptr = tSLInformation.pucTxCommandBuffer; /* Initiate a HCI command */ @@ -410,6 +434,8 @@ void netapp_ipconfig(tNetappIpconfigRetArgs * ipconfig) /* Wait for command complete event */ SimpleLinkWaitEvent(HCI_NETAPP_IPCONFIG, ipconfig); + + cc3000_lib_unlock(); } #else void netapp_ipconfig(tNetappIpconfigRetArgs * ipconfig) @@ -437,6 +463,9 @@ long netapp_arp_flush(void) int8_t scRet; uint8_t *ptr; + + cc3000_lib_lock(); + scRet = EFAIL; ptr = tSLInformation.pucTxCommandBuffer; @@ -448,6 +477,8 @@ long netapp_arp_flush(void) SimpleLinkWaitEvent(HCI_NETAPP_ARP_FLUSH, &scRet); + cc3000_lib_unlock(); + return scRet; } #endif @@ -484,6 +515,8 @@ long netapp_set_debug_level(unsigned long ulLevel) int8_t scRet; uint8_t *ptr, *args; + cc3000_lib_lock(); + scRet = EFAIL; ptr = tSLInformation.pucTxCommandBuffer; args = (ptr + HEADERS_SIZE_CMD); @@ -500,6 +533,8 @@ long netapp_set_debug_level(unsigned long ulLevel) SimpleLinkWaitEvent(HCI_NETAPP_SET_DEBUG_LEVEL, &scRet); + cc3000_lib_unlock(); + return scRet; } #endif diff --git a/drivers/wireless/cc3000/nvmem.c b/drivers/wireless/cc3000/nvmem.c index c1aff53c4e4..c45f4394614 100644 --- a/drivers/wireless/cc3000/nvmem.c +++ b/drivers/wireless/cc3000/nvmem.c @@ -41,8 +41,8 @@ #include #include -#include #include +#include "cc3000.h" /****************************************************************************** * Pre-processor Definitions @@ -88,6 +88,8 @@ signed long nvmem_read(unsigned long ulFileId, unsigned long ulLength, uint8_t *ptr; uint8_t *args; + cc3000_lib_lock(); + ptr = tSLInformation.pucTxCommandBuffer; args = (ptr + HEADERS_SIZE_CMD); @@ -113,6 +115,8 @@ signed long nvmem_read(unsigned long ulFileId, unsigned long ulLength, SimpleLinkWaitData(buff, 0, 0); + cc3000_lib_unlock(); + return ucStatus; } @@ -146,6 +150,8 @@ signed long nvmem_write(unsigned long ulFileId, unsigned long ulLength, uint8_t *ptr; uint8_t *args; + cc3000_lib_lock(); + iRes = EFAIL; ptr = tSLInformation.pucTxCommandBuffer; @@ -168,6 +174,8 @@ signed long nvmem_write(unsigned long ulFileId, unsigned long ulLength, SimpleLinkWaitEvent(HCI_EVNT_NVMEM_WRITE, &iRes); + cc3000_lib_unlock(); + return iRes; } @@ -285,6 +293,8 @@ uint8_t nvmem_read_sp_version(uint8_t *patchVer) /* 1st byte is the status and the rest is the SP version */ uint8_t retBuf[5]; + cc3000_lib_lock(); + ptr = tSLInformation.pucTxCommandBuffer; /* Initiate a HCI command, no args are required */ @@ -300,6 +310,8 @@ uint8_t nvmem_read_sp_version(uint8_t *patchVer) *(patchVer+1) = retBuf[4]; + cc3000_lib_unlock(); + return retBuf[0]; } #endif @@ -332,6 +344,8 @@ signed long nvmem_create_entry(unsigned long ulFileId, unsigned long ulNewLen) uint8_t *args; uint16_t retval; + cc3000_lib_lock(); + ptr = tSLInformation.pucTxCommandBuffer; args = (ptr + HEADERS_SIZE_CMD); @@ -346,5 +360,7 @@ signed long nvmem_create_entry(unsigned long ulFileId, unsigned long ulNewLen) SimpleLinkWaitEvent(HCI_CMND_NVMEM_CREATE_ENTRY, &retval); + cc3000_lib_unlock(); + return retval; } diff --git a/drivers/wireless/cc3000/socket.c b/drivers/wireless/cc3000/socket.c index ce2fcdd5e35..2bf9969f89d 100644 --- a/drivers/wireless/cc3000/socket.c +++ b/drivers/wireless/cc3000/socket.c @@ -36,158 +36,64 @@ * Included Files *****************************************************************************/ +#include +#include + #include #include #include +#include #include #include -#include +#include + #include -#include -#include + +#include "cc3000_socket.h" +#include "cc3000.h" /***************************************************************************** * Pre-processor Definitions *****************************************************************************/ -/* Enable this flag if and only if you must comply with BSD socket close() - * function - */ - -#ifdef _API_USE_BSD_CLOSE -# define close(sd) closesocket(sd) +#ifndef ARRAY_SIZE +# define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) #endif -/* Enable this flag if and only if you must comply with BSD socket read() and - * write() functions - */ +/**************************************************************************** + * Private Types + ****************************************************************************/ -#ifdef _API_USE_BSD_READ_WRITE -# define read(sd, buf, len, flags) recv(sd, buf, len, flags) -# define write(sd, buf, len, flags) send(sd, buf, len, flags) -#endif +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ -#define SOCKET_OPEN_PARAMS_LEN (12) -#define SOCKET_CLOSE_PARAMS_LEN (4) -#define SOCKET_ACCEPT_PARAMS_LEN (4) -#define SOCKET_BIND_PARAMS_LEN (20) -#define SOCKET_LISTEN_PARAMS_LEN (8) -#define SOCKET_GET_HOST_BY_NAME_PARAMS_LEN (9) -#define SOCKET_CONNECT_PARAMS_LEN (20) -#define SOCKET_SELECT_PARAMS_LEN (44) -#define SOCKET_SET_SOCK_OPT_PARAMS_LEN (20) -#define SOCKET_GET_SOCK_OPT_PARAMS_LEN (12) -#define SOCKET_RECV_FROM_PARAMS_LEN (12) -#define SOCKET_SENDTO_PARAMS_LEN (24) -#define SOCKET_MDNS_ADVERTISE_PARAMS_LEN (12) +/**************************************************************************** + * Public Data + ****************************************************************************/ -/* The legnth of arguments for the SEND command: sd + buff_offset + len + flags, - * while size of each parameter is 32 bit - so the total length is 16 bytes; - */ +pthread_mutex_t g_cc3000_mut; -#define HCI_CMND_SEND_ARG_LENGTH (16) +/**************************************************************************** + * Private Data + ****************************************************************************/ -#define SELECT_TIMEOUT_MIN_MICRO_SECONDS 5000 - -#define HEADERS_SIZE_DATA (SPI_HEADER_SIZE + 5) - -#define SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE \ - (SPI_HEADER_SIZE + SIMPLE_LINK_HCI_CMND_HEADER_SIZE) - -#define MDNS_DEVICE_SERVICE_MAX_LENGTH (32) - -/***************************************************************************** - * Public Functions - *****************************************************************************/ -/***************************************************************************** - * Name: HostFlowControlConsumeBuff - * - * Input Parameters: - * sd socket descriptor - * - * Returned Value: - * 0 in case there are buffers available, - * -1 in case of bad socket - * -2 if there are no free buffers present (only when - * SEND_NON_BLOCKING is enabled) - * - * Decription: - * if SEND_NON_BLOCKING not define - block until have free buffer - * becomes available, else return immediately with correct status - * regarding the buffers available. - * - *****************************************************************************/ - -int HostFlowControlConsumeBuff(int sd) +static const int bsd2ti_types[] = { -#ifndef SEND_NON_BLOCKING - /* Wait in busy loop */ + CC3000_SOCK_STREAM, /* SOCK_STREAM */ + CC3000_SOCK_DGRAM, /* SOCK_DGRAM */ + CC3000_SOCK_SEQPACKET, /* SOCK_SEQPACKET */ + CC3000_SOCK_RAW, /* SOCK_RAW */ + CC3000_SOCK_RDM /* SOCK_RDM */ +}; - 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 - */ +/**************************************************************************** + * Private Functions + ****************************************************************************/ - if (tSLInformation.slTransmitDataError != 0) - { - errno = tSLInformation.slTransmitDataError; - tSLInformation.slTransmitDataError = 0; - return errno; - } - - if (SOCKET_STATUS_ACTIVE != get_socket_active_status(sd)) - { - return -1; - } - - /* We must yield here for the the Event to get processed that returns - * the buffers - */ - - usleep(100000); - } - 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 -} +/**************************************************************************** + * Public Functions + ****************************************************************************/ /***************************************************************************** * Name: socket @@ -212,36 +118,54 @@ int HostFlowControlConsumeBuff(int sd) * *****************************************************************************/ -int socket(long domain, long type, long protocol) +int cc3000_socket(int domain, int type, int protocol) { - long ret; - uint8_t *ptr, *args; + int sd; - ret = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); + if (type < SOCK_STREAM || type >= ARRAY_SIZE(bsd2ti_types)) + { + errno = EPROTOTYPE; + return -1; + } - /* Fill in HCI packet structure */ + switch(domain) + { + case AF_INET: + domain = CC3000_AF_INET; + break; + case AF_INET6: + domain = CC3000_AF_INET6; + break; + default: + errno = EAFNOSUPPORT; + return -1; + } - args = UINT32_TO_STREAM(args, domain); - args = UINT32_TO_STREAM(args, type); - args = UINT32_TO_STREAM(args, protocol); + switch(protocol) + { + case CC3000_IPPROTO_IP: + case CC3000_IPPROTO_ICMP: + case CC3000_IPPROTO_TCP: + case CC3000_IPPROTO_UDP: + case CC3000_IPPROTO_IPV6: + case CC3000_IPPROTO_NONE: + case CC3000_IPPROTO_RAW: + case CC3000_IPPROTO_MAX: + break; - /* Initiate a HCI command */ + default: + errno = EPROTONOSUPPORT; + return -1; + } - 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; + cc3000_lib_lock(); + type = bsd2ti_types[type]; + sd = cc3000_socket_impl(domain,type,protocol); +#ifdef CONFIG_CC3000_MT + cc3000_add_socket(sd, 0); +#endif + cc3000_lib_unlock(); + return sd; } /***************************************************************************** @@ -251,47 +175,27 @@ int socket(long domain, long type, long protocol) * The socket function closes a created socket. * * Input Parameters: - * sd socket handle. + * sockfd socket handle. * * Returned Value: * On success, zero is returned. On error, -1 is returned. * *****************************************************************************/ -long closesocket(long sd) +int cc3000_closesocket(int sockfd) { - long ret; - uint8_t *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); - + int ret; + cc3000_lib_lock(); + ret = cc3000_closesocket_impl(sockfd); +#ifdef CONFIG_CC3000_MT + cc3000_remove_socket(sockfd, 0); +#endif + cc3000_lib_unlock(); return ret; } /***************************************************************************** - * Name: accept + * Name: accept, cc3000_do_accept * * Decription: * accept a connection on a socket: @@ -313,7 +217,7 @@ long closesocket(long sd) * length (in bytes) of the address returned. * * Input Parameters: - * sd socket descriptor (handle) + * sockfd socket descriptor (handle) * 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. @@ -335,51 +239,47 @@ long closesocket(long sd) * *****************************************************************************/ -long accept(long sd, sockaddr *addr, socklen_t *addrlen) +int cc3000_do_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) { - long ret; - uint8_t *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); - } - + int ret; + cc3000_lib_lock(); + ret = cc3000_accept_impl(sockfd, addr, addrlen); + cc3000_lib_unlock(); return ret; } +int cc3000_accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) +#ifdef CONFIG_CC3000_MT +{ + short non_blocking=CC3000_SOCK_ON; + if (setsockopt(sockfd, CC3000_SOL_SOCKET, CC3000_SOCKOPT_ACCEPT_NONBLOCK, + &non_blocking, sizeof(non_blocking)) < 0) + { + ndbg("setsockopt failure %d\n", errno); + return -errno; + } + + memset(addr,0,*addrlen); + return cc3000_accept_socket(sockfd,0,addr,addrlen); +} +#else +{ + int ret = OK; + + cc3000_accept_socket(sockfd,0); + short nonBlocking=CC3000_SOCK_OFF; + + if (setsockopt(sockfd, CC3000_SOL_SOCKET, CC3000_SOCKOPT_ACCEPT_NONBLOCK, + &nonBlocking, sizeof(nonBlocking)) < 0) + { + ndbg("setsockopt failure %d\n", errno); + return -errno; + } + + return cc3000_do_accept(int sockfd, addr, addrlen);; +} +#endif + /***************************************************************************** * Name: bind * @@ -393,7 +293,7 @@ long accept(long sd, sockaddr *addr, socklen_t *addrlen) * socket may receive connections. * * Input Parameters: - * sd socket descriptor (handle) + * sockfd socket descriptor (handle) * addr specifies the destination address. On this version * only AF_INET is supported. * addrlen contains the size of the structure pointed to by addr. @@ -403,35 +303,13 @@ long accept(long sd, sockaddr *addr, socklen_t *addrlen) * *****************************************************************************/ -long bind(long sd, const sockaddr *addr, long addrlen) +int cc3000_bind(int sockfd, FAR const struct sockaddr *addr, socklen_t addrlen) { - long ret; - uint8_t *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, ((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 */ - - SimpleLinkWaitEvent(HCI_CMND_BIND, &ret); - - errno = ret; + int ret = OK; + cc3000_lib_lock(); + ret = cc3000_bind_impl(sockfd, addr, addrlen); + cc3000_lib_unlock(); return ret; } @@ -450,7 +328,7 @@ long bind(long sd, const sockaddr *addr, long addrlen) * NOTE: On this version, backlog is not supported * * Input Parameters: - * sd socket descriptor (handle) + * sockfd socket descriptor (handle) * backlog specifies the listen queue depth. On this version * backlog is not supported. * @@ -459,30 +337,382 @@ long bind(long sd, const sockaddr *addr, long addrlen) * *****************************************************************************/ -long listen(long sd, long backlog) +int cc3000_listen(int sockfd, int backlog) { - long ret; - uint8_t *ptr, *args; + int ret = OK; - ret = EFAIL; - ptr = tSLInformation.pucTxCommandBuffer; - args = (ptr + HEADERS_SIZE_CMD); + cc3000_lib_lock(); + ret = cc3000_listen_impl(sockfd,backlog); + cc3000_lib_unlock(); + return ret; +} - /* Fill in temporary command buffer */ +/***************************************************************************** + * Name: connect + * + * Decription: + * 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. + * + * Input Parameters: + * sockfd socket descriptor (handle) + * addr specifies the destination addr. On this version + * only AF_INET is supported. + * addrlen contains the size of the structure pointed to by addr + * + * Returned Value: + * On success, zero is returned. On error, -1 is returned + * + *****************************************************************************/ - args = UINT32_TO_STREAM(args, sd); - args = UINT32_TO_STREAM(args, backlog); +int cc3000_connect(int sockfd, FAR const struct sockaddr *addr, socklen_t addrlen) +{ + int ret = OK; - /* Initiate a HCI command */ + cc3000_lib_lock(); + ret = cc3000_connect_impl(sockfd, addr, addrlen); + cc3000_lib_unlock(); + return ret; +} - hci_command_send(HCI_CMND_LISTEN, - ptr, SOCKET_LISTEN_PARAMS_LEN); +/***************************************************************************** + * Name: select + * + * Decription: + * 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 + * + * Input Parameters: + * nfds the highest-numbered file descriptor in any of the + * three sets, plus 1. + * readfds socket descriptors list for read monitoring + * writefds socket descriptors list for write monitoring + * exceptfds socket descriptors list for exception monitoring + * 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. + * + * Returned Value: + * 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. + * *readfds - return the sockets on which Read request will + * return without delay with valid data. + * *writefds - return the sockets on which Write request + * will return without delay. + * *exceptfds - return the sockets which closed recently. + * + *****************************************************************************/ - /* Since we are in blocking state - wait for event complete */ +int cc3000_select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, + struct timeval *timeout) +{ + int ret = OK; - SimpleLinkWaitEvent(HCI_CMND_LISTEN, &ret); - errno = ret; + cc3000_lib_lock(); + ret = cc3000_select_impl(nfds, (TICC3000fd_set *)readfds, + (TICC3000fd_set *)writefds, + (TICC3000fd_set *)exceptfds, timeout); + cc3000_lib_unlock(); + return ret; +} +#ifndef CC3000_TINY_DRIVER +/***************************************************************************** + * Name: setsockopt + * + * Decription: + * 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 value and value_len are used to access value - + * use for setsockopt(). For getsockopt() they identify a buffer + * in which the value for the requested option(s) are to + * be returned. For getsockopt(), value_len 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 (option) + * SOCKOPT_RECV_TIMEOUT configures recv and recvfrom timeout + * in milliseconds. In that case value should be pointer to + * unsigned long. + * 2. SOCKOPT_NONBLOCK (option). sets the socket non-blocking mode on + * or off. In that case value should be SOCK_ON or SOCK_OFF (value). + * + * Input Parameters: + * sockfd socket handle + * level defines the protocol level for this option + * option defines the option name to Interrogate + * value specifies a value for the option + * value_len specifies the length of the option value + * + * Returned Value: + * On success, zero is returned. On error, -1 is returned + * + *****************************************************************************/ + +int cc3000_setsockopt(int sockfd, int level, int option, + FAR const void *value, socklen_t value_len) +{ + int ret = OK; + + cc3000_lib_lock(); + ret = cc3000_setsockopt_impl(sockfd, level, option, value, value_len); + cc3000_lib_unlock(); + return ret; +} +#endif + +/***************************************************************************** + * Name: getsockopt + * + * Decription: + * 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 value and value_len are used to access value - + * use for setsockopt(). For getsockopt() they identify a buffer + * in which the value for the requested option(s) are to + * be returned. For getsockopt(), value_len 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 (option) + * SOCKOPT_RECV_TIMEOUT configures recv and recvfrom timeout + * in milliseconds. + * In that case value should be pointer to unsigned long. + * 2. SOCKOPT_NONBLOCK (option). sets the socket non-blocking mode on + * or off. + * In that case value should be SOCK_ON or SOCK_OFF (value). + * + * Input Parameters: + * sockfd socket handle + * level defines the protocol level for this option + * option defines the option name to Interrogate + * value specifies a value for the option + * value_len specifies the length of the option value + * + * Returned Value: + * On success, zero is returned. On error, -1 is returned + * + *****************************************************************************/ + +int cc3000_getsockopt(int sockfd, int level, int option, FAR void *value, + FAR socklen_t *value_len) +{ + int ret = OK; + + cc3000_lib_lock(); + ret = cc3000_getsockopt_impl(sockfd, level, option, value, value_len); + cc3000_lib_unlock(); + return ret; +} + +/***************************************************************************** + * Name: recv + * + * Decription: + * function receives a message from a connection-mode socket + * + * NOTE: On this version, only blocking mode is supported. + * + * Input Parameters: + * sockfd socket handle + * buf Points to the buffer where the message should be stored + * len Specifies the length in bytes of the buffer pointed to + * by the buffer argument. + * flags Specifies the type of message reception. + * On this version, this parameter is not supported. + * + * Returned Value: + * Return the number of bytes received, or -1 if an error + * occurred + * + *****************************************************************************/ + +ssize_t cc3000_recv(int sockfd, FAR void *buf, size_t len, int flags) +{ + ssize_t ret = OK; + +#ifdef CONFIG_CC3000_MT + ret = cc3000_wait_data(sockfd, 0); + if (ret != OK ) + { + return -1; + } +#endif + + cc3000_lib_lock(); + ret = cc3000_recv_impl(sockfd, buf, len, flags); + cc3000_lib_unlock(); + return ret; +} + +/***************************************************************************** + * Name: recvfrom + * + * Decription: + * read data from socket + * function receives a message from a connection-mode or + * connectionless-mode socket. Note that raw sockets are not + * supported. + * + * NOTE: On this version, only blocking mode is supported. + * + * Input Parameters: + * sockfd socket handle + * buf Points to the buffer where the message should be stored + * len Specifies the length in bytes of the buffer pointed to + * by the buffer argument. + * flags Specifies the type of message reception. + * On this version, this parameter is not supported. + * from pointer to an address structure indicating the source + * address: sockaddr. On this version only AF_INET is + * supported. + * fromlen source address tructure size + * + * Returned Value: + * Return the number of bytes received, or -1 if an error + * occurred + * + *****************************************************************************/ + +ssize_t cc3000_recvfrom(int sockfd, FAR void *buf, size_t len, int flags, + FAR struct sockaddr *from, FAR socklen_t *fromlen) +{ + ssize_t ret = OK; + +#ifdef CONFIG_CC3000_MT + ret = cc3000_wait_data(sockfd, 0); + if (ret != OK ) + { + return -1; + } +#endif + + cc3000_lib_lock(); + ret = cc3000_recvfrom_impl(sockfd, buf, len, flags, from, fromlen); + cc3000_lib_unlock(); + return ret; +} + +/***************************************************************************** + * Name: send + * + * Decription: + * Write data to TCP socket + * This function is used to transmit a message to another + * socket. + * + * NOTE: On this version, only blocking mode is supported. + * + * Input Parameters: + * sockfd socket handle + * buf Points to a buffer containing the message to be sent + * len message size in bytes + * flags On this version, this parameter is not supported + * + * Returned Value: + * Return the number of bytes transmitted, or -1 if an + * error occurred + * + *****************************************************************************/ + +ssize_t cc3000_send(int sockfd, FAR const void *buf, size_t len, int flags) +{ + ssize_t ret = OK; + + cc3000_lib_lock(); + ret = cc3000_send_impl(sockfd, buf, len, flags); + cc3000_lib_unlock(); + return ret; +} + +/***************************************************************************** + * Name: sendto + * + * Decription: + * Write data to TCP socket + * This function is used to transmit a message to another + * socket. + * + * NOTE: On this version, only blocking mode is supported. + * + * Input Parameters: + * sockfd socket handle + * buf Points to a buffer containing the message to be sent + * len message size in bytes + * flags On this version, this parameter is not supported + * to pointer to an address structure indicating the destination + * address: sockaddr. On this version only AF_INET is + * supported. + * tolen destination address structure size + * + * Returned Value: + * Return the number of bytes transmitted, or -1 if an + * error occurred + * + *****************************************************************************/ + +ssize_t cc3000_sendto(int sockfd, FAR const void *buf, size_t len, int flags, + FAR const struct sockaddr *to, socklen_t tolen) +{ + ssize_t ret = OK; + + cc3000_lib_lock(); + ret = cc3000_sendto_impl(sockfd, buf, len, flags, to, tolen); + cc3000_lib_unlock(); return ret; } @@ -510,697 +740,18 @@ long listen(long sd, long backlog) *****************************************************************************/ #ifndef CC3000_TINY_DRIVER -int gethostbyname(char * hostname, uint16_t usNameLen, unsigned long* out_ip_addr) +// TODO: Standard is struct hostent *gethostbyname(const char *name); +int cc3000_gethostbyname(char * hostname, uint16_t usNameLen, unsigned long* out_ip_addr) { - tBsdGethostbynameParams ret; - uint8_t *ptr, *args; + int ret = OK; - 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; + cc3000_lib_lock(); + ret = cc3000_gethostbyname_impl(hostname, usNameLen, out_ip_addr); + cc3000_lib_unlock(); + return ret; } #endif -/***************************************************************************** - * Name: connect - * - * Decription: - * 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. - * - * Input Parameters: - * sd socket descriptor (handle) - * addr specifies the destination addr. On this version - * only AF_INET is supported. - * addrlen contains the size of the structure pointed to by addr - * - * Returned Value: - * On success, zero is returned. On error, -1 is returned - * - *****************************************************************************/ - -long connect(long sd, const sockaddr *addr, long addrlen) -{ - long int ret; - uint8_t *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, ((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 */ - - SimpleLinkWaitEvent(HCI_CMND_CONNECT, &ret); - - errno = ret; - - return (long)ret; -} - -/***************************************************************************** - * Name: select - * - * Decription: - * 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 - * - * Input Parameters: - * nfds the highest-numbered file descriptor in any of the - * three sets, plus 1. - * writesds socket descriptors list for write monitoring - * readsds socket descriptors list for read monitoring - * exceptsds socket descriptors list for exception monitoring - * 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. - * - * Returned Value: - * 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. - * - *****************************************************************************/ - -int select(long nfds, TICC3000fd_set *readsds, TICC3000fd_set *writesds, - TICC3000fd_set *exceptsds, struct timeval *timeout) -{ - uint8_t *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; - } -} - -/***************************************************************************** - * Name: setsockopt - * - * Decription: - * 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). - * - * Input Parameters: - * sd socket handle - * level defines the protocol level for this option - * optname defines the option name to Interrogate - * optval specifies a value for the option - * optlen specifies the length of the option value - * - * Returned Value: - * On success, zero is returned. On error, -1 is returned - * - *****************************************************************************/ - -#ifndef CC3000_TINY_DRIVER -int setsockopt(long sd, long level, long optname, const void *optval, socklen_t optlen) -{ - int ret; - uint8_t *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, ((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 */ - - SimpleLinkWaitEvent(HCI_CMND_SETSOCKOPT, &ret); - - if (ret >= 0) - { - return 0; - } - else - { - errno = ret; - return ret; - } -} -#endif - -/***************************************************************************** - * Name: getsockopt - * - * Decription: - * 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). - * - * Input Parameters: - * sd socket handle - * level defines the protocol level for this option - * optname defines the option name to Interrogate - * optval specifies a value for the option - * optlen specifies the length of the option value - * - * Returned Value: - * On success, zero is returned. On error, -1 is returned - * - *****************************************************************************/ - -int getsockopt (long sd, long level, long optname, void *optval, socklen_t *optlen) -{ - uint8_t *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 (((int8_t)tRetParams.iStatus) >= 0) - { - *optlen = 4; - memcpy(optval, tRetParams.ucOptValue, 4); - return 0; - } - else - { - errno = tRetParams.iStatus; - return errno; - } -} - -/***************************************************************************** - * Name: simple_link_recv - * - * Input Parameters: - * sd socket handle - * buf read buffer - * len buffer length - * flags indicates blocking or non-blocking operation - * from pointer to an address structure indicating source address - * fromlen source address structure size - * - * Returned Value: - * Return the number of bytes received, or -1 if an error - * occurred - * - * Decription: - * 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 - * - *****************************************************************************/ - -int simple_link_recv(long sd, void *buf, long len, long flags, sockaddr *from, - socklen_t *fromlen, long opcode) -{ - uint8_t *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((uint8_t *)buf, (uint8_t *)from, (uint8_t *)fromlen); - } - - errno = tSocketReadEvent.iNumberOfBytes; - - return tSocketReadEvent.iNumberOfBytes; -} - -/***************************************************************************** - * Name: recv - * - * Decription: - * function receives a message from a connection-mode socket - * - * NOTE: On this version, only blocking mode is supported. - * - * Input Parameters: - * sd socket handle - * buf Points to the buffer where the message should be stored - * len Specifies the length in bytes of the buffer pointed to - * by the buffer argument. - * flags Specifies the type of message reception. - * On this version, this parameter is not supported. - * - * Returned Value: - * Return the number of bytes received, or -1 if an error - * occurred - * - *****************************************************************************/ - -int recv(long sd, void *buf, long len, long flags) -{ - return(simple_link_recv(sd, buf, len, flags, NULL, NULL, HCI_CMND_RECV)); -} - -/***************************************************************************** - * Name: recvfrom - * - * Decription: - * read data from socket - * function receives a message from a connection-mode or - * connectionless-mode socket. Note that raw sockets are not - * supported. - * - * NOTE: On this version, only blocking mode is supported. - * - * Input Parameters: - * sd socket handle - * buf Points to the buffer where the message should be stored - * len Specifies the length in bytes of the buffer pointed to - * by the buffer argument. - * flags Specifies the type of message reception. - * On this version, this parameter is not supported. - * from pointer to an address structure indicating the source - * address: sockaddr. On this version only AF_INET is - * supported. - * fromlen source address tructure size - * - * Returned Value: - * Return the number of bytes received, or -1 if an error - * occurred - * - *****************************************************************************/ - -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)); -} - -/***************************************************************************** - * Name: simple_link_send - * - * Input Parameters: - * sd socket handle - * buf write buffer - * len buffer length - * flags On this version, this parameter is not supported - * to pointer to an address structure indicating destination - * address - * tolen destination address structure size - * - * Returned Value: - * Return the number of bytes transmitted, or -1 if an error - * occurred, or -2 in case there are no free buffers available - * (only when SEND_NON_BLOCKING is enabled) - * - * Decription: - * This function is used to transmit a message to another - * socket - * - *****************************************************************************/ - -int simple_link_send(long sd, const void *buf, long len, long flags, - const sockaddr *to, long tolen, long opcode) -{ - tBsdReadReturnParams tSocketSendEvent; - uint8_t uArgSize = 0, addrlen; - uint8_t *ptr, *pDataPtr = NULL, *args; - unsigned long addr_offset = 0; - int res; - - /* Check the bsd_arguments */ - - if (0 != (res = HostFlowControlConsumeBuff(sd))) - { - return res; - } - - /* Update the number of sent packets */ - - tSLInformation.NumberOfSentPackets++; - - /* Allocate a buffer and construct a packet and send it over spi */ - - ptr = tSLInformation.pucTxCommandBuffer; - 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) - { - SimpleLinkWaitEvent(HCI_EVNT_SENDTO, &tSocketSendEvent); - } - else - { - SimpleLinkWaitEvent(HCI_EVNT_SEND, &tSocketSendEvent); - } - - return len; -} - -/***************************************************************************** - * Name: send - * - * Decription: - * Write data to TCP socket - * This function is used to transmit a message to another - * socket. - * - * NOTE: On this version, only blocking mode is supported. - * - * Input Parameters: - * sd socket handle - * buf Points to a buffer containing the message to be sent - * len message size in bytes - * flags On this version, this parameter is not supported - * - * Returned Value: - * Return the number of bytes transmitted, or -1 if an - * error occurred - * - *****************************************************************************/ - -int send(long sd, const void *buf, long len, long flags) -{ - return(simple_link_send(sd, buf, len, flags, NULL, 0, HCI_CMND_SEND)); -} - -/***************************************************************************** - * Name: sendto - * - * Decription: - * Write data to TCP socket - * This function is used to transmit a message to another - * socket. - * - * NOTE: On this version, only blocking mode is supported. - * - * Input Parameters: - * sd socket handle - * buf Points to a buffer containing the message to be sent - * len message size in bytes - * flags On this version, this parameter is not supported - * to pointer to an address structure indicating the destination - * address: sockaddr. On this version only AF_INET is - * supported. - * tolen destination address structure size - * - * Returned Value: - * Return the number of bytes transmitted, or -1 if an - * error occurred - * - *****************************************************************************/ - -int sendto(long sd, const void *buf, long len, long flags, const sockaddr *to, - socklen_t tolen) -{ - return(simple_link_send(sd, buf, len, flags, to, tolen, HCI_CMND_SENDTO)); -} - /***************************************************************************** * Name: mdnsAdvertiser * @@ -1219,35 +770,14 @@ int sendto(long sd, const void *buf, long len, long flags, const sockaddr *to, * *****************************************************************************/ -int mdnsAdvertiser(uint16_t mdnsEnabled, char * deviceServiceName, - uint16_t deviceServiceNameLength) +int cc3000_mdnsadvertiser(uint16_t mdnsEnabled, char *deviceServiceName, + uint16_t deviceServiceNameLength) + { - uint8_t *pTxBuffer; - uint8_t *pArgs; - int ret; - - if (deviceServiceNameLength > MDNS_DEVICE_SERVICE_MAX_LENGTH) - { - return EFAIL; - } - - pTxBuffer = tSLInformation.pucTxCommandBuffer; - pArgs = (pTxBuffer + SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE); - - /* Fill in HCI packet structure */ - - pArgs = UINT32_TO_STREAM(pArgs, mdnsEnabled); - pArgs = UINT32_TO_STREAM(pArgs, 8); - pArgs = UINT32_TO_STREAM(pArgs, deviceServiceNameLength); - ARRAY_TO_STREAM(pArgs, deviceServiceName, deviceServiceNameLength); - - /* Initiate a HCI command */ - - hci_command_send(HCI_CMND_MDNS_ADVERTISE, pTxBuffer, SOCKET_MDNS_ADVERTISE_PARAMS_LEN + deviceServiceNameLength); - - /* Since we are in blocking state - wait for event complete */ - - SimpleLinkWaitEvent(HCI_EVNT_MDNS_ADVERTISE, &ret); + int ret = OK; + cc3000_lib_lock(); + ret = cc3000_mdnsadvertiser_impl(mdnsEnabled, deviceServiceName, deviceServiceNameLength); + cc3000_lib_unlock(); return ret; } diff --git a/drivers/wireless/cc3000/socket_imp.c b/drivers/wireless/cc3000/socket_imp.c new file mode 100644 index 00000000000..262135b656b --- /dev/null +++ b/drivers/wireless/cc3000/socket_imp.c @@ -0,0 +1,1256 @@ +/**************************************************************************** + * drivers/wireless/socket_imp.c - CC3000 Host Driver Implementation. + * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ + * + * Port to nuttx: + * David Sidrane + * + * 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. + * + *****************************************************************************/ + +/***************************************************************************** + * Included Files + *****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include "cc3000_socket.h" +#include +#include + +/***************************************************************************** + * Pre-processor Definitions + *****************************************************************************/ + +/* Enable this flag if and only if you must comply with BSD socket close() + * function + */ + +#ifdef _API_USE_BSD_CLOSE +# define close(sd) closesocket(sd) +#endif + +/* Enable this flag if and only if you must comply with BSD socket read() and + * write() functions + */ + +#ifdef _API_USE_BSD_READ_WRITE +# define read(sd, buf, len, flags) recv(sd, buf, len, flags) +# define write(sd, buf, len, flags) send(sd, buf, len, flags) +#endif + +#define SOCKET_OPEN_PARAMS_LEN (12) +#define SOCKET_CLOSE_PARAMS_LEN (4) +#define SOCKET_ACCEPT_PARAMS_LEN (4) +#define SOCKET_BIND_PARAMS_LEN (20) +#define SOCKET_LISTEN_PARAMS_LEN (8) +#define SOCKET_GET_HOST_BY_NAME_PARAMS_LEN (9) +#define SOCKET_CONNECT_PARAMS_LEN (20) +#define SOCKET_SELECT_PARAMS_LEN (44) +#define SOCKET_SET_SOCK_OPT_PARAMS_LEN (20) +#define SOCKET_GET_SOCK_OPT_PARAMS_LEN (12) +#define SOCKET_RECV_FROM_PARAMS_LEN (12) +#define SOCKET_SENDTO_PARAMS_LEN (24) +#define SOCKET_MDNS_ADVERTISE_PARAMS_LEN (12) + +/* The legnth of arguments for the SEND command: sd + buff_offset + len + flags, + * while size of each parameter is 32 bit - so the total length is 16 bytes; + */ + +#define HCI_CMND_SEND_ARG_LENGTH (16) + +#define SELECT_TIMEOUT_MIN_MICRO_SECONDS 5000 + +#define HEADERS_SIZE_DATA (SPI_HEADER_SIZE + 5) + +#define SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE \ + (SPI_HEADER_SIZE + SIMPLE_LINK_HCI_CMND_HEADER_SIZE) + +#define MDNS_DEVICE_SERVICE_MAX_LENGTH (32) + +/***************************************************************************** + * Public Functions + *****************************************************************************/ +/***************************************************************************** + * Name: HostFlowControlConsumeBuff + * + * Input Parameters: + * sd socket descriptor + * + * Returned Value: + * 0 in case there are buffers available, + * -1 in case of bad socket + * -2 if there are no free buffers present (only when + * SEND_NON_BLOCKING is enabled) + * + * Decription: + * if SEND_NON_BLOCKING not define - block until have free buffer + * becomes available, else return immediately with correct status + * regarding the buffers available. + * + *****************************************************************************/ + +int HostFlowControlConsumeBuff(int sd) +{ +#ifndef SEND_NON_BLOCKING + /* 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; + } + + /* We must yield here for the the Event to get processed that returns + * the buffers + */ + + usleep(100000); + } + 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 +} + +/***************************************************************************** + * Name: socket + * + * Decription: + * 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. + * + * Input Parameters: + * domain selects the protocol family which will be used for + * communication. On this version only AF_INET is supported + * type specifies the communication semantics. On this version + * only SOCK_STREAM, SOCK_DGRAM, SOCK_RAW are supported + * protocol specifies a particular protocol to be used with the + * socket IPPROTO_TCP, IPPROTO_UDP or IPPROTO_RAW are + * supported. + * + * Returned Value: + * On success, socket handle that is used for consequent socket + * operations. On error, -1 is returned. + * + *****************************************************************************/ + +int cc3000_socket_impl(long domain, long type, long protocol) +{ + long ret; + uint8_t *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; +} + +/***************************************************************************** + * Name: closesocket + * + * Decription: + * The socket function closes a created socket. + * + * Input Parameters: + * sd socket handle. + * + * Returned Value: + * On success, zero is returned. On error, -1 is returned. + * + *****************************************************************************/ + +long cc3000_closesocket_impl(long sd) +{ + long ret; + uint8_t *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; +} + +/***************************************************************************** + * Name: accept + * + * Decription: + * 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. + * + * Input Parameters: + * sd socket descriptor (handle) + * 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. + * addrlen The addrlen argument is a value-result argument: + * it should initially contain the size of the structure + * pointed to by addr. + * + * Returned Value: + * 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) + * + *****************************************************************************/ + +long cc3000_accept_impl(long sd, struct sockaddr *addr, socklen_t *addrlen) +{ + long ret; + uint8_t *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, CC3000_ASIC_ADDR_LEN); + *addrlen = CC3000_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; +} + +/***************************************************************************** + * Name: bind + * + * Decription: + * 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. + * + * Input Parameters: + * sd socket descriptor (handle) + * addr specifies the destination address. On this version + * only AF_INET is supported. + * addrlen contains the size of the structure pointed to by addr. + * + * Returned Value: + * On success, zero is returned. On error, -1 is returned. + * + *****************************************************************************/ + +long cc3000_bind_impl(long sd, const struct sockaddr *addr, socklen_t addrlen) +{ + long ret; + uint8_t *ptr, *args; + + ret = EFAIL; + ptr = tSLInformation.pucTxCommandBuffer; + args = (ptr + HEADERS_SIZE_CMD); + + addrlen = CC3000_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 */ + + SimpleLinkWaitEvent(HCI_CMND_BIND, &ret); + + errno = ret; + + return ret; +} + +/***************************************************************************** + * Name: listen + * + * Decription: + * 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. + * + * NOTE: On this version, backlog is not supported + * + * Input Parameters: + * sd socket descriptor (handle) + * backlog specifies the listen queue depth. On this version + * backlog is not supported. + * + * Returned Value: + * On success, zero is returned. On error, -1 is returned. + * + *****************************************************************************/ + +long cc3000_listen_impl(long sd, long backlog) +{ + long ret; + uint8_t *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; +} + +/***************************************************************************** + * Name: gethostbyname + * + * Decription: + * 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. + * + * Input Parameters: + * hostname host name + * usNameLen name length + * 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. + * + * Returned Value: + * On success, positive is returned. On error, negative is returned + * + *****************************************************************************/ + +#ifndef CC3000_TINY_DRIVER +int cc3000_gethostbyname_impl(char * hostname, uint16_t usNameLen, unsigned long* out_ip_addr) +{ + tBsdGethostbynameParams ret; + uint8_t *ptr, *args; + + errno = EFAIL; + + if (usNameLen > CC3000_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 + +/***************************************************************************** + * Name: connect + * + * Decription: + * 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. + * + * Input Parameters: + * sd socket descriptor (handle) + * addr specifies the destination addr. On this version + * only AF_INET is supported. + * addrlen contains the size of the structure pointed to by addr + * + * Returned Value: + * On success, zero is returned. On error, -1 is returned + * + *****************************************************************************/ + +long cc3000_connect_impl(long sd, const struct sockaddr *addr, socklen_t addrlen) +{ + long int ret; + uint8_t *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, ((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 */ + + SimpleLinkWaitEvent(HCI_CMND_CONNECT, &ret); + + errno = ret; + + return (long)ret; +} + +/***************************************************************************** + * Name: select + * + * Decription: + * 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 + * + * Input Parameters: + * nfds the highest-numbered file descriptor in any of the + * three sets, plus 1. + * writesds socket descriptors list for write monitoring + * readsds socket descriptors list for read monitoring + * exceptsds socket descriptors list for exception monitoring + * 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. + * + * Returned Value: + * 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. + * + *****************************************************************************/ + +int cc3000_select_impl(long nfds, TICC3000fd_set *readsds, TICC3000fd_set *writesds, + TICC3000fd_set *exceptsds, struct timeval *timeout) +{ + uint8_t *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; + } +} + +/***************************************************************************** + * Name: setsockopt + * + * Decription: + * 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). + * + * Input Parameters: + * sd socket handle + * level defines the protocol level for this option + * optname defines the option name to Interrogate + * optval specifies a value for the option + * optlen specifies the length of the option value + * + * Returned Value: + * On success, zero is returned. On error, -1 is returned + * + *****************************************************************************/ + +#ifndef CC3000_TINY_DRIVER +int cc3000_setsockopt_impl(long sd, long level, long optname, const void *optval, socklen_t optlen) +{ + int ret; + uint8_t *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, ((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 */ + + SimpleLinkWaitEvent(HCI_CMND_SETSOCKOPT, &ret); + + if (ret >= 0) + { + return 0; + } + else + { + errno = ret; + return ret; + } +} +#endif + +/***************************************************************************** + * Name: getsockopt + * + * Decription: + * 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). + * + * Input Parameters: + * sd socket handle + * level defines the protocol level for this option + * optname defines the option name to Interrogate + * optval specifies a value for the option + * optlen specifies the length of the option value + * + * Returned Value: + * On success, zero is returned. On error, -1 is returned + * + *****************************************************************************/ + +int cc3000_getsockopt_impl(long sd, long level, long optname, void *optval, socklen_t *optlen) +{ + uint8_t *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 (((int8_t)tRetParams.iStatus) >= 0) + { + *optlen = 4; + memcpy(optval, tRetParams.ucOptValue, 4); + return 0; + } + else + { + errno = tRetParams.iStatus; + return errno; + } +} + +/***************************************************************************** + * Name: simple_link_recv + * + * Input Parameters: + * sd socket handle + * buf read buffer + * len buffer length + * flags indicates blocking or non-blocking operation + * from pointer to an address structure indicating source address + * fromlen source address structure size + * + * Returned Value: + * Return the number of bytes received, or -1 if an error + * occurred + * + * Decription: + * 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 + * + *****************************************************************************/ + +int simple_link_recv(long sd, void *buf, long len, long flags, struct sockaddr *from, + socklen_t *fromlen, long opcode) +{ + uint8_t *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((uint8_t *)buf, (uint8_t *)from, (uint8_t *)fromlen); + } + + errno = tSocketReadEvent.iNumberOfBytes; + + return tSocketReadEvent.iNumberOfBytes; +} + +/***************************************************************************** + * Name: recv + * + * Decription: + * function receives a message from a connection-mode socket + * + * NOTE: On this version, only blocking mode is supported. + * + * Input Parameters: + * sd socket handle + * buf Points to the buffer where the message should be stored + * len Specifies the length in bytes of the buffer pointed to + * by the buffer argument. + * flags Specifies the type of message reception. + * On this version, this parameter is not supported. + * + * Returned Value: + * Return the number of bytes received, or -1 if an error + * occurred + * + *****************************************************************************/ + +int cc3000_recv_impl(long sd, void *buf, long len, long flags) +{ + return(simple_link_recv(sd, buf, len, flags, NULL, NULL, HCI_CMND_RECV)); +} + +/***************************************************************************** + * Name: recvfrom + * + * Decription: + * read data from socket + * function receives a message from a connection-mode or + * connectionless-mode socket. Note that raw sockets are not + * supported. + * + * NOTE: On this version, only blocking mode is supported. + * + * Input Parameters: + * sd socket handle + * buf Points to the buffer where the message should be stored + * len Specifies the length in bytes of the buffer pointed to + * by the buffer argument. + * flags Specifies the type of message reception. + * On this version, this parameter is not supported. + * from pointer to an address structure indicating the source + * address: sockaddr. On this version only AF_INET is + * supported. + * fromlen source address tructure size + * + * Returned Value: + * Return the number of bytes received, or -1 if an error + * occurred + * + *****************************************************************************/ + +int cc3000_recvfrom_impl(long sd, void *buf, long len, long flags, struct sockaddr *from, + socklen_t *fromlen) +{ + return(simple_link_recv(sd, buf, len, flags, from, fromlen, + HCI_CMND_RECVFROM)); +} + +/***************************************************************************** + * Name: simple_link_send + * + * Input Parameters: + * sd socket handle + * buf write buffer + * len buffer length + * flags On this version, this parameter is not supported + * to pointer to an address structure indicating destination + * address + * tolen destination address structure size + * + * Returned Value: + * Return the number of bytes transmitted, or -1 if an error + * occurred, or -2 in case there are no free buffers available + * (only when SEND_NON_BLOCKING is enabled) + * + * Decription: + * This function is used to transmit a message to another + * socket + * + *****************************************************************************/ + +int simple_link_send(long sd, const void *buf, long len, long flags, + const struct sockaddr *to, long tolen, long opcode) +{ + tBsdReadReturnParams tSocketSendEvent; + uint8_t uArgSize = 0, addrlen; + uint8_t *ptr, *pDataPtr = NULL, *args; + unsigned long addr_offset = 0; + int res; + + /* Check the bsd_arguments */ + + if (0 != (res = HostFlowControlConsumeBuff(sd))) + { + return res; + } + + /* Update the number of sent packets */ + + tSLInformation.NumberOfSentPackets++; + + /* Allocate a buffer and construct a packet and send it over spi */ + + ptr = tSLInformation.pucTxCommandBuffer; + 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) + { + SimpleLinkWaitEvent(HCI_EVNT_SENDTO, &tSocketSendEvent); + } + else + { + SimpleLinkWaitEvent(HCI_EVNT_SEND, &tSocketSendEvent); + } + + return len; +} + +/***************************************************************************** + * Name: send + * + * Decription: + * Write data to TCP socket + * This function is used to transmit a message to another + * socket. + * + * NOTE: On this version, only blocking mode is supported. + * + * Input Parameters: + * sd socket handle + * buf Points to a buffer containing the message to be sent + * len message size in bytes + * flags On this version, this parameter is not supported + * + * Returned Value: + * Return the number of bytes transmitted, or -1 if an + * error occurred + * + *****************************************************************************/ + +int cc3000_send_impl(long sd, const void *buf, long len, long flags) +{ + return(simple_link_send(sd, buf, len, flags, NULL, 0, HCI_CMND_SEND)); +} + +/***************************************************************************** + * Name: sendto + * + * Decription: + * Write data to TCP socket + * This function is used to transmit a message to another + * socket. + * + * NOTE: On this version, only blocking mode is supported. + * + * Input Parameters: + * sd socket handle + * buf Points to a buffer containing the message to be sent + * len message size in bytes + * flags On this version, this parameter is not supported + * to pointer to an address structure indicating the destination + * address: sockaddr. On this version only AF_INET is + * supported. + * tolen destination address structure size + * + * Returned Value: + * Return the number of bytes transmitted, or -1 if an + * error occurred + * + *****************************************************************************/ + +int cc3000_sendto_impl(long sd, const void *buf, long len, long flags, const struct sockaddr *to, + socklen_t tolen) +{ + return(simple_link_send(sd, buf, len, flags, to, tolen, HCI_CMND_SENDTO)); +} + +/***************************************************************************** + * Name: mdnsAdvertiser + * + * Decription: + * Set CC3000 in mDNS advertiser mode in order to advertise itself. + * + * Input Parameters: + * mdnsEnabled flag to enable/disable the mDNS feature + * deviceServiceName Service name as part of the published + * canonical domain name + * deviceServiceNameLength Length of the service name + * + * Returned Value: + * On success, zero is returned, return SOC_ERROR if socket was not + * opened successfully, or if an error occurred. + * + *****************************************************************************/ + +int cc3000_mdnsadvertiser_impl(uint16_t mdnsEnabled, char * deviceServiceName, + uint16_t deviceServiceNameLength) +{ + uint8_t *pTxBuffer; + uint8_t *pArgs; + int ret; + + if (deviceServiceNameLength > MDNS_DEVICE_SERVICE_MAX_LENGTH) + { + return EFAIL; + } + + pTxBuffer = tSLInformation.pucTxCommandBuffer; + pArgs = (pTxBuffer + SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE); + + /* Fill in HCI packet structure */ + + pArgs = UINT32_TO_STREAM(pArgs, mdnsEnabled); + pArgs = UINT32_TO_STREAM(pArgs, 8); + pArgs = UINT32_TO_STREAM(pArgs, deviceServiceNameLength); + ARRAY_TO_STREAM(pArgs, deviceServiceName, deviceServiceNameLength); + + /* Initiate a HCI command */ + + hci_command_send(HCI_CMND_MDNS_ADVERTISE, pTxBuffer, SOCKET_MDNS_ADVERTISE_PARAMS_LEN + deviceServiceNameLength); + + /* Since we are in blocking state - wait for event complete */ + + SimpleLinkWaitEvent(HCI_EVNT_MDNS_ADVERTISE, &ret); + + return ret; +} diff --git a/drivers/wireless/cc3000/spi.c b/drivers/wireless/cc3000/spi.c index 758e2ec670b..a5e190e3bce 100644 --- a/drivers/wireless/cc3000/spi.c +++ b/drivers/wireless/cc3000/spi.c @@ -71,6 +71,7 @@ static struct bool run; uint8_t rx_buffer[CC3000_RX_BUFFER_SIZE]; mqd_t queue; + sem_t *done; } spiconf; @@ -95,12 +96,9 @@ static struct void SpiResumeSpi(void) { - DEBUGASSERT(spiconf.cc3000fd); - - if (ioctl(spiconf.cc3000fd,CC3000IOC_COMPLETE,0)) - { - printf("ioctl:CC3000IOC_COMPLETE failed: %s\n", strerror(errno)); - } + DEBUGASSERT(spiconf.cc3000fd && spiconf.done); + sem_post(spiconf.done); + nllvdbg("Done\n"); } /***************************************************************************** @@ -158,10 +156,9 @@ long SpiRead(uint8_t *pUserBuffer, uint16_t usLength) uint8_t *SpiWait(void) { - int nbytes; DEBUGASSERT(spiconf.cc3000fd); - nbytes = mq_receive(spiconf.queue, spiconf.rx_buffer, CC3000_RX_BUFFER_SIZE, 0); + mq_receive(spiconf.queue, spiconf.rx_buffer, CC3000_RX_BUFFER_SIZE, 0); return spiconf.rx_buffer; } @@ -181,14 +178,19 @@ uint8_t *SpiWait(void) static void *unsoliced_thread_func(void *parameter) { - char queuename[QUEUE_NAMELEN]; + char buff[QUEUE_NAMELEN]; int status = 0; int nbytes = 0; int minor = 0; - ioctl(spiconf.cc3000fd, CC3000IOC_GETQUEID, (unsigned long)&minor); - snprintf(queuename, QUEUE_NAMELEN, QUEUE_FORMAT, minor); - spiconf.queue = mq_open(queuename,O_RDONLY); + ioctl(spiconf.cc3000fd, CC3000IOC_GETQUESEMID, (unsigned long)&minor); + snprintf(buff, QUEUE_NAMELEN, QUEUE_FORMAT, minor); + spiconf.queue = mq_open(buff,O_RDONLY); + DEBUGASSERT(spiconf.queue != (mqd_t) -1); + DEBUGASSERT(SEM_NAMELEN == QUEUE_NAMELEN); + snprintf(buff, SEM_NAMELEN, SEM_FORMAT, minor); + spiconf.done = sem_open(buff,O_RDONLY); + DEBUGASSERT(spiconf.done != (sem_t *)-1); while(spiconf.run) { @@ -196,12 +198,13 @@ static void *unsoliced_thread_func(void *parameter) nbytes = mq_receive(spiconf.queue, spiconf.rx_buffer, CC3000_RX_BUFFER_SIZE, 0); if (nbytes > 0) { - spivdbg("%d Processed\n",nbytes); + nlldbg("%d Processed\n",nbytes); spiconf.pfRxHandler(spiconf.rx_buffer); } } mq_close(spiconf.queue); + sem_close(spiconf.done); pthread_exit((pthread_addr_t)status); return (pthread_addr_t)status; } @@ -223,9 +226,11 @@ static void *unsoliced_thread_func(void *parameter) void SpiOpen(gcSpiHandleRx pfRxHandler) { int status; + int fd; DEBUGASSERT(spiconf.cc3000fd == 0); - int fd = open("/dev/wireless0",O_RDWR|O_BINARY); + + fd = open("/dev/wireless0",O_RDWR|O_BINARY); if (fd > 0) { spiconf.pfRxHandler = pfRxHandler; diff --git a/drivers/wireless/cc3000/wlan.c b/drivers/wireless/cc3000/wlan.c index 489fb1a950c..11c934b6c5f 100644 --- a/drivers/wireless/cc3000/wlan.c +++ b/drivers/wireless/cc3000/wlan.c @@ -41,16 +41,18 @@ #include #include +#include #include #include #include -#include "spi.h" -#include #include #include #include +#include "spi.h" +#include "cc3000.h" + /***************************************************************************** * Preprocessor Definitions *****************************************************************************/ @@ -137,7 +139,8 @@ static void SimpleLink_Init_Start(uint16_t usPatchesAvailableAtHost) ptr = tSLInformation.pucTxCommandBuffer; args = (uint8_t *)(ptr + HEADERS_SIZE_CMD); - UINT8_TO_STREAM(args, ((usPatchesAvailableAtHost) ? SL_PATCHES_REQUEST_FORCE_HOST : SL_PATCHES_REQUEST_DEFAULT)); + UINT8_TO_STREAM(args, ((usPatchesAvailableAtHost) ? + SL_PATCHES_REQUEST_FORCE_HOST : SL_PATCHES_REQUEST_DEFAULT)); /* IRQ Line asserted - send HCI_CMND_SIMPLE_LINK_START to CC3000 */ @@ -194,23 +197,14 @@ static void SimpleLink_Init_Start(uint16_t usPatchesAvailableAtHost) void wlan_init(tWlanCB sWlanCB, tFWPatches sFWPatches, tDriverPatches sDriverPatches, - tBootLoaderPatches sBootLoaderPatches, - tWlanReadInteruptPin sReadWlanInterruptPin, - tWlanInterruptEnable sWlanInterruptEnable, - tWlanInterruptDisable sWlanInterruptDisable, - tWriteWlanPin sWriteWlanPin) + tBootLoaderPatches sBootLoaderPatches) { + cc3000_lib_lock(); tSLInformation.sFWPatches = sFWPatches; tSLInformation.sDriverPatches = sDriverPatches; tSLInformation.sBootLoaderPatches = sBootLoaderPatches; /* Init I/O callback */ - - tSLInformation.ReadWlanInterruptPin = sReadWlanInterruptPin; - tSLInformation.WlanInterruptEnable = sWlanInterruptEnable; - tSLInformation.WlanInterruptDisable = sWlanInterruptDisable; - tSLInformation.WriteWlanPin = sWriteWlanPin; - /* Init asynchronous events callback */ tSLInformation.sWlanCB= sWlanCB; @@ -218,6 +212,7 @@ void wlan_init(tWlanCB sWlanCB, tFWPatches sFWPatches, /* By default TX Complete events are routed to host too */ tSLInformation.InformHostOnTxComplete = 1; + cc3000_lib_unlock(); } /***************************************************************************** @@ -237,8 +232,12 @@ void wlan_init(tWlanCB sWlanCB, tFWPatches sFWPatches, void SpiReceiveHandler(void *pvBuffer) { - tSLInformation.usEventOrDataReceived = 1; tSLInformation.pucReceivedData = (uint8_t *)pvBuffer; + tSLInformation.usEventOrDataReceived = 1; + + uint16_t event_type; + STREAM_TO_UINT16((char *)tSLInformation.pucReceivedData, HCI_EVENT_OPCODE_OFFSET,event_type); + nllvdbg("Evtn:0x%x\n", event_type); hci_unsolicited_event_handler(); } @@ -272,7 +271,7 @@ void SpiReceiveHandler(void *pvBuffer) void wlan_start(uint16_t usPatchesAvailableAtHost) { - unsigned long ulSpiIRQState; + cc3000_lib_lock(); tSLInformation.NumberOfSentPackets = 0; tSLInformation.NumberOfReleasedPackets = 0; @@ -293,41 +292,13 @@ void wlan_start(uint16_t usPatchesAvailableAtHost) SpiOpen(SpiReceiveHandler); - /* Check the IRQ line */ - - ulSpiIRQState = tSLInformation.ReadWlanInterruptPin(); - - /* ASIC 1273 chip enable: toggle WLAN EN line */ - - tSLInformation.WriteWlanPin(WLAN_ENABLE); - - if (ulSpiIRQState) - { - /* Wait till the IRQ line goes low */ - - while (tSLInformation.ReadWlanInterruptPin() != 0) - { - } - } - else - { - /* Wait till the IRQ line goes high and than low */ - - while (tSLInformation.ReadWlanInterruptPin() == 0) - { - } - - while (tSLInformation.ReadWlanInterruptPin() != 0) - { - } - } - SimpleLink_Init_Start(usPatchesAvailableAtHost); /* Read Buffer's size and finish */ hci_command_send(HCI_CMND_READ_BUFFER_SIZE, tSLInformation.pucTxCommandBuffer, 0); SimpleLinkWaitEvent(HCI_CMND_READ_BUFFER_SIZE, 0); + cc3000_lib_unlock(); } /***************************************************************************** @@ -346,24 +317,9 @@ void wlan_start(uint16_t usPatchesAvailableAtHost) void wlan_stop(void) { - /* ASIC 1273 chip disable */ - - tSLInformation.WriteWlanPin(WLAN_DISABLE); - - /* Wait till IRQ line goes high... */ - - while (tSLInformation.ReadWlanInterruptPin() == 0) - { - } - - /* Free the used by WLAN Driver memory */ - - if (tSLInformation.pucTxCommandBuffer) - { - tSLInformation.pucTxCommandBuffer = 0; - } - + cc3000_lib_lock(); SpiClose(); + cc3000_lib_unlock(); } /***************************************************************************** @@ -407,6 +363,8 @@ long wlan_connect(unsigned long ulSecType, char *ssid, long ssid_len, uint8_t *args; uint8_t bssid_zero[] = {0, 0, 0, 0, 0, 0}; + cc3000_lib_lock(); + ret = EFAIL; ptr = tSLInformation.pucTxCommandBuffer; args = (ptr + HEADERS_SIZE_CMD); @@ -447,7 +405,7 @@ long wlan_connect(unsigned long ulSecType, char *ssid, long ssid_len, SimpleLinkWaitEvent(HCI_CMND_WLAN_CONNECT, &ret); errno = ret; - + cc3000_lib_unlock(); return ret; } #else @@ -458,6 +416,8 @@ long wlan_connect(char *ssid, long ssid_len) uint8_t *args; uint8_t bssid_zero[] = {0, 0, 0, 0, 0, 0}; + cc3000_lib_lock(); + ret = EFAIL; ptr = tSLInformation.pucTxCommandBuffer; args = (ptr + HEADERS_SIZE_CMD); @@ -486,6 +446,8 @@ long wlan_connect(char *ssid, long ssid_len) SimpleLinkWaitEvent(HCI_CMND_WLAN_CONNECT, &ret); errno = ret; + cc3000_lib_unlock(); + return ret; } #endif @@ -509,6 +471,8 @@ long wlan_disconnect(void) long ret; uint8_t *ptr; + cc3000_lib_lock(); + ret = EFAIL; ptr = tSLInformation.pucTxCommandBuffer; @@ -519,6 +483,8 @@ long wlan_disconnect(void) SimpleLinkWaitEvent(HCI_CMND_WLAN_DISCONNECT, &ret); errno = ret; + cc3000_lib_unlock(); + return ret; } @@ -562,6 +528,8 @@ long wlan_ioctl_set_connection_policy(unsigned long should_connect_to_open_ap, uint8_t *ptr; uint8_t *args; + cc3000_lib_lock(); + ret = EFAIL; ptr = tSLInformation.pucTxCommandBuffer; args = (uint8_t *)(ptr + HEADERS_SIZE_CMD); @@ -581,6 +549,7 @@ long wlan_ioctl_set_connection_policy(unsigned long should_connect_to_open_ap, SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_SET_CONNECTION_POLICY, &ret); + cc3000_lib_unlock(); return ret; } @@ -628,6 +597,8 @@ long wlan_add_profile(unsigned long ulSecType, uint8_t* ucSsid, uint8_t *args; uint8_t bssid_zero[] = {0, 0, 0, 0, 0, 0}; + cc3000_lib_lock(); + ptr = tSLInformation.pucTxCommandBuffer; args = (ptr + HEADERS_SIZE_CMD); @@ -733,7 +704,7 @@ long wlan_add_profile(unsigned long ulSecType, uint8_t* ucSsid, /* Wait for command complete event */ SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_ADD_PROFILE, &ret); - + cc3000_lib_unlock(); return ret; } #else @@ -770,6 +741,8 @@ long wlan_ioctl_del_profile(unsigned long ulIndex) uint8_t *ptr; uint8_t *args; + cc3000_lib_lock(); + ptr = tSLInformation.pucTxCommandBuffer; args = (uint8_t *)(ptr + HEADERS_SIZE_CMD); @@ -787,6 +760,8 @@ long wlan_ioctl_del_profile(unsigned long ulIndex) SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_DEL_PROFILE, &ret); + cc3000_lib_unlock(); + return ret; } @@ -829,6 +804,8 @@ long wlan_ioctl_get_scan_results(unsigned long ulScanTimeout, uint8_t *ucResults uint8_t *ptr; uint8_t *args; + cc3000_lib_lock(); + ptr = tSLInformation.pucTxCommandBuffer; args = (ptr + HEADERS_SIZE_CMD); @@ -845,6 +822,8 @@ long wlan_ioctl_get_scan_results(unsigned long ulScanTimeout, uint8_t *ucResults SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_GET_SCAN_RESULTS, ucResults); + cc3000_lib_unlock(); + return 0; } #endif @@ -900,6 +879,8 @@ long wlan_ioctl_set_scan_params(unsigned long uiEnable, uint8_t *ptr; uint8_t *args; + cc3000_lib_lock(); + ptr = tSLInformation.pucTxCommandBuffer; args = (ptr + HEADERS_SIZE_CMD); @@ -926,6 +907,8 @@ long wlan_ioctl_set_scan_params(unsigned long uiEnable, SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_SET_SCANPARAM, &uiRes); + cc3000_lib_unlock(); + return uiRes; } #endif @@ -960,6 +943,8 @@ long wlan_set_event_mask(unsigned long ulMask) uint8_t *ptr; uint8_t *args; + cc3000_lib_lock(); + if ((ulMask & HCI_EVNT_WLAN_TX_COMPLETE) == HCI_EVNT_WLAN_TX_COMPLETE) { tSLInformation.InformHostOnTxComplete = 0; @@ -998,6 +983,8 @@ long wlan_set_event_mask(unsigned long ulMask) SimpleLinkWaitEvent(HCI_CMND_EVENT_MASK, &ret); + cc3000_lib_unlock(); + return ret; } @@ -1022,6 +1009,8 @@ long wlan_ioctl_statusget(void) long ret; uint8_t *ptr; + cc3000_lib_lock(); + ret = EFAIL; ptr = tSLInformation.pucTxCommandBuffer; @@ -1032,6 +1021,8 @@ long wlan_ioctl_statusget(void) SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_STATUSGET, &ret); + cc3000_lib_unlock(); + return ret; } #endif @@ -1063,6 +1054,8 @@ long wlan_smart_config_start(unsigned long algoEncryptedFlag) uint8_t *ptr; uint8_t *args; + cc3000_lib_lock(); + ret = EFAIL; ptr = tSLInformation.pucTxCommandBuffer; args = (uint8_t *)(ptr + HEADERS_SIZE_CMD); @@ -1079,6 +1072,7 @@ long wlan_smart_config_start(unsigned long algoEncryptedFlag) SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_START, &ret); + cc3000_lib_unlock(); return ret; } @@ -1101,6 +1095,8 @@ long wlan_smart_config_stop(void) long ret; uint8_t *ptr; + cc3000_lib_lock(); + ret = EFAIL; ptr = tSLInformation.pucTxCommandBuffer; @@ -1110,6 +1106,7 @@ long wlan_smart_config_stop(void) SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_STOP, &ret); + cc3000_lib_unlock(); return ret; } @@ -1136,6 +1133,8 @@ long wlan_smart_config_set_prefix(char* cNewPrefix) uint8_t *ptr; uint8_t *args; + cc3000_lib_lock(); + ret = EFAIL; ptr = tSLInformation.pucTxCommandBuffer; args = (ptr + HEADERS_SIZE_CMD); @@ -1163,6 +1162,8 @@ long wlan_smart_config_set_prefix(char* cNewPrefix) SimpleLinkWaitEvent(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_SET_PREFIX, &ret); + cc3000_lib_unlock(); + return ret; }