diff --git a/drivers/wireless/cc3000/cc3000drv.c b/drivers/wireless/cc3000/cc3000drv.c new file mode 100644 index 0000000000..b12e72d463 --- /dev/null +++ b/drivers/wireless/cc3000/cc3000drv.c @@ -0,0 +1,400 @@ +/************************************************************************** + * drivers/wireless/cc3000/cc3000drv.c - Driver wrapper functions to + * conntect nuttx to the TI CC3000 + * + * 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 +#include +#include +#include +#include +#include +#include "cc3000drv.h" + +#include +#include + +/***************************************************************************** + * Pre-processor Definitions + *****************************************************************************/ + +#undef SPI_DEBUG /* Define to enable debug */ +#undef SPI_VERBOSE /* Define to enable verbose debug */ + +#ifdef SPI_DEBUG +# define spidbg lldbg +# ifdef SPI_VERBOSE +# define spivdbg lldbg +# else +# define spivdbg(x...) +# endif +#else +# undef SPI_VERBOSE +# define spidbg(x...) +# define spivdbg(x...) +#endif + +/***************************************************************************** + * Private Types + *****************************************************************************/ + +static struct +{ + int cc3000fd; + gcSpiHandleRx pfRxHandler; + pthread_t unsoliced_thread; + bool run; + uint8_t rx_buffer[CC3000_RX_BUFFER_SIZE]; + mqd_t queue; + sem_t *done; +} spiconf; + +/***************************************************************************** + * Public Functions + *****************************************************************************/ + +/***************************************************************************** + * Name: cc3000_resume + * + * Description: + * Will re enable the to deliver messages + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + *****************************************************************************/ + +void cc3000_resume(void) +{ + DEBUGASSERT(spiconf.cc3000fd && spiconf.done); + sem_post(spiconf.done); + nllvdbg("Done\n"); +} + +/***************************************************************************** + * Name: cc3000_write + * + * Description: + * This function enter point for write flow + * + * Input Parameters: + * pUserBuffer + * usLength + * + * Returned Value: + * + *****************************************************************************/ + +long cc3000_write(uint8_t *pUserBuffer, uint16_t usLength) +{ + DEBUGASSERT(spiconf.cc3000fd); + return write(spiconf.cc3000fd,pUserBuffer,usLength) == usLength ? 0 : -errno; +} + +/***************************************************************************** + * Name: cc3000_read + * + * Description: + * This function enter point for read flow. This function will block the + * caller untinlthere is data Available + * + * Input Parameters: + * pUserBuffer + * usLength + * + * Returned Value: + * + *****************************************************************************/ + +long cc3000_read(uint8_t *pUserBuffer, uint16_t usLength) +{ + DEBUGASSERT(spiconf.cc3000fd); + return read(spiconf.cc3000fd,pUserBuffer,usLength); +} + +/***************************************************************************** + * Name: cc3000_wait + * + * Description: + * Waits on a message from the driver. + * + * Input Parameters: + * None + * + * Returned Value: + * + *****************************************************************************/ + +uint8_t *cc3000_wait(void) +{ + DEBUGASSERT(spiconf.cc3000fd); + + mq_receive(spiconf.queue, spiconf.rx_buffer, CC3000_RX_BUFFER_SIZE, 0); + return spiconf.rx_buffer; +} + +/***************************************************************************** + * Name: unsoliced_thread_func + * + * Description: + * This is the thread for unsolicited events. This function will block the + * caller untinlthere is data Available + * + * Input Parameters: + * parameter + * + * Returned Value: + * + *****************************************************************************/ + +static void *unsoliced_thread_func(void *parameter) +{ + char buff[QUEUE_NAMELEN]; + int status = 0; + int nbytes = 0; + int minor = 0; + + 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) + { + memset(spiconf.rx_buffer,0,sizeof(spiconf.rx_buffer)); + nbytes = mq_receive(spiconf.queue, spiconf.rx_buffer, + CC3000_RX_BUFFER_SIZE, 0); + if (nbytes > 0) + { + 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; +} + +/***************************************************************************** + * Name: cc3000_open + * + * Description: + * Open the cc3000 driver + * + * Input Parameters: + * pfRxHandler the Rx handler for messages + * + * Returned Value: + * None + * + *****************************************************************************/ + +void cc3000_open(gcSpiHandleRx pfRxHandler) +{ + int status; + int fd; + + DEBUGASSERT(spiconf.cc3000fd == 0); + + fd = open("/dev/wireless0",O_RDWR|O_BINARY); + if (fd > 0) + { + spiconf.pfRxHandler = pfRxHandler; + spiconf.cc3000fd = fd; + spiconf.run = true; + + pthread_attr_t attr; + struct sched_param param; + pthread_attr_init(&attr); + attr.stacksize = 364; + param.sched_priority = SCHED_PRIORITY_DEFAULT-10; + pthread_attr_setschedparam(&attr, ¶m); + status = pthread_create(&spiconf.unsoliced_thread, &attr, + unsoliced_thread_func, NULL); + DEBUGASSERT(status == 0) + } + + DEBUGASSERT(spiconf.cc3000fd); +} + +/***************************************************************************** + * Name: cc3000_close + * + * Description: + * Close the cc3000 driver + * + * Input Parameters: + * None + * + * Returned Value: + * None + * + *****************************************************************************/ + +void cc3000_close(void) +{ + if (spiconf.cc3000fd) + { + int status; + spiconf.run = false; + + pthread_cancel(spiconf.unsoliced_thread); + pthread_join(spiconf.unsoliced_thread, (pthread_addr_t*)&status); + + close(spiconf.cc3000fd); + spiconf.cc3000fd = 0; + } +} + +/**************************************************************************** + * Name: cc3000_wait_data + * + * Description: + * Adds this socket for monitoring for the data operation + * + * Input Parameters: + * sd cc3000 socket handle or -1 tp remove it + * + * Returned Value: + * Zero is returned on success. Otherwise, a -1 value is + * returned to indicate socket not found. + * + ****************************************************************************/ + +int cc3000_wait_data(int sockfd) +{ + DEBUGASSERT(spiconf.cc3000fd); + int rv = sockfd; + ioctl(spiconf.cc3000fd, CC3000IOC_SELECTDATA, (unsigned long)&rv); + return rv; +} + +/**************************************************************************** + * 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 to_cc3000_accept_socket(int sockfd, struct sockaddr *addr, socklen_t *addrlen); + +int cc3000_accept_socket(int sockfd, struct sockaddr *addr, socklen_t *addrlen) +{ + //return to_cc3000_accept_socket(sockfd, addr,addrlen); + DEBUGASSERT(spiconf.cc3000fd); + + cc3000_acceptcfg cfg; + cfg.sockfd = sockfd; + cfg.addr = addr; + cfg.addrlen = addrlen; + ioctl(spiconf.cc3000fd, CC3000IOC_SELECTACCEPT, (unsigned long)&cfg); + return cfg.sockfd; +} + +/**************************************************************************** + * 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 sockfd) +{ + DEBUGASSERT(spiconf.cc3000fd); + int rv = sockfd; + ioctl(spiconf.cc3000fd, CC3000IOC_ADDSOCKET, (unsigned long)&rv); + return rv; +} + +/**************************************************************************** + * 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 sockfd) +{ + DEBUGASSERT(spiconf.cc3000fd); + int rv = sockfd; + ioctl(spiconf.cc3000fd, CC3000IOC_REMOVESOCKET, (unsigned long)&rv); + return rv; +} diff --git a/drivers/wireless/cc3000/cc3000drv.h b/drivers/wireless/cc3000/cc3000drv.h new file mode 100644 index 0000000000..72745d5fcc --- /dev/null +++ b/drivers/wireless/cc3000/cc3000drv.h @@ -0,0 +1,88 @@ +/************************************************************************** + * drivers/wireless/cc3000/cc3000drv.h - Driver wrapper functions to + * connect nuttx to the TI CC3000 + * + * 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. + * + *****************************************************************************/ + +#ifndef __DRIVERS_WIRELESS_CC3000_CC3000DRV_H +#define __DRIVERS_WIRELESS_CC3000_CC3000DRV_H + +/***************************************************************************** + * Included Files + *****************************************************************************/ + +#include +#include + +/***************************************************************************** + * Public Types + *****************************************************************************/ + +typedef void (*gcSpiHandleRx)(void *p); + +/***************************************************************************** + * Public Data + *****************************************************************************/ + +/***************************************************************************** + * Public Function Prototypes + *****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +void cc3000_open(gcSpiHandleRx pfRxHandler); +void cc3000_close(void); +long cc3000_write(uint8_t *pUserBuffer, uint16_t usLength); +uint8_t *cc3000_wait(void); +long cc3000_read(uint8_t *pUserBuffer, uint16_t usLength); +void cc3000_resume(void); + +int cc3000_wait_data(int sockfd); +int cc3000_accept_socket(int sockfd, struct sockaddr *addr, + socklen_t *addrlen); +int cc3000_add_socket(int sockfd); +int cc3000_remove_socket(int sockfd); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __DRIVERS_WIRELESS_CC3000_CC3000DRV_H */