add access to nvmem functions to enable firmware update
Fork of cc3000_hostdriver_mbedsocket by
Revision 0:615c697c33b0, committed 2013-09-19
- Comitter:
- Kojto
- Date:
- Thu Sep 19 07:55:14 2013 +0000
- Child:
- 1:c7b8f55e0ca1
- Commit message:
- initial commit
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Helper/def.h Thu Sep 19 07:55:14 2013 +0000 @@ -0,0 +1,28 @@ +/* Copyright (C) 2012 mbed.org, MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef DEF_H +#define DEF_H + +#include "cmsis.h" +//#define htons(x) __REV16(x) +//#define ntohs(x) __REV16(x) +//#define htonl(x) __REV(x) +//#define ntohl(x) __REV(x) + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Socket/Endpoint.cpp Thu Sep 19 07:55:14 2013 +0000 @@ -0,0 +1,123 @@ +/* Copyright (C) 2012 mbed.org, MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#include "Socket/Socket.h" +#include "Socket/Endpoint.h" +#include <cstring> + + #include "cc3000.h" + +using std::memset; + +Endpoint::Endpoint() { + _cc3000_module = cc3000::get_instance(); + if (_cc3000_module == NULL) { + error("Endpoint constructor error: no cc3000 instance available!\r\n"); + } + reset_address(); +} +Endpoint::~Endpoint() {} + +void Endpoint::reset_address(void) { + _ipAddress[0] = '\0'; + std::memset(&_remote_host,0, sizeof(sockaddr)); +} + +int Endpoint::set_address(const char* host, const int port) { + reset_address(); + + // IP Address + char address[5]; + char *p_address = address; + + // Dot-decimal notation + int result = std::sscanf(host, "%3u.%3u.%3u.%3u", + (unsigned int*)&address[0], (unsigned int*)&address[1], + (unsigned int*)&address[2], (unsigned int*)&address[3]); + + if (result != 4) { + //Resolve DNS address or populate hard-coded IP address + uint32_t address_integer; + _cc3000_module->_socket.get_host_by_name((uint8_t *)host, strlen(host) , &address_integer); + + address[0] = (address_integer >> 24); + address[1] = (address_integer >> 16); + address[2] = (address_integer >> 8); + address[3] = (address_integer >> 0); + sprintf(_ipAddress,"%3u.%3u.%3u.%3u", address[0],address[1],address[2],address[3]); + _remote_host.sin_addr.s_addr = address_integer; + } else { + std::memcpy((char*)&_remote_host.sin_addr.s_addr, p_address, 4); + } + + /* store address*/ + _remote_host.sin_family = AF_INET; + + // Set port + _remote_host.sin_port = htons(port); + + return 0; +} + +static char *inet_ntoa_r(const in_addr addr, char *buf, int buflen) +{ + uint32_t s_addr; + char inv[3]; + char *rp; + uint8_t *ap; + uint8_t rem; + uint8_t n; + uint8_t i; + int len = 0; + + s_addr = addr.s_addr; + + rp = buf; + ap = (uint8_t *)&s_addr; + for(n = 0; n < 4; n++) { + i = 0; + do { + rem = *ap % (uint8_t)10; + *ap /= (uint8_t)10; + inv[i++] = '0' + rem; + } while(*ap); + while(i--) { + if (len++ >= buflen) { + return NULL; + } + *rp++ = inv[i]; + } + if (len++ >= buflen) { + return NULL; + } + *rp++ = '.'; + ap++; + } + *--rp = 0; + return buf; +} + +char* Endpoint::get_address() { + if ((_ipAddress[0] == '\0') && (_remote_host.sin_addr.s_addr != 0)) + inet_ntoa_r(_remote_host.sin_addr, _ipAddress, sizeof(_ipAddress)); + return _ipAddress; +} + + +int Endpoint::get_port() { + return ntohs(_remote_host.sin_port); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Socket/Endpoint.h Thu Sep 19 07:55:14 2013 +0000 @@ -0,0 +1,67 @@ +/* Copyright (C) 2012 mbed.org, MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef ENDPOINT_H +#define ENDPOINT_H + +#include "cc3000.h" + +using namespace mbed_cc3000; + +class UDPSocket; + +/** +IP Endpoint (address, port) +*/ +class Endpoint { + friend class UDPSocket; + +public: + /** IP Endpoint (address, port) + */ + Endpoint(void); + + ~Endpoint(void); + + /** Reset the address of this endpoint + */ + void reset_address(void); + + /** Set the address of this endpoint + \param host The endpoint address (it can either be an IP Address or a hostname that will be resolved with DNS). + \param port The endpoint port + \return 0 on success, -1 on failure (when an hostname cannot be resolved by DNS). + */ + int set_address(const char* host, const int port); + + /** Get the IP address of this endpoint + \return The IP address of this endpoint. + */ + char* get_address(void); + + /** Get the port of this endpoint + \return The port of this endpoint + */ + int get_port(void); + +protected: + char _ipAddress[17]; + sockaddr_in _remote_host; + cc3000 *_cc3000_module; +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Socket/Socket.cpp Thu Sep 19 07:55:14 2013 +0000 @@ -0,0 +1,82 @@ +/* Copyright (C) 2012 mbed.org, MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "Socket.h" +#include <cstring> + +Socket::Socket() : _sock_fd(-1), _blocking(true), _timeout(1500) { + _cc3000_module = cc3000::get_instance(); + if (_cc3000_module == NULL) { + error("Socket constructor error: no cc3000 instance available!\r\n"); + } +} + +void Socket::set_blocking(bool blocking, unsigned int timeout) { + _blocking = blocking; + _timeout = timeout; +} + +int Socket::set_option(int level, int optname, const void *optval, socklen_t optlen) { + return _cc3000_module->_socket.set_sockopt(_sock_fd, level, optname, optval, optlen); +} + +int Socket::get_option(int level, int optname, void *optval, socklen_t *optlen) { + return _cc3000_module->_socket.get_sockopt(_sock_fd, level, optname, optval, optlen); +} + +int Socket::select(struct timeval *timeout, bool read, bool write) { + if (_sock_fd < 0 ) { + return -1; + } + + fd_set fdSet; + FD_ZERO(&fdSet); + FD_SET(_sock_fd, &fdSet); + + fd_set* readset = (read ) ? (&fdSet) : (NULL); + fd_set* writeset = (write) ? (&fdSet) : (NULL); + + int ret = _cc3000_module->_socket.select(_sock_fd+1, readset, writeset, NULL, timeout); + return (ret <= 0 || !FD_ISSET(_sock_fd, &fdSet)) ? (-1) : (0); +} + +int Socket::wait_readable(TimeInterval& timeout) { + return select(&timeout._time, true, false); +} + +int Socket::wait_writable(TimeInterval& timeout) { + return select(&timeout._time, false, true); +} + +int Socket::close() { + if (_sock_fd < 0 ) { + return -1; + } + + _cc3000_module->_socket.closesocket(_sock_fd); + return 0; +} + +Socket::~Socket() { + close(); //Don't want to leak +} + +TimeInterval::TimeInterval(unsigned int ms) { + _time.tv_sec = ms / 1000; + _time.tv_usec = (ms - (_time.tv_sec * 1000)) * 1000; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Socket/Socket.h Thu Sep 19 07:55:14 2013 +0000 @@ -0,0 +1,96 @@ +/* Copyright (C) 2012 mbed.org, MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef SOCKET_H_ +#define SOCKET_H_ + +#include "cc3000.h" + +using namespace mbed_cc3000; + +class TimeInterval; + +/** Socket file descriptor and select wrapper + */ +class Socket { +public: + /** Socket + */ + Socket(); + + /** Set blocking or non-blocking mode of the socket and a timeout on + blocking socket operations + \param blocking true for blocking mode, false for non-blocking mode. + \param timeout timeout in ms [Default: (1500)ms]. + */ + void set_blocking(bool blocking, unsigned int timeout=1500); + + /** Set socket options + \param level stack level (see: lwip/sockets.h) + \param optname option ID + \param optval option value + \param socklen_t length of the option value + \return 0 on success, -1 on failure + */ + int set_option(int level, int optname, const void *optval, socklen_t optlen); + + /** Get socket options + \param level stack level (see: lwip/sockets.h) + \param optname option ID + \param optval buffer pointer where to write the option value + \param socklen_t length of the option value + \return 0 on success, -1 on failure + */ + int get_option(int level, int optname, void *optval, socklen_t *optlen); + + + /** Close the socket file descriptor + */ + int close(); + + ~Socket(); + +protected: + int _sock_fd; + + int wait_readable(TimeInterval& timeout); + int wait_writable(TimeInterval& timeout); + + bool _blocking; + int _timeout; + + cc3000 *_cc3000_module; +private: + int select(struct timeval *timeout, bool read, bool write); +}; + +/** Time interval class used to specify timeouts + */ +class TimeInterval { + friend class Socket; + +public: + /** Time Interval + \param ms time interval expressed in milliseconds + */ + TimeInterval(unsigned int ms); + +private: + struct timeval _time; +}; + +#endif /* SOCKET_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Socket/TCPSocketConnection.cpp Thu Sep 19 07:55:14 2013 +0000 @@ -0,0 +1,67 @@ +/* Copyright (C) 2012 mbed.org, MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "TCPSocketConnection.h" +#include <algorithm> + +TCPSocketConnection::TCPSocketConnection() {} + +int TCPSocketConnection::connect(const char* host, const int port) +{ + +} + +bool TCPSocketConnection::is_connected(void) +{ + +} + +int TCPSocketConnection::send(char* data, int length) +{ + +} + +// -1 if unsuccessful, else number of bytes written +int TCPSocketConnection::send_all(char* data, int length) +{ + Timer tmr; + int idx = 0; + tmr.start(); + + while ((tmr.read_ms() < _timeout) || _blocking) { + + idx += wifi->send(data, length); + + if (idx == length) + return idx; + } + return (idx == 0) ? -1 : idx; +} + +// -1 if unsuccessful, else number of bytes received +int TCPSocketConnection::receive(char* data, int length) +{ + +} + + +// -1 if unsuccessful, else number of bytes received +int TCPSocketConnection::receive_all(char* data, int length) +{ + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Socket/TCPSocketConnection.h Thu Sep 19 07:55:14 2013 +0000 @@ -0,0 +1,76 @@ +/* Copyright (C) 2012 mbed.org, MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef TCPSOCKET_H +#define TCPSOCKET_H + +#include "Socket.h" +#include "Endpoint.h" + +/** +TCP socket connection +*/ +class TCPSocketConnection: public Socket, public Endpoint { + +public: + /** TCP socket connection + */ + TCPSocketConnection(); + + /** Connects this TCP socket to the server + \param host The host to connect to. It can either be an IP Address or a hostname that will be resolved with DNS. + \param port The host's port to connect to. + \return 0 on success, -1 on failure. + */ + int connect(const char* host, const int port); + + /** Check if the socket is connected + \return true if connected, false otherwise. + */ + bool is_connected(void); + + /** Send data to the remote host. + \param data The buffer to send to the host. + \param length The length of the buffer to send. + \return the number of written bytes on success (>=0) or -1 on failure + */ + int send(char* data, int length); + + /** Send all the data to the remote host. + \param data The buffer to send to the host. + \param length The length of the buffer to send. + \return the number of written bytes on success (>=0) or -1 on failure + */ + int send_all(char* data, int length); + + /** Receive data from the remote host. + \param data The buffer in which to store the data received from the host. + \param length The maximum length of the buffer. + \return the number of received bytes on success (>=0) or -1 on failure + */ + int receive(char* data, int length); + + /** Receive all the data from the remote host. + \param data The buffer in which to store the data received from the host. + \param length The maximum length of the buffer. + \return the number of received bytes on success (>=0) or -1 on failure + */ + int receive_all(char* data, int length); +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Socket/TCPSocketServer.cpp Thu Sep 19 07:55:14 2013 +0000 @@ -0,0 +1,36 @@ +/* Copyright (C) 2012 mbed.org, MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "TCPSocketServer.h" +#include <string> + +TCPSocketServer::TCPSocketServer() {} + +// Server initialization +int TCPSocketServer::bind(int port) { + +} + +int TCPSocketServer::listen(int backlog) { + +} + + +int TCPSocketServer::accept(TCPSocketConnection& connection) { + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Socket/TCPSocketServer.h Thu Sep 19 07:55:14 2013 +0000 @@ -0,0 +1,52 @@ +/* Copyright (C) 2012 mbed.org, MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef TCPSOCKETSERVER_H +#define TCPSOCKETSERVER_H + +#include "Socket/Socket.h" +#include "TCPSocketConnection.h" + +/** TCP Server. + */ +class TCPSocketServer : public Socket { + public: + /** Instantiate a TCP Server. + */ + TCPSocketServer(); + + /** Bind a socket to a specific port. + \param port The port to listen for incoming connections on. + \return 0 on success, -1 on failure. + */ + int bind(int port); + + /** Start listening for incoming connections. + \param backlog number of pending connections that can be queued up at any + one time [Default: 1]. + \return 0 on success, -1 on failure. + */ + int listen(int backlog=1); + + /** Accept a new connection. + \param connection A TCPSocketConnection instance that will handle the incoming connection. + \return 0 on success, -1 on failure. + */ + int accept(TCPSocketConnection& connection); +}; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Socket/UDPSocket.cpp Thu Sep 19 07:55:14 2013 +0000 @@ -0,0 +1,98 @@ +/* Copyright (C) 2012 mbed.org, MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "UDPSocket.h" + +#include <string> +#include <algorithm> + +UDPSocket::UDPSocket() { + +} + +int UDPSocket::init(void) { + /* open upd socket */ + _sock_fd = _cc3000_module->_socket.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (_sock_fd == -1) { +#if (CC3000_DEBUG == 1) + printf("DEBUG: Failed to create new socket (udp).\n"); +#endif + return 0; + } + + return 1; +} + +// Server initialization +int UDPSocket::bind(int port) { + init(); + + sockaddr_in localHost; + std::memset(&localHost, 0, sizeof(localHost)); + + localHost.sin_family = AF_INET; + localHost.sin_port = htons(port); + localHost.sin_addr.s_addr = htons(0); + + if (_cc3000_module->_socket.bind(_sock_fd, (sockaddr *)&localHost, sizeof(localHost)) != 0) { +#if (CC3000_DEBUG == 1) + printf("DEBUG: Failed to bind a socket (udp). Closing socket.\n"); +#endif + _cc3000_module->_socket.closesocket(_sock_fd); + return -1; + } + return 0; +} + +// -1 if unsuccessful, else number of bytes written +int UDPSocket::sendTo(Endpoint &remote, char *packet, int length) +{ + if (_sock_fd < 0) { + return -1; + } + + if (!_blocking) { + TimeInterval timeout(_timeout); + if (wait_writable(timeout) != 0) + return 0; + } + + return _cc3000_module->_socket.sendto(_sock_fd, packet, length, 0, (sockaddr *)&remote._remote_host, sizeof(remote._remote_host)); +} + +// -1 if unsuccessful, else number of bytes received +int UDPSocket::receiveFrom(Endpoint &remote, char *buffer, int length) +{ + if (_sock_fd < 0) { + return -1; + } + + if (!_blocking) { + TimeInterval timeout(_timeout); + if (wait_readable(timeout) != 0) { + return 0; + } + } + + remote.reset_address(); + socklen_t remote_host_length = sizeof(remote._remote_host); + + return _cc3000_module->_socket.recvfrom(_sock_fd, buffer, length, 0, (sockaddr *)&remote._remote_host, &remote_host_length); +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Socket/UDPSocket.h Thu Sep 19 07:55:14 2013 +0000 @@ -0,0 +1,68 @@ +/* Copyright (C) 2012 mbed.org, MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without restriction, + * including without limitation the rights to use, copy, modify, merge, publish, distribute, + * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef UDPSOCKET_H +#define UDPSOCKET_H + +#include "Endpoint.h" +#include "Socket.h" + +#include <cstdint> + +/** +UDP Socket +*/ +class UDPSocket: public Socket { + +public: + /** Instantiate an UDP Socket. + */ + UDPSocket(); + + /** Init the UDP Client Socket without binding it to any specific port + \return 0 on success, -1 on failure. + */ + int init(void); + + /** Bind a UDP Server Socket to a specific port + \param port The port to listen for incoming connections on + \return 0 on success, -1 on failure. + */ + int bind(int port = -1); + + /** Send a packet to a remote endpoint + \param remote The remote endpoint + \param packet The packet to be sent + \param length The length of the packet to be sent + \return the number of written bytes on success (>=0) or -1 on failure + */ + int sendTo(Endpoint &remote, char *packet, int length); + + /** Receive a packet from a remote endpoint + \param remote The remote endpoint + \param buffer The buffer for storing the incoming packet data. If a packet + is too long to fit in the supplied buffer, excess bytes are discarded + \param length The length of the buffer + \return the number of received bytes on success (>=0) or -1 on failure + */ + int receiveFrom(Endpoint &remote, char *buffer, int length); +}; + +#include "def.h" + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cc3000.cpp Thu Sep 19 07:55:14 2013 +0000 @@ -0,0 +1,477 @@ +/***************************************************************************** +* +* C++ interface/implementation created by Martin Kojtal (0xc0170). Thanks to +* Jim Carver and Frank Vannieuwkerke for their inital cc3000 mbed port and +* provided help. +* +* This version of "host driver" uses CC3000 Host Driver Implementation. Thus +* read the following copyright: +* +* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the +* distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*****************************************************************************/ +#include "cc3000.h" +#include "cc3000_event.h" + +namespace mbed_cc3000 { + +/* TODO this prefix remove? verify */ +static uint8_t cc3000_prefix[] = {'T', 'T', 'T'}; +cc3000 *cc3000::_inst; + +cc3000::cc3000(PinName cc3000_irq, PinName cc3000_en, PinName cc3000_cs, SPI cc3000_spi, IRQn_Type irq_port) + : _event(_simple_link, _hci, _spi, *this), _socket(_simple_link, _hci, _event), _spi(cc3000_irq, cc3000_en, cc3000_cs, cc3000_spi, irq_port, _event, _simple_link), _hci(_spi), + _nvmem(_hci, _event, _simple_link), _netapp(_simple_link, _nvmem, _hci, _event), _wlan(_simple_link, _event, _spi, _hci), _buffer(256) { + /* TODO - pIRQ riorities ?? */ + + _simple_link.set_tx_complete_signal(1); + _status.dhcp = 0; + _status.connected = 0; + _status.socket = 0; + _status.dhcp_configured = 0; + _status.smart_config_complete = 0; + _status.stop_smart_config = 0; + _status.ok_to_shut_down = 0; + + _inst = this; +} + +cc3000::~cc3000() { + +} + +void cc3000::usync_callback(int32_t event_type, uint8_t * data, uint8_t length) { + if (event_type == HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE) + { + _status.smart_config_complete = 1; + _status.stop_smart_config = 1; + } + + if (event_type == HCI_EVNT_WLAN_UNSOL_CONNECT) + { + _status.connected = 1; + } + + if (event_type == HCI_EVNT_WLAN_UNSOL_DISCONNECT) + { + _status.connected = 0; + _status.dhcp = 0; + _status.dhcp_configured = 0; + } + + if (event_type == HCI_EVNT_WLAN_UNSOL_DHCP) + { + if ( *(data + NETAPP_IPCONFIG_MAC_OFFSET) == 0) { + _status.dhcp = 1; + } else { + _status.dhcp = 0; + } + } + + if (event_type == HCI_EVENT_CC3000_CAN_SHUT_DOWN) + { + _status.ok_to_shut_down = 1; + } + + if (event_type == HCI_EVNT_WLAN_ASYNC_PING_REPORT) + { + memcpy(&_ping_report, data, length); + } + + if (event_type == HCI_EVNT_BSD_TCP_CLOSE_WAIT) { + uint8_t socketnum; + socketnum = data[0]; + if (socketnum < MAX_SOCKETS) { + _closed_sockets[socketnum] = true; /* clients socket is closed */ + } + } +} + +void cc3000::start_smart_config(const uint8_t *smart_config_key) { + // Reset all the previous configuration + _wlan.ioctl_set_connection_policy(0, 0, 0); + _wlan.ioctl_del_profile(255); + + //Wait until CC3000 is disconected + while (_status.connected == 1) + { + wait_us(5); + _event.hci_unsolicited_event_handler(); + } + + // Trigger the Smart Config process + + _wlan.smart_config_set_prefix(cc3000_prefix); + // Start the Smart Config process with AES disabled + _wlan.smart_config_start(0); + +#if (CC3000_DEBUG == 1) + printf("DEBUG: Waiting for smartconfig to be completed.\n"); +#endif + // Wait for Smart config finished + while (_status.smart_config_complete == 0) + { + wait_ms(100); + + } +#if (CC3000_DEBUG == 1) + printf("DEBUG: Smartconfig finished.\n"); +#endif +#ifndef CC3000_UNENCRYPTED_SMART_CONFIG + // create new entry for AES encryption key + _nvmem.create_entry(NVMEM_AES128_KEY_FILEID, 16); + // write AES key to NVMEM + _security.aes_write_key((uint8_t *)(&smart_config_key[0])); + // Decrypt configuration information and add profile + _wlan.smart_config_process(); +#endif + + // Configure to connect automatically to the AP retrieved in the + // Smart config process + _wlan.ioctl_set_connection_policy(0, 1, 1); + + // reset the CC3000 + _wlan.stop(); + wait(2); + _wlan.start(0); + wait(2); + + // Mask out all non-required events + _wlan.set_event_mask(HCI_EVNT_WLAN_KEEPALIVE|HCI_EVNT_WLAN_UNSOL_INIT|HCI_EVNT_WLAN_ASYNC_PING_REPORT); +} + +bool cc3000::connect_secure(const uint8_t *ssid, const uint8_t *key, int32_t security_mode) { + uint32_t ret; + + _wlan.disconnect(); + wait_ms(3); + ret = _wlan.connect(security_mode, ssid, strlen((const char *)ssid), 0, (uint8_t *)key, strlen((const char *)key)); + if (ret == 0) { /* TODO static internal cc3000 state 0 to TRUE */ + ret = true; + } else { + ret = false; + } + return ret; +} + +bool cc3000::connect_to_AP(const uint8_t *ssid, const uint8_t *key, int32_t security_mode) { + Timer t; /* TODO static? */ + bool ret = true; + + t.start(); + while (is_connected() == false) { + if (key == 0) { + if (connect_open(ssid)) { + break; + } + } else { +#ifndef CC3000_TINY_DRIVER + if (connect_secure(ssid,key,security_mode)) { + break; + } +#else + return false; /* secure connection not supported with TINY_DRIVER */ +#endif + } + + /* timeout 10 seconds */ + if (t.read_ms() > 10000){ + ret = false; +#if (CC3000_DEBUG == 1) + printf("Connection to AP failed.\n"); +#endif + break; + } + } + + return ret; +} + +void cc3000::start(uint8_t patch) { + _wlan.start(patch); + _wlan.set_event_mask(HCI_EVNT_WLAN_UNSOL_INIT | HCI_EVNT_WLAN_KEEPALIVE); +} + +void cc3000::stop(void) { + _wlan.stop(); +} + +void cc3000::restart(uint8_t patch) { + _wlan.stop(); + wait_ms(500); + _wlan.start(patch); +} + +bool cc3000::connect_open(const uint8_t *ssid) { + uint32_t ret; + + _wlan.disconnect(); + wait_ms(3); +#ifndef CC3000_TINY_DRIVER + ret = _wlan.connect(0,ssid, strlen((const char *)ssid), 0, 0, 0); +#else + ret = _wlan.connect(ssid, strlen((const char *)ssid)); +#endif + if (ret == 0) { + ret = true; + } else { + ret = false; + } + return ret; +} + +bool cc3000::is_connected() { + return _status.connected; +} + +bool cc3000::is_dhcp_configured() { + return _status.dhcp; +} + +bool cc3000::is_smart_confing_completed() { + return _status.smart_config_complete; +} + +void cc3000::get_mac_address(uint8_t address[6]) { + _nvmem.get_mac_address(address); +} + +void cc3000::set_mac_address(uint8_t address[6]) { + _nvmem.set_mac_address(address); +} + +void cc3000::get_user_file_info(uint8_t *info_file, size_t size) { + _nvmem.read( NVMEM_USER_FILE_1_FILEID, size, 0, info_file); +} + +#ifndef CC3000_TINY_DRIVER +bool cc3000::get_ip_config(tNetappIpconfigRetArgs *ip_config) { + if ((_status.dhcp == false) || (_status.connected == false)) { + return false; + } + + _netapp.ipconfig(ip_config); + return true; +} +#endif + +cc3000_client cc3000::create_tcp_client(uint32_t ip_address, uint16_t port) { + sockaddr socket_address = {0}; + int32_t tcp_socket; + + tcp_socket = _socket.socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (tcp_socket == -1) { +#if (CC3000_DEBUG == 1) + printf("DEBUG: Failed to create new socket (tcp).\n"); +#endif + return cc3000_client(*this); + } + + socket_address.family = AF_INET; + socket_address.data[0] = (port & 0xFF00) >> 8; + socket_address.data[1] = (port & 0x00FF); + socket_address.data[2] = ip_address >> 24; + socket_address.data[3] = ip_address >> 16; + socket_address.data[4] = ip_address >> 8; + socket_address.data[5] = ip_address; + + if (_socket.connect(tcp_socket, &socket_address, sizeof(socket_address)) == -1) { +#if (CC3000_DEBUG == 1) + printf("DEBUG: Failed to connect (tcp).\n"); +#endif + _socket.closesocket(tcp_socket); + return cc3000_client(*this); + } + + return cc3000_client(*this, tcp_socket); +} +cc3000_client cc3000::create_udp_client(uint32_t ip_address, uint16_t port) { + sockaddr socket_address = {0}; + int32_t udp_socket; + + udp_socket = _socket.socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (udp_socket == -1) { +#if (CC3000_DEBUG == 1) + printf("DEBUG: Failed to create new socket (udp).\n"); +#endif + return cc3000_client(*this); + } + + socket_address.family = AF_INET; + socket_address.data[0] = (port & 0xFF00) >> 8; + socket_address.data[1] = (port & 0x00FF); + socket_address.data[2] = ip_address >> 24; + socket_address.data[3] = ip_address >> 16; + socket_address.data[4] = ip_address >> 8; + socket_address.data[5] = ip_address; + + if (_socket.connect(udp_socket, &socket_address, sizeof(socket_address)) == -1) { +#if (CC3000_DEBUG == 1) + printf("DEBUG: Failed to connect (udp).\n"); +#endif + _socket.closesocket(udp_socket); + return cc3000_client(*this); + } + + return cc3000_client(*this, udp_socket); +} + +cc3000_server cc3000::create_tcp_server(uint32_t ip_address, uint16_t port) { + sockaddr socket_address = {0}; + int32_t tcp_socket; + + tcp_socket = _socket.socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (tcp_socket == -1) { +#if (CC3000_DEBUG == 1) + printf("Failed to create new socket.\n"); +#endif + return cc3000_server(*this, socket_address); + } + + socket_address.family = AF_INET; + socket_address.data[0] = (port & 0xFF00) >> 8; + socket_address.data[1] = (port & 0x00FF); + socket_address.data[2] = ip_address >> 24; + socket_address.data[3] = ip_address >> 16; + socket_address.data[4] = ip_address >> 8; + socket_address.data[5] = ip_address; + + if (_socket.bind(tcp_socket, &socket_address, sizeof(socket_address)) != 0) { +#if (CC3000_DEBUG == 1) + printf("DEBUG: Failed to bind the new socket.\n"); +#endif + return cc3000_server(*this, socket_address); + } + if (_socket.listen(tcp_socket, 1) != 0) { /* 1 client */ +#if (CC3000_DEBUG == 1) + printf("DEBUG: Failed to listen on the new socket.\n"); +#endif + return cc3000_server(*this, socket_address); + } + + return cc3000_server(*this, socket_address, tcp_socket); +} + +void cc3000::delete_profiles(void) { + tUserFS user_info; + + _wlan.ioctl_set_connection_policy(0, 0, 0); + _wlan.ioctl_del_profile(255); + + user_info.FTC = 0; + set_user_file_info((uint8_t *)&user_info, sizeof(user_info)); +} + +void cc3000::set_user_file_info(uint8_t *info_file, size_t size) { + _nvmem.write( NVMEM_USER_FILE_1_FILEID, size, 0, info_file); +} + +bool cc3000::disconnect(void){ + if (_wlan.disconnect()) { + return false; + } else { + return true; + } +} + +uint32_t cc3000::ping(uint32_t ip, uint8_t attempts, uint16_t timeout, uint8_t size) { + uint32_t reversed_ip = (ip >> 24) | (ip >> 8) & 0xFF00 | (ip << 8) & 0xFF0000 | (ip << 24); + + _ping_report.packets_received = 0; + if (_netapp.ping_send(&reversed_ip, attempts, size, timeout) == -1) { +#if (CC3000_DEBUG == 1) + printf("DEBUG: Failed to send ping.\n"); +#endif + return 0; + } + wait_ms(timeout*attempts*2); + + /* known issue of cc3000 - sent number is send + received */ +#if (CC3000_DEBUG == 1) + printf("DEBUG: Sent: %d \n",_ping_report.packets_sent); + printf("DEBUG: Received: %d \n",_ping_report.packets_received); + printf("DEBUG: Min time: %d \n",_ping_report.min_round_time); + printf("DEBUG: Max time: %d \n",_ping_report.max_round_time); + printf("DEBUG: Avg time: %d \n",_ping_report.avg_round_time); +#endif + + return _ping_report.packets_received; +} + +int32_t cc3000::readable(void) { + return _buffer.available(); +} + +uint8_t cc3000::getc(void) +{ + char c; + + while (!_buffer.available()); + _buffer.dequeue(&c); + return (uint8_t)c; +} + +/* Conversion between uint types and C strings */ +uint8_t* UINT32_TO_STREAM_f (uint8_t *p, uint32_t u32) +{ + *(p)++ = (uint8_t)(u32); + *(p)++ = (uint8_t)((u32) >> 8); + *(p)++ = (uint8_t)((u32) >> 16); + *(p)++ = (uint8_t)((u32) >> 24); + return p; +} + + +uint8_t* UINT16_TO_STREAM_f (uint8_t *p, uint16_t u16) +{ + *(p)++ = (uint8_t)(u16); + *(p)++ = (uint8_t)((u16) >> 8); + return p; +} + + +uint16_t STREAM_TO_UINT16_f(uint8_t *p, uint16_t offset) +{ + return (uint16_t)((uint16_t)((uint16_t) + (*(p + offset + 1)) << 8) + (uint16_t)(*(p + offset))); +} + + +uint32_t STREAM_TO_UINT32_f(uint8_t *p, uint16_t offset) +{ + return (uint32_t)((uint32_t)((uint32_t) + (*(p + offset + 3)) << 24) + (uint32_t)((uint32_t) + (*(p + offset + 2)) << 16) + (uint32_t)((uint32_t) + (*(p + offset + 1)) << 8) + (uint32_t)(*(p + offset))); +} + +} /* end of mbed_cc3000 namespace */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cc3000.h Thu Sep 19 07:55:14 2013 +0000 @@ -0,0 +1,703 @@ +/***************************************************************************** +* +* C++ interface/implementation created by Martin Kojtal (0xc0170). Thanks to +* Jim Carver and Frank Vannieuwkerke for their inital cc3000 mbed port and +* provided help. +* +* This version of "host driver" uses CC3000 Host Driver Implementation. Thus +* read the following copyright: +* +* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the +* distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*****************************************************************************/ +#ifndef CC3000_H +#define CC3000_H + +#include "mbed.h" +#include "cc3000_common.h" +#include "cc3000_spi.h" +#include "cc3000_simplelink.h" +#include "cc3000_netapp.h" +#include "cc3000_nvmem.h" +#include "cc3000_socket.h" + +#define MAX_SOCKETS 4 + +/** Enable debug messages + */ +#define CC3000_DEBUG 1 + +namespace mbed_cc3000 { + +/** User info structure + */ +typedef struct { + uint8_t FTC; // First time config performed + uint8_t PP_version[2]; // Patch Programmer version + uint8_t SERV_PACK[2]; // Service Pack Version + uint8_t DRV_VER[3]; // Driver Version + uint8_t FW_VER[3]; // Firmware Version + uint8_t validCIK; // CIK[] is valid (Client Interface Key) + uint8_t CIK[40]; +} tUserFS; + +/** Function pointers which are not yet implemented + */ +enum FunctionNumber { + FW_PATCHES = 0, + DRIVER_PATCHES = 1, + BOOTLOADER_PATCHES = 2, +}; + +/** CC3000 Simple Link class which contains status of cc3000. + */ +class cc3000_simple_link { +public: + /** ctor - sets magic number in the buffers (overflow mark). + */ + cc3000_simple_link(); + /** dtor + */ + ~cc3000_simple_link(); + /** Returns data received flag. + * \return + * if data have been received. + */ + uint8_t get_data_received_flag(); + /** Set data received flag. + * \param value The value to be set. + */ + void set_data_received_flag(uint8_t value); + /** Returns if tx was completed. + * \return + * true if tx was completed, + * false otherwise. + */ + bool get_tx_complete_signal(); + /** + */ + void set_tx_complete_signal(bool value); + /** + */ + uint8_t *get_received_buffer(); + /** + */ + void set_received_buffer(uint8_t value); + /** + */ + uint8_t *get_transmit_buffer(); + /** + */ + void set_transmit_buffer(uint8_t value); + /** + */ + uint16_t get_number_free_buffers(); + /** + */ + void set_number_free_buffers(uint16_t value); + /** + */ + uint16_t get_buffer_length(); + /** + */ + void set_buffer_length(uint16_t value); + /** + */ + uint16_t get_pending_data(); + /** + */ + void set_pending_data(uint16_t value); + /** + */ + uint16_t get_op_code(); + /** + */ + void set_op_code(uint16_t code); + /** + */ + uint16_t get_released_packets(); + /** + */ + void set_number_of_released_packets(uint16_t value); + /** + */ + uint16_t get_sent_packets(); + /** + */ + void set_sent_packets(uint16_t value); + + int32_t get_transmit_error(); + void set_transmit_error(int32_t value); + + uint16_t get_buffer_size(void); + void set_buffer_size(uint16_t value); + + void *get_func_pointer(FunctionNumber function); + + uint8_t *get_received_data(void); + void set_received_data(uint8_t *pointer); + +private: + uint8_t _data_received_flag; + bool _tx_complete_signal; + uint16_t _rx_event_opcode; + uint16_t _free_buffers; + uint16_t _buffer_length; + uint16_t _buffer_size; + uint16_t _rx_data_pending; + uint16_t _sent_packets; + uint16_t _released_packets; + int32_t _transmit_data_error; + uint8_t *_received_data; + uint8_t _rx_buffer[CC3000_RX_BUFFER_SIZE]; + uint8_t _tx_buffer[CC3000_TX_BUFFER_SIZE]; +private: + int8_t *(* _fFWPatches)(uint32_t *length); + int8_t *(* _fDriverPatches)(uint32_t *length); + int8_t *(* _fBootLoaderPatches)(uint32_t *length); +}; + +/** Forward declaration classes + */ +class cc3000_hci; +class cc3000_nvmem; +class cc3000_spi; +class cc3000; + +/** + */ +class cc3000_event { +public: + cc3000_event(cc3000_simple_link &simplelink, cc3000_hci &hci, cc3000_spi &spi, cc3000 &cc3000); + ~cc3000_event(); + + void hci_unsol_handle_patch_request(uint8_t *event_hdr); + uint8_t *hci_event_handler(void *ret_param, uint8_t *from, uint8_t *fromlen); + int32_t hci_unsol_event_handler(uint8_t *event_hdr); + int32_t hci_unsolicited_event_handler(void); + int32_t get_socket_active_status(int32_t sd); + void set_socket_active_status(int32_t sd, int32_t status); + int32_t hci_event_unsol_flowcontrol_handler(uint8_t *event); + void update_socket_active_status(uint8_t *resp_params); + void simplelink_wait_event(uint16_t op_code, void *ret_param); + void simplelink_wait_data(uint8_t *buffer, uint8_t *from, uint8_t *fromlen); + + void received_handler(uint8_t *buffer); + private: + uint32_t socket_active_status; + cc3000_simple_link &_simple_link; + cc3000_hci &_hci; + cc3000_spi &_spi; + cc3000 &_cc3000; +}; + +class cc3000_netapp { +public: + cc3000_netapp(cc3000_simple_link &simple_link, cc3000_nvmem &nvmem, cc3000_hci &hci, cc3000_event &event); + ~cc3000_netapp(); + int32_t config_mac_adrress(uint8_t *mac); + int32_t dhcp(uint32_t *ip, uint32_t *subnet_mask,uint32_t *default_gateway, uint32_t *dns_server); +#ifndef CC3000_TINY_DRIVER + void ipconfig(tNetappIpconfigRetArgs *ipconfig); + int32_t timeout_values(uint32_t *dhcp, uint32_t *arp,uint32_t *keep_alive, uint32_t *inactivity); + int32_t ping_send(uint32_t *ip, uint32_t ping_attempts, uint32_t ping_size, uint32_t ping_timeout); + void ping_report(); + int32_t ping_stop(); + int32_t arp_flush(); +#endif +private: + cc3000_simple_link &_simple_link; + cc3000_nvmem &_nvmem; + cc3000_hci &_hci; + cc3000_event &_event; +}; + +#ifndef CC3000_UNENCRYPTED_SMART_CONFIG +class cc3000_security { +public: + void expandKey(uint8_t *expanded_key, uint8_t *key); + uint8_t galois_mul2(uint8_t value); + void aes_encr(uint8_t *state, uint8_t *expanded_key); + void aes_decr(uint8_t *state, uint8_t *expanded_key); + void aes_encrypt(uint8_t *state, uint8_t *key); + void aes_decrypt(uint8_t *state, uint8_t *key); + int32_t aes_read_key(uint8_t *key); + int32_t aes_write_key(uint8_t *key); +private: + uint8_t _expanded_key[176]; +}; +#endif + +class cc3000_socket { +public: + cc3000_socket(cc3000_simple_link &simplelink, cc3000_hci &hci, cc3000_event &event); + ~cc3000_socket(); + int32_t HostFlowControlConsumeBuff(int32_t sd); + int32_t socket(int32_t domain, int32_t type, int32_t protocol); + int32_t closesocket(int32_t sd); + int32_t accept(int32_t sd, sockaddr *addr, socklen_t *addrlen); + int32_t bind(int32_t sd, const sockaddr *addr, int32_t addrlen); + int32_t listen(int32_t sd, int32_t backlog); +#ifndef CC3000_TINY_DRIVER + int32_t get_host_by_name(uint8_t * hostname, uint16_t name_length, uint32_t* out_ip_addr); + int32_t set_sockopt(int32_t sd, int32_t level, int32_t optname, const void *optval, socklen_t optlen); +#endif + int32_t connect(int32_t sd, const sockaddr *addr, int32_t addrlen); + int32_t select(int32_t nfds, fd_set *readsds, fd_set *writesds, fd_set *exceptsds, struct timeval *timeout); + int32_t get_sockopt (int32_t sd, int32_t level, int32_t optname, void *optval, socklen_t *optlen); + int32_t simple_link_recv(int32_t sd, void *buf, int32_t len, int32_t flags, sockaddr *from, socklen_t *fromlen, int32_t opcode); + int32_t recv(int32_t sd, void *buf, int32_t len, int32_t flags); + int32_t recvfrom(int32_t sd, void *buf, int32_t len, int32_t flags, sockaddr *from, socklen_t *fromlen); + int32_t simple_link_send(int32_t sd, const void *buf, int32_t len, int32_t flags, const sockaddr *to, int32_t tolen, int32_t opcode); + int32_t send(int32_t sd, const void *buf, int32_t len, int32_t flags); + int32_t sendto(int32_t sd, const void *buf, int32_t len, int32_t flags, const sockaddr *to, socklen_t tolen); + int32_t mdns_advertiser(uint16_t mdns_enabled, uint8_t * device_service_name, uint16_t device_service_name_length); +private: + cc3000_simple_link &_simple_link; + cc3000_hci &_hci; + cc3000_event &_event; +}; + +/** SPI communication class + */ +class cc3000_spi { +public: + /** ctor + */ + cc3000_spi(PinName cc3000_irq, PinName cc3000_en, PinName cc3000_cs, SPI cc3000_spi, IRQn_Type irq_port, cc3000_event &event, cc3000_simple_link &simple_link); + /** dtor + */ + ~cc3000_spi(); + /** Close SPI - disables IRQ and set received buffer to 0 + * \param none + * \return none + */ + void close(); + /** + * \param none + * \return none + */ + void open(); + /** + * \param buffer + * \param length + * \return none + */ + uint32_t first_write(uint8_t *buffer, uint16_t length); + /** + */ + uint32_t write(uint8_t *buffer, uint16_t length); + /** + */ + void write_synchronous(uint8_t *data, uint16_t size); + /** + */ + void read_synchronous(uint8_t *data, uint16_t size); + /** + */ + uint32_t read_data_cont(); + /** + */ + void wlan_irq_enable(); + /** + */ + void wlan_irq_disable(); + /** + */ + void wlan_irq_set(uint8_t value); + /** + */ + uint32_t wlan_irq_read(); + /** + */ + void WLAN_IRQHandler(); + /** + */ + void write_wlan_en(uint8_t value); +private: + tSpiInfo _spi_info; + InterruptIn _wlan_irq; + DigitalOut _wlan_en; + DigitalOut _wlan_cs; + SPI _wlan_spi; + IRQn_Type _irq_port; + pFunctionPointer_t _function_pointer; + cc3000_event &_event; + cc3000_simple_link &_simple_link; +}; + +class cc3000_hci { +public: + cc3000_hci(cc3000_spi &spi); + ~cc3000_hci(); + uint16_t command_send(uint16_t op_code, uint8_t *buffer, uint8_t length); + uint32_t data_send(uint8_t op_code, uint8_t *args, uint16_t arg_length, + uint16_t data_length, const uint8_t *tail, uint16_t tail_length); + void data_command_send(uint16_t op_code, uint8_t *buffer, uint8_t arg_length, + uint16_t data_length); + void patch_send(uint8_t op_code, uint8_t *buffer, uint8_t *patch, uint16_t data_length); +private: + cc3000_spi &_spi; +}; + +class cc3000_nvmem { +public: + cc3000_nvmem(cc3000_hci &hci, cc3000_event &_event,cc3000_simple_link &simple_link); + ~cc3000_nvmem(); + int32_t read(uint32_t file_id, uint32_t length, uint32_t offset, uint8_t *buff); + int32_t write(uint32_t file_id, uint32_t length, uint32_t entry_offset, uint8_t *buff); + uint8_t set_mac_address(uint8_t *mac); + uint8_t get_mac_address(uint8_t *mac); + uint8_t write_patch(uint32_t file_id, uint32_t length, const uint8_t *data); + int32_t create_entry(uint32_t file_id, uint32_t new_len); +#ifndef CC3000_TINY_DRIVER + uint8_t read_sp_version(uint8_t* patch_ver); +#endif +private: + cc3000_hci &_hci; + cc3000_event &_event; + cc3000_simple_link &_simple_link; +}; + +class cc3000_wlan { +public: + cc3000_wlan(cc3000_simple_link &simple_link, cc3000_event &event, cc3000_spi &spi, cc3000_hci &hci); + ~cc3000_wlan(); + /** Send SIMPLE LINK START to cc3000 + * \param patches_available_host Flag to indicate if patches are available + * \return none + */ + void simpleLink_init_start(uint16_t patches_available_host); + /** Start wlan device. Blocking call until init is completed + * \param patches_available_host Flag to indicate if patches are available + * \return none + */ + void start(uint16_t patches_available_host); + /** Stop wlan device + * \param none + * \return none + */ + void stop(void); +#ifndef CC3000_TINY_DRIVER + int32_t connect(uint32_t sec_type, const uint8_t *ssid, int32_t ssid_length, uint8_t *b_ssid, uint8_t *key, int32_t key_len); + int32_t add_profile(uint32_t sec_type, uint8_t* ssid, uint32_t ssid_length, uint8_t *b_ssid, uint32_t priority, uint32_t pairwise_cipher_or_tx_key_len, uint32_t group_cipher_tx_key_index, + uint32_t key_mgmt, uint8_t* pf_or_key, uint32_t pass_phrase_length); + int32_t ioctl_get_scan_results(uint32_t scan_timeout, uint8_t *results); + int32_t ioctl_set_scan_params(uint32_t enable, uint32_t min_dwell_time, uint32_t max_dwell_time, uint32_t num_probe_requests, + uint32_t channel_mask, int32_t rssi_threshold, uint32_t snr_threshold, uint32_t default_tx_power, uint32_t *interval_list); + int32_t ioctl_statusget(void); +#else + int32_t connect(const uint8_t *ssid, int32_t ssid_length); + int32_t add_profile(uint32_t sec_type, uint8_t *ssid, uint32_t ssid_length, uint8_t *b_ssid, uint32_t priority, + uint32_t pairwise_cipher_or_tx_key_len, uint32_t group_cipher_tx_key_index, uint32_t key_mgmt, + uint8_t* pf_or_key, uint32_t pass_phrase_length); +#endif +#ifndef CC3000_UNENCRYPTED_SMART_CONFIG + int32_t smart_config_process(void); +#endif + int32_t disconnect(); + int32_t ioctl_set_connection_policy(uint32_t should_connect_to_open_ap, uint32_t use_fast_connect, uint32_t use_profiles); + int32_t ioctl_del_profile(uint32_t index); + int32_t set_event_mask(uint32_t mask); + int32_t smart_config_start(uint32_t encrypted_flag); + int32_t smart_config_stop(void); + int32_t smart_config_set_prefix(uint8_t *new_prefix); +private: + cc3000_simple_link &_simple_link; + cc3000_event &_event; + cc3000_spi &_spi; + cc3000_hci &_hci; +}; + +/** Client TCP/UDP class - TODO - not complete client + */ +class cc3000_client { +public: + /** + */ + cc3000_client(cc3000 &cc3000_ref); + /** + */ + cc3000_client(cc3000 &cc3000_ref, int16_t socket); + /** + */ + bool connected(void); + /** + */ + int16_t write(const void *buffer, uint16_t length, uint32_t flags); + /** + */ + int16_t read(void *buffer, uint16_t length, uint32_t flags); + /** + */ + void close(void); + +private: + int16_t _current_socket; + cc3000 &_cc3000; +}; + +/** Server TCP/UDP + */ +class cc3000_server { +public: + /** ctor (server was not created successfully) + */ + cc3000_server(cc3000 &cc3000_ref, sockaddr socket_add); + /** ctor + */ + cc3000_server(cc3000 &cc3000_ref, sockaddr socket_add, int16_t socket); + /** Blocking accept + */ + int32_t accept(void); + /** + */ + int32_t receive(void *buffer, uint16_t length, uint32_t flags); + /** + */ + int32_t send(void *buffer, uint16_t length, uint32_t flags); + /** + */ + void bind(void); + /** + */ + void listen(uint32_t backlog); + /** + */ + void close(void); +private: + int16_t _current_socket; + sockaddr _socket_address; + cc3000 &_cc3000; +}; + +/** The main class of entire cc3000 implementation + */ +class cc3000 { +public: + typedef struct { + bool dhcp; + bool connected; + uint8_t socket; + bool smart_config_complete; + bool stop_smart_config; + bool dhcp_configured; + bool ok_to_shut_down; + } tStatus; + /** ctor for cc3000 class. + * \param cc3000_irq IRQ pin + * \param cc3000_en Enable pin + * \param cc3000_cs Chip select pin + * \param cc3000_spi SPI interface + * \param irq_port IRQ pin's port + */ + cc3000(PinName cc3000_irq, PinName cc3000_en, PinName cc3000_cs, SPI cc3000_spi, IRQn_Type irq_port); + /** dtor + */ + ~cc3000(); + /** Initiate cc3000. It starts the wlan communication and deletes profiles. + * \param patch Patch + */ + void start(uint8_t patch); + /** Stops the wlan communication. + */ + void stop(); + /** Restarts the wlan communication. + */ + void restart(uint8_t patch); + /** Disconnect wlan device + * + */ + bool disconnect(void); + /** Callback which is called from the event class. This updates status of cc3000. + * \param event_type Type of the event + * \param data Pointer to data + * \param length Length of data + * \return none + */ + void usync_callback(int32_t event_type, uint8_t *data, uint8_t length); + /** Connect to SSID (open/secured) with timeout (10ms). + * \param ssid SSID name + * \param key Security key (if key = 0, open connection) + * \param security_mode Security mode + * \return true if connection was established, false otherwise. + */ + bool connect_to_AP(const uint8_t *ssid, const uint8_t *key, int32_t security_mode); + /** Connect to SSID which is secured + * \param ssid SSID name + * \param key Security key + * \param security_mode Security mode + * \return true if connection was established, false otherwise. + */ + bool connect_secure(const uint8_t *ssid, const uint8_t *key, int32_t security_mode); + /** Connect to SSID which is open (no security) + * \param ssid SSID name + * \return true if connection was established, false otherwise. + */ + bool connect_open(const uint8_t *ssid); + /** Status of the cc3000 connection. + * \return true if it's connected, false otherwise. + */ + bool is_connected(); + /** Status of DHCP. + * \param none + * \return true if DCHP is configured, false otherwise. + */ + bool is_dhcp_configured(); + /** Status of smart confing completation. + * \param none + * \return smart config was set, false otherwise. + */ + bool is_smart_confing_completed(); + /** Return the cc3000's mac address. + * \param address Retreived mac address. + * \return none + */ + void get_mac_address(uint8_t address[6]); + /** Set the cc3000's mac address + * \param address Mac address to be set + * \return none + */ + void set_mac_address(uint8_t address[6]); + /** Get user file info + * \param info_file Pointer where info will be stored + * \param size Available size + * \return none + */ + void get_user_file_info(uint8_t *info_file, size_t size); + /** Set user filo info + * \param info_file Pointer to user's info + * \return none + */ + void set_user_file_info(uint8_t *info_file, size_t size); + /** Start smart config + * \param smart_config_key Pointer to smart config key + * \return none + */ + void start_smart_config(const uint8_t *smart_config_key); /* TODO enable AES ? */ +#ifndef CC3000_TINY_DRIVER + /** Return ip configuration + * \param ip_config Pointer to ipconfig data + * \return true if it's connected and info was retrieved, false otherwise. + */ + bool get_ip_config(tNetappIpconfigRetArgs *ip_config); +#endif + /** Creates tcp client + * \param ip_address Client's IP address + * \param port Client's PORT + * \return client with socket != -1 + */ + cc3000_client create_tcp_client(uint32_t ip_address, uint16_t port); + /** Creates tcp server + * \param ip_address Server's IP address + * \param port Server's PORT + * \return server with socket != -1 + */ + cc3000_server create_tcp_server(uint32_t ip_address, uint16_t port); + /** Creates udp client + * \param ip_address Server's IP address + * \param port Server's PORT + * \return client with socket != -1 + */ + cc3000_client create_udp_client(uint32_t ip_address, uint16_t port); + /** Delete all stored profiles + * \param none + * \return none + */ + void delete_profiles(void); + /** + * + */ + uint32_t ping(uint32_t ip, uint8_t attempts, uint16_t timeout, uint8_t size); + + static cc3000 *get_instance() { + return _inst; + } + + int32_t readable(void); + uint8_t getc(void); +public: + cc3000_simple_link _simple_link; + cc3000_event _event; +#ifndef CC3000_UNENCRYPTED_SMART_CONFIG + cc3000_security _security; +#endif + cc3000_socket _socket; + cc3000_spi _spi; + cc3000_hci _hci; + cc3000_nvmem _nvmem; + cc3000_netapp _netapp; + cc3000_wlan _wlan; +protected: + static cc3000 *_inst; + CircBuffer<char> _buffer; +private: + tStatus _status; + netapp_pingreport_args_t _ping_report; + bool _closed_sockets[MAX_SOCKETS]; +}; + +/** +* Copy 32 bit to stream while converting to little endian format. +* @param p pointer to the new stream +* @param u32 pointer to the 32 bit +* @return pointer to the new stream +*/ +uint8_t *UINT32_TO_STREAM_f (uint8_t *p, uint32_t u32); + +/** +* Copy 16 bit to stream while converting to little endian format. +* @param p pointer to the new stream +* @param u32 pointer to the 16 bit +* @return pointer to the new stream +*/ +uint8_t *UINT16_TO_STREAM_f (uint8_t *p, uint16_t u16); + +/** +* Copy received stream to 16 bit in little endian format. +* @param p pointer to the stream +* @param offset offset in the stream +* @return pointer to the new 16 bit +*/ +uint16_t STREAM_TO_UINT16_f(uint8_t* p, uint16_t offset); + +/** +* Copy received stream to 32 bit in little endian format. +* @param p pointer to the stream +* @param offset offset in the stream +* @return pointer to the new 32 bit +*/ +uint32_t STREAM_TO_UINT32_f(uint8_t* p, uint16_t offset); + +} /* end of mbed_cc3000 namespace */ + + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cc3000_client.cpp Thu Sep 19 07:55:14 2013 +0000 @@ -0,0 +1,72 @@ +/***************************************************************************** +* +* C++ interface/implementation created by Martin Kojtal (0xc0170). Thanks to +* Jim Carver and Frank Vannieuwkerke for their inital cc3000 mbed port and +* provided help. +* +* This version of "host driver" uses CC3000 Host Driver Implementation. Thus +* read the following copyright: +* +* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the +* distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*****************************************************************************/ +#include "cc3000.h" + +namespace mbed_cc3000 { + + +cc3000_client::cc3000_client(cc3000 &cc3000_ref) : _cc3000(cc3000_ref) { + _current_socket = -1; +} + +cc3000_client::cc3000_client(cc3000 &cc3000_ref, int16_t socket) : _cc3000(cc3000_ref) { + _current_socket = socket; +} + +bool cc3000_client::connected(void) { + if (_current_socket < 0) { + return false; + } + + return true; +} + +int16_t cc3000_client::write(const void *buffer, uint16_t length, uint32_t flags = 0) { + return _cc3000._socket.send(_current_socket, buffer, length, flags); +} + +int16_t cc3000_client::read(void *buffer, uint16_t length, uint32_t flags) +{ + return _cc3000._socket.recv(_current_socket, buffer, length, flags); + +} + +} /* end of mbed_cc3000 namespace */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cc3000_event.cpp Thu Sep 19 07:55:14 2013 +0000 @@ -0,0 +1,585 @@ +/***************************************************************************** +* +* C++ interface/implementation created by Martin Kojtal (0xc0170). Thanks to +* Jim Carver and Frank Vannieuwkerke for their inital cc3000 mbed port and +* provided help. +* +* This version of "host driver" uses CC3000 Host Driver Implementation. Thus +* read the following copyright: +* +* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the +* distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*****************************************************************************/ +#include "cc3000.h" +#include "cc3000_event.h" +#include "cc3000_netapp.h" + +namespace mbed_cc3000 { + +cc3000_event::cc3000_event(cc3000_simple_link &simplelink, cc3000_hci &hci, cc3000_spi &spi, cc3000 &cc3000) + : socket_active_status(SOCKET_STATUS_INIT_VAL), _simple_link(simplelink), _hci(hci), _spi(spi), _cc3000(cc3000) { + +} + +cc3000_event::~cc3000_event() { + +} + +/* TODO removed buffer, set it in init */ +void cc3000_event::received_handler(uint8_t *buffer) { + _simple_link.set_data_received_flag(1); + _simple_link.set_received_data(buffer); + + hci_unsolicited_event_handler(); +} + +void cc3000_event::hci_unsol_handle_patch_request(uint8_t *event_hdr) { + uint8_t *params = (uint8_t *)(event_hdr) + HCI_EVENT_HEADER_SIZE; + uint32_t length = 0; + uint8_t *patch; + + switch (*params) + { + case HCI_EVENT_PATCHES_DRV_REQ: + { + tDriverPatches func_pointer = (tDriverPatches)_simple_link.get_func_pointer(DRIVER_PATCHES); + if (func_pointer) + { + patch = func_pointer(&length); + if (patch) + { + _hci.patch_send(HCI_EVENT_PATCHES_DRV_REQ, _simple_link.get_transmit_buffer(), patch, length); + return; + } + } + + // Send 0 length Patches response event + _hci.patch_send(HCI_EVENT_PATCHES_DRV_REQ, _simple_link.get_transmit_buffer(), 0, 0); + break; + } + case HCI_EVENT_PATCHES_FW_REQ: + { + tFWPatches func_pointer = (tFWPatches)_simple_link.get_func_pointer(FW_PATCHES); + if (func_pointer) + { + patch = func_pointer(&length); + // Build and send a patch + if (patch) + { + _hci.patch_send(HCI_EVENT_PATCHES_FW_REQ, _simple_link.get_transmit_buffer(), patch, length); + return; + } + } + // Send 0 length Patches response event + _hci.patch_send(HCI_EVENT_PATCHES_FW_REQ, _simple_link.get_transmit_buffer(), 0, 0); + break; + } + case HCI_EVENT_PATCHES_BOOTLOAD_REQ: + { + tBootLoaderPatches func_pointer = (tBootLoaderPatches)_simple_link.get_func_pointer(BOOTLOADER_PATCHES); + if (func_pointer) + { + patch = func_pointer(&length); + if (patch) + { + _hci.patch_send(HCI_EVENT_PATCHES_BOOTLOAD_REQ, _simple_link.get_transmit_buffer(), patch, length); + return; + } + } + // Send 0 length Patches response event + _hci.patch_send(HCI_EVENT_PATCHES_BOOTLOAD_REQ, _simple_link.get_transmit_buffer(), 0, 0); + break; + } + } +} + +uint8_t *cc3000_event::hci_event_handler(void *ret_param, uint8_t *from, uint8_t *fromlen) { + uint8_t *received_data, argument_size; + uint16_t length; + uint8_t *pucReceivedParams; + uint16_t received_op_code = 0; + uint32_t return_value; + uint8_t * RecvParams; + uint8_t *RetParams; + + while (1) + { + if (_simple_link.get_data_received_flag() != 0) + { + received_data = _simple_link.get_received_data(); + if (*received_data == HCI_TYPE_EVNT) + { + // Event Received + STREAM_TO_UINT16((uint8_t *)received_data, HCI_EVENT_OPCODE_OFFSET,received_op_code); + pucReceivedParams = received_data + HCI_EVENT_HEADER_SIZE; + RecvParams = pucReceivedParams; + RetParams = (uint8_t *)ret_param; + + // unsolicited event received - finish handling + if (hci_unsol_event_handler((uint8_t *)received_data) == 0) + { + STREAM_TO_UINT8(received_data, HCI_DATA_LENGTH_OFFSET, length); + + switch(received_op_code) + { + case HCI_CMND_READ_BUFFER_SIZE: + { + uint16_t temp = _simple_link.get_number_free_buffers(); + STREAM_TO_UINT8((uint8_t *)pucReceivedParams, 0, temp); + _simple_link.set_number_free_buffers(temp); + + temp = _simple_link.get_buffer_length(); + STREAM_TO_UINT16((uint8_t *)pucReceivedParams, 1, temp); + _simple_link.set_buffer_length(temp); + } + break; + + case HCI_CMND_WLAN_CONFIGURE_PATCH: + case HCI_NETAPP_DHCP: + case HCI_NETAPP_PING_SEND: + case HCI_NETAPP_PING_STOP: + case HCI_NETAPP_ARP_FLUSH: + case HCI_NETAPP_SET_DEBUG_LEVEL: + case HCI_NETAPP_SET_TIMERS: + case HCI_EVNT_NVMEM_READ: + case HCI_EVNT_NVMEM_CREATE_ENTRY: + case HCI_CMND_NVMEM_WRITE_PATCH: + case HCI_NETAPP_PING_REPORT: + case HCI_EVNT_MDNS_ADVERTISE: + + STREAM_TO_UINT8(received_data, HCI_EVENT_STATUS_OFFSET, *(uint8_t *)ret_param); + break; + + case HCI_CMND_SETSOCKOPT: + case HCI_CMND_WLAN_CONNECT: + case HCI_CMND_WLAN_IOCTL_STATUSGET: + case HCI_EVNT_WLAN_IOCTL_ADD_PROFILE: + case HCI_CMND_WLAN_IOCTL_DEL_PROFILE: + case HCI_CMND_WLAN_IOCTL_SET_CONNECTION_POLICY: + case HCI_CMND_WLAN_IOCTL_SET_SCANPARAM: + case HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_START: + case HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_STOP: + case HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_SET_PREFIX: + case HCI_CMND_EVENT_MASK: + case HCI_EVNT_WLAN_DISCONNECT: + case HCI_EVNT_SOCKET: + case HCI_EVNT_BIND: + case HCI_CMND_LISTEN: + case HCI_EVNT_CLOSE_SOCKET: + case HCI_EVNT_CONNECT: + case HCI_EVNT_NVMEM_WRITE: + + STREAM_TO_UINT32((uint8_t *)pucReceivedParams,0, *(uint32_t *)ret_param); + break; + + case HCI_EVNT_READ_SP_VERSION: + + STREAM_TO_UINT8(received_data, HCI_EVENT_STATUS_OFFSET, *(uint8_t *)ret_param); + ret_param = ((uint8_t *)ret_param) + 1; + STREAM_TO_UINT32((uint8_t *)pucReceivedParams, 0, return_value); + UINT32_TO_STREAM((uint8_t *)ret_param, return_value); + break; + + case HCI_EVNT_BSD_GETHOSTBYNAME: + + STREAM_TO_UINT32((uint8_t *)pucReceivedParams,GET_HOST_BY_NAME_RETVAL_OFFSET,*(uint32_t *)ret_param); + ret_param = ((uint8_t *)ret_param) + 4; + STREAM_TO_UINT32((uint8_t *)pucReceivedParams,GET_HOST_BY_NAME_ADDR_OFFSET,*(uint32_t *)ret_param); + break; + + case HCI_EVNT_ACCEPT: + { + STREAM_TO_UINT32((uint8_t *)pucReceivedParams,ACCEPT_SD_OFFSET,*(uint32_t *)ret_param); + ret_param = ((uint8_t *)ret_param) + 4; + STREAM_TO_UINT32((uint8_t *)pucReceivedParams,ACCEPT_RETURN_STATUS_OFFSET,*(uint32_t *)ret_param); + ret_param = ((uint8_t *)ret_param) + 4; + + //This argument returns in network order + memcpy((uint8_t *)ret_param, pucReceivedParams + ACCEPT_ADDRESS__OFFSET, sizeof(sockaddr)); + break; + } + + case HCI_EVNT_RECV: + case HCI_EVNT_RECVFROM: + { + STREAM_TO_UINT32((uint8_t *)pucReceivedParams,SL_RECEIVE_SD_OFFSET ,*(uint32_t *)ret_param); + ret_param = ((uint8_t *)ret_param) + 4; + STREAM_TO_UINT32((uint8_t *)pucReceivedParams,SL_RECEIVE_NUM_BYTES_OFFSET,*(uint32_t *)ret_param); + ret_param = ((uint8_t *)ret_param) + 4; + STREAM_TO_UINT32((uint8_t *)pucReceivedParams,SL_RECEIVE__FLAGS__OFFSET,*(uint32_t *)ret_param); + + if(((tBsdReadReturnParams *)ret_param)->iNumberOfBytes == ERROR_SOCKET_INACTIVE) + { + set_socket_active_status(((tBsdReadReturnParams *)ret_param)->iSocketDescriptor,SOCKET_STATUS_INACTIVE); + } + break; + } + + case HCI_EVNT_SEND: + case HCI_EVNT_SENDTO: + { + STREAM_TO_UINT32((uint8_t *)pucReceivedParams,SL_RECEIVE_SD_OFFSET ,*(uint32_t *)ret_param); + ret_param = ((uint8_t *)ret_param) + 4; + STREAM_TO_UINT32((uint8_t *)pucReceivedParams,SL_RECEIVE_NUM_BYTES_OFFSET,*(uint32_t *)ret_param); + ret_param = ((uint8_t *)ret_param) + 4; + + break; + } + + case HCI_EVNT_SELECT: + { + STREAM_TO_UINT32((uint8_t *)pucReceivedParams,SELECT_STATUS_OFFSET,*(uint32_t *)ret_param); + ret_param = ((uint8_t *)ret_param) + 4; + STREAM_TO_UINT32((uint8_t *)pucReceivedParams,SELECT_READFD_OFFSET,*(uint32_t *)ret_param); + ret_param = ((uint8_t *)ret_param) + 4; + STREAM_TO_UINT32((uint8_t *)pucReceivedParams,SELECT_WRITEFD_OFFSET,*(uint32_t *)ret_param); + ret_param = ((uint8_t *)ret_param) + 4; + STREAM_TO_UINT32((uint8_t *)pucReceivedParams,SELECT_EXFD_OFFSET,*(uint32_t *)ret_param); + break; + } + + case HCI_CMND_GETSOCKOPT: + + STREAM_TO_UINT8(received_data, HCI_EVENT_STATUS_OFFSET,((tBsdGetSockOptReturnParams *)ret_param)->iStatus); + //This argument returns in network order + memcpy((uint8_t *)ret_param, pucReceivedParams, 4); + break; + + case HCI_CMND_WLAN_IOCTL_GET_SCAN_RESULTS: + + STREAM_TO_UINT32((uint8_t *)pucReceivedParams,GET_SCAN_RESULTS_TABlE_COUNT_OFFSET,*(uint32_t *)ret_param); + ret_param = ((uint8_t *)ret_param) + 4; + STREAM_TO_UINT32((uint8_t *)pucReceivedParams,GET_SCAN_RESULTS_SCANRESULT_STATUS_OFFSET,*(uint32_t *)ret_param); + ret_param = ((uint8_t *)ret_param) + 4; + STREAM_TO_UINT16((uint8_t *)pucReceivedParams,GET_SCAN_RESULTS_ISVALID_TO_SSIDLEN_OFFSET,*(uint32_t *)ret_param); + ret_param = ((uint8_t *)ret_param) + 2; + STREAM_TO_UINT16((uint8_t *)pucReceivedParams,GET_SCAN_RESULTS_FRAME_TIME_OFFSET,*(uint32_t *)ret_param); + ret_param = ((uint8_t *)ret_param) + 2; + memcpy((uint8_t *)ret_param, (uint8_t *)(pucReceivedParams + GET_SCAN_RESULTS_FRAME_TIME_OFFSET + 2), GET_SCAN_RESULTS_SSID_MAC_LENGTH); + break; + + case HCI_CMND_SIMPLE_LINK_START: + break; + + case HCI_NETAPP_IPCONFIG: + + //Read IP address + STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_IP_LENGTH); + RecvParams += 4; + + //Read subnet + STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_IP_LENGTH); + RecvParams += 4; + + //Read default GW + STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_IP_LENGTH); + RecvParams += 4; + + //Read DHCP server + STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_IP_LENGTH); + RecvParams += 4; + + //Read DNS server + STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_IP_LENGTH); + RecvParams += 4; + + //Read Mac address + STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_MAC_LENGTH); + RecvParams += 6; + + //Read SSID + STREAM_TO_STREAM(RecvParams,RetParams,NETAPP_IPCONFIG_SSID_LENGTH); + + } + } + if (received_op_code == _simple_link.get_op_code()) + { + _simple_link.set_op_code(0); + } + } + else + { + pucReceivedParams = received_data; + STREAM_TO_UINT8((uint8_t *)received_data, HCI_PACKET_ARGSIZE_OFFSET, argument_size); + + STREAM_TO_UINT16((uint8_t *)received_data, HCI_PACKET_LENGTH_OFFSET, length); + + // Data received: note that the only case where from and from length + // are not null is in recv from, so fill the args accordingly + if (from) + { + STREAM_TO_UINT32((uint8_t *)(received_data + HCI_DATA_HEADER_SIZE), BSD_RECV_FROM_FROMLEN_OFFSET, *(uint32_t *)fromlen); + memcpy(from, (received_data + HCI_DATA_HEADER_SIZE + BSD_RECV_FROM_FROM_OFFSET) ,*fromlen); + } + + memcpy(ret_param, pucReceivedParams + HCI_DATA_HEADER_SIZE + argument_size, length - argument_size); + + _simple_link.set_pending_data(0); + } + + _simple_link.set_data_received_flag(0); + + //tWlanInterruptEnable func_pointer = (tWlanInterruptEnable)_simple_link.get_func_pointer(WLAN_INTERRUPT_ENABLE); + //func_pointer(); + _spi.wlan_irq_enable(); + + // Since we are going to TX - we need to handle this event after the ResumeSPi since we need interrupts + if ((*received_data == HCI_TYPE_EVNT) && (received_op_code == HCI_EVNT_PATCHES_REQ)) + { + hci_unsol_handle_patch_request((uint8_t *)received_data); + } + if ((_simple_link.get_op_code() == 0) && (_simple_link.get_pending_data() == 0)) + { + return NULL; + } + } + } +} + +int32_t cc3000_event::hci_unsol_event_handler(uint8_t *event_hdr) { + uint8_t *data = NULL; + int32_t event_type; + uint32_t number_of_released_packets; + uint32_t number_of_sent_packets; + + STREAM_TO_UINT16(event_hdr, HCI_EVENT_OPCODE_OFFSET,event_type); + + if (event_type & HCI_EVNT_UNSOL_BASE) { + switch(event_type) { + case HCI_EVNT_DATA_UNSOL_FREE_BUFF: + { + hci_event_unsol_flowcontrol_handler(event_hdr); + + number_of_released_packets = _simple_link.get_released_packets(); + number_of_sent_packets = _simple_link.get_sent_packets(); + + if (number_of_released_packets == number_of_sent_packets) + { + if (_simple_link.get_tx_complete_signal()) + { + //tWlanCB func_pointer = (tWlanCB)_simple_link.get_func_pointer(WLAN_CB); + _cc3000.usync_callback(HCI_EVENT_CC3000_CAN_SHUT_DOWN, NULL, 0); + } + } + return 1; + } + } + } + + if (event_type & HCI_EVNT_WLAN_UNSOL_BASE) { + switch(event_type) { + case HCI_EVNT_WLAN_KEEPALIVE: + case HCI_EVNT_WLAN_UNSOL_CONNECT: + case HCI_EVNT_WLAN_UNSOL_DISCONNECT: + case HCI_EVNT_WLAN_UNSOL_INIT: + case HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE: + // { + // tWlanCB func_pointer = (tWlanCB)_simple_link.get_func_pointer(WLAN_CB); + // if( func_pointer ) + // { + // func_pointer(event_type, 0, 0); + // } + _cc3000.usync_callback(event_type, 0, 0); + break; + // } + case HCI_EVNT_WLAN_UNSOL_DHCP: + { + uint8_t params[NETAPP_IPCONFIG_MAC_OFFSET + 1]; // extra byte is for the status + uint8_t *recParams = params; + data = (uint8_t *)(event_hdr) + HCI_EVENT_HEADER_SIZE; + + //Read IP address + STREAM_TO_STREAM(data,recParams,NETAPP_IPCONFIG_IP_LENGTH); + data += 4; + //Read subnet + STREAM_TO_STREAM(data,recParams,NETAPP_IPCONFIG_IP_LENGTH); + data += 4; + //Read default GW + STREAM_TO_STREAM(data,recParams,NETAPP_IPCONFIG_IP_LENGTH); + data += 4; + //Read DHCP server + STREAM_TO_STREAM(data,recParams,NETAPP_IPCONFIG_IP_LENGTH); + data += 4; + //Read DNS server + STREAM_TO_STREAM(data,recParams,NETAPP_IPCONFIG_IP_LENGTH); + // read the status + STREAM_TO_UINT8(event_hdr, HCI_EVENT_STATUS_OFFSET, *recParams); + + // tWlanCB func_pointer = (tWlanCB)_simple_link.get_func_pointer(WLAN_CB); + // if( func_pointer ) + // { + _cc3000.usync_callback(event_type, (uint8_t *)params, sizeof(params)); + // } + break; + } + case HCI_EVNT_WLAN_ASYNC_PING_REPORT: + { + netapp_pingreport_args_t params; + data = (uint8_t *)(event_hdr) + HCI_EVENT_HEADER_SIZE; + STREAM_TO_UINT32(data, NETAPP_PING_PACKETS_SENT_OFFSET, params.packets_sent); + STREAM_TO_UINT32(data, NETAPP_PING_PACKETS_RCVD_OFFSET, params.packets_received); + STREAM_TO_UINT32(data, NETAPP_PING_MIN_RTT_OFFSET, params.min_round_time); + STREAM_TO_UINT32(data, NETAPP_PING_MAX_RTT_OFFSET, params.max_round_time); + STREAM_TO_UINT32(data, NETAPP_PING_AVG_RTT_OFFSET, params.avg_round_time); + + // tWlanCB func_pointer = (tWlanCB)_simple_link.get_func_pointer(WLAN_CB); + // if (func_pointer) + // { + _cc3000.usync_callback(event_type, (uint8_t *)¶ms, sizeof(params)); + // } + break; + } + case HCI_EVNT_BSD_TCP_CLOSE_WAIT: + { + // tWlanCB func_pointer = (tWlanCB)_simple_link.get_func_pointer(WLAN_CB); + // if (func_pointer) + // { + _cc3000.usync_callback(event_type, NULL, 0); + // } + break; + } + + //'default' case which means "event not supported" + default: + return (0); + } + return(1); + } + + if ((event_type == HCI_EVNT_SEND) || (event_type == HCI_EVNT_SENDTO) || (event_type == HCI_EVNT_WRITE)) { + uint8_t *pArg; + int32_t status; + pArg = M_BSD_RESP_PARAMS_OFFSET(event_hdr); + STREAM_TO_UINT32(pArg, BSD_RSP_PARAMS_STATUS_OFFSET,status); + if (ERROR_SOCKET_INACTIVE == status) { + // The only synchronous event that can come from SL device in form of + // command complete is "Command Complete" on data sent, in case SL device + // was unable to transmit + int32_t transmit_error = _simple_link.get_transmit_error(); + STREAM_TO_UINT8(event_hdr, HCI_EVENT_STATUS_OFFSET, transmit_error); + _simple_link.set_transmit_error(transmit_error); + update_socket_active_status(M_BSD_RESP_PARAMS_OFFSET(event_hdr)); + return (1); + } + else { + return (0); + } + } + return(0); +} + +int32_t cc3000_event::hci_unsolicited_event_handler(void) { + uint32_t res = 0; + uint8_t *received_data; + + if (_simple_link.get_data_received_flag() != 0) { + received_data = (_simple_link.get_received_data()); + + if (*received_data == HCI_TYPE_EVNT) { + // unsolicited event received - finish handling + if (hci_unsol_event_handler((uint8_t *)received_data) == 1) { + // An unsolicited event was received: + // release the buffer and clean the event received + _simple_link.set_data_received_flag(0); + + res = 1; + _spi.wlan_irq_enable(); + } + } + } + return res; +} + +void cc3000_event::set_socket_active_status(int32_t sd, int32_t status) { + if (M_IS_VALID_SD(sd) && M_IS_VALID_STATUS(status)) + { + socket_active_status &= ~(1 << sd); /* clean socket's mask */ + socket_active_status |= (status << sd); /* set new socket's mask */ + } +} + +int32_t cc3000_event::hci_event_unsol_flowcontrol_handler(uint8_t *event) { + int32_t temp, value; + uint16_t i; + uint16_t pusNumberOfHandles=0; + uint8_t *pReadPayload; + + STREAM_TO_UINT16((uint8_t *)event,HCI_EVENT_HEADER_SIZE,pusNumberOfHandles); + pReadPayload = ((uint8_t *)event + HCI_EVENT_HEADER_SIZE + sizeof(pusNumberOfHandles)); + temp = 0; + + for(i = 0; i < pusNumberOfHandles; i++) { + STREAM_TO_UINT16(pReadPayload, FLOW_CONTROL_EVENT_FREE_BUFFS_OFFSET, value); + temp += value; + pReadPayload += FLOW_CONTROL_EVENT_SIZE; + } + + _simple_link.set_number_free_buffers(_simple_link.get_number_free_buffers() + temp); + _simple_link.set_number_of_released_packets(_simple_link.get_released_packets() + temp); + + return(ESUCCESS); +} + +int32_t cc3000_event::get_socket_active_status(int32_t sd) { + if(M_IS_VALID_SD(sd)) { + return (socket_active_status & (1 << sd)) ? SOCKET_STATUS_INACTIVE : SOCKET_STATUS_ACTIVE; + } else { + return SOCKET_STATUS_INACTIVE; + } +} + +void cc3000_event::update_socket_active_status(uint8_t *resp_params) { + int32_t status, sd; + + STREAM_TO_UINT32(resp_params, BSD_RSP_PARAMS_SOCKET_OFFSET,sd); + STREAM_TO_UINT32(resp_params, BSD_RSP_PARAMS_STATUS_OFFSET,status); + + if(ERROR_SOCKET_INACTIVE == status) { + set_socket_active_status(sd, SOCKET_STATUS_INACTIVE); + } +} + +void cc3000_event::simplelink_wait_event(uint16_t op_code, void *ret_param) { + // In the blocking implementation the control to caller will be returned only + // after the end of current transaction + _simple_link.set_op_code(op_code); + hci_event_handler(ret_param, 0, 0); +} + +void cc3000_event::simplelink_wait_data(uint8_t *pBuf, uint8_t *from, uint8_t *fromlen) { + // In the blocking implementation the control to caller will be returned only + // after the end of current transaction, i.e. only after data will be received + _simple_link.set_pending_data(1); + hci_event_handler(pBuf, from, fromlen); +} + + +} /* end of cc3000 namespace */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cc3000_event.h Thu Sep 19 07:55:14 2013 +0000 @@ -0,0 +1,143 @@ +/***************************************************************************** +* +* C++ interface/implementation created by Martin Kojtal (0xc0170). Thanks to +* Jim Carver and Frank Vannieuwkerke for their inital cc3000 mbed port and +* provided help. +* +* This version of "host driver" uses CC3000 Host Driver Implementation. Thus +* read the following copyright: +* +* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the +* distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*****************************************************************************/ +#ifndef CC3000_EVENT_H +#define CC3000_EVENT_H + +typedef struct _bsd_read_return_t +{ + int32_t iSocketDescriptor; + int32_t iNumberOfBytes; + uint32_t uiFlags; +} tBsdReadReturnParams; + +typedef struct _bsd_getsockopt_return_t +{ + uint8_t ucOptValue[4]; + uint8_t iStatus; +} tBsdGetSockOptReturnParams; + +typedef struct _bsd_accept_return_t +{ + int32_t iSocketDescriptor; + int32_t iStatus; + sockaddr tSocketAddress; + +} tBsdReturnParams; + +typedef struct _bsd_select_return_t +{ + int32_t iStatus; + uint32_t uiRdfd; + uint32_t uiWrfd; + uint32_t uiExfd; +} tBsdSelectRecvParams; + +typedef struct _bsd_gethostbyname_return_t +{ + int32_t retVal; + int32_t outputAddress; +} tBsdGethostbynameParams; + +#define FLOW_CONTROL_EVENT_HANDLE_OFFSET (0) +#define FLOW_CONTROL_EVENT_BLOCK_MODE_OFFSET (1) +#define FLOW_CONTROL_EVENT_FREE_BUFFS_OFFSET (2) +#define FLOW_CONTROL_EVENT_SIZE (4) + +#define BSD_RSP_PARAMS_SOCKET_OFFSET (0) +#define BSD_RSP_PARAMS_STATUS_OFFSET (4) + +#define GET_HOST_BY_NAME_RETVAL_OFFSET (0) +#define GET_HOST_BY_NAME_ADDR_OFFSET (4) + +#define ACCEPT_SD_OFFSET (0) +#define ACCEPT_RETURN_STATUS_OFFSET (4) +#define ACCEPT_ADDRESS__OFFSET (8) + +#define SL_RECEIVE_SD_OFFSET (0) +#define SL_RECEIVE_NUM_BYTES_OFFSET (4) +#define SL_RECEIVE__FLAGS__OFFSET (8) + + +#define SELECT_STATUS_OFFSET (0) +#define SELECT_READFD_OFFSET (4) +#define SELECT_WRITEFD_OFFSET (8) +#define SELECT_EXFD_OFFSET (12) + + +#define NETAPP_IPCONFIG_IP_OFFSET (0) +#define NETAPP_IPCONFIG_SUBNET_OFFSET (4) +#define NETAPP_IPCONFIG_GW_OFFSET (8) +#define NETAPP_IPCONFIG_DHCP_OFFSET (12) +#define NETAPP_IPCONFIG_DNS_OFFSET (16) +#define NETAPP_IPCONFIG_MAC_OFFSET (20) +#define NETAPP_IPCONFIG_SSID_OFFSET (26) + +#define NETAPP_IPCONFIG_IP_LENGTH (4) +#define NETAPP_IPCONFIG_MAC_LENGTH (6) +#define NETAPP_IPCONFIG_SSID_LENGTH (32) + + +#define NETAPP_PING_PACKETS_SENT_OFFSET (0) +#define NETAPP_PING_PACKETS_RCVD_OFFSET (4) +#define NETAPP_PING_MIN_RTT_OFFSET (8) +#define NETAPP_PING_MAX_RTT_OFFSET (12) +#define NETAPP_PING_AVG_RTT_OFFSET (16) + +#define GET_SCAN_RESULTS_TABlE_COUNT_OFFSET (0) +#define GET_SCAN_RESULTS_SCANRESULT_STATUS_OFFSET (4) +#define GET_SCAN_RESULTS_ISVALID_TO_SSIDLEN_OFFSET (8) +#define GET_SCAN_RESULTS_FRAME_TIME_OFFSET (10) +#define GET_SCAN_RESULTS_SSID_MAC_LENGTH (38) + +#define M_BSD_RESP_PARAMS_OFFSET(hci_event_hdr)((uint8_t *)(hci_event_hdr) + HCI_EVENT_HEADER_SIZE) + +#define SOCKET_STATUS_ACTIVE 0 +#define SOCKET_STATUS_INACTIVE 1 +/* Init socket_active_status = 'all ones': init all sockets with SOCKET_STATUS_INACTIVE. + Will be changed by 'set_socket_active_status' upon 'connect' and 'accept' calls */ +#define SOCKET_STATUS_INIT_VAL 0xFFFF +#define M_IS_VALID_SD(sd) ((0 <= (sd)) && ((sd) <= 7)) +#define M_IS_VALID_STATUS(status) (((status) == SOCKET_STATUS_ACTIVE)||((status) == SOCKET_STATUS_INACTIVE)) + +#define BSD_RECV_FROM_FROMLEN_OFFSET (4) +#define BSD_RECV_FROM_FROM_OFFSET (16) + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cc3000_hci.cpp Thu Sep 19 07:55:14 2013 +0000 @@ -0,0 +1,149 @@ +/***************************************************************************** +* +* C++ interface/implementation created by Martin Kojtal (0xc0170). Thanks to +* Jim Carver and Frank Vannieuwkerke for their inital cc3000 mbed port and +* provided help. +* +* This version of "host driver" uses CC3000 Host Driver Implementation. Thus +* read the following copyright: +* +* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the +* distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*****************************************************************************/ +#include "cc3000.h" + +namespace mbed_cc3000 { + +cc3000_hci::cc3000_hci(cc3000_spi &spi) : _spi(spi) { + +} + +cc3000_hci::~cc3000_hci() { + +} + +uint16_t cc3000_hci::command_send(uint16_t op_code, uint8_t *buffer, uint8_t length) { + unsigned char *stream; + + stream = (buffer + SPI_HEADER_SIZE); + + UINT8_TO_STREAM(stream, HCI_TYPE_CMND); + stream = UINT16_TO_STREAM(stream, op_code); + UINT8_TO_STREAM(stream, length); + //Update the opcode of the event we will be waiting for + _spi.write(buffer, length + SIMPLE_LINK_HCI_CMND_HEADER_SIZE); + return(0); +} + +uint32_t cc3000_hci::data_send(uint8_t op_code, uint8_t *args, uint16_t arg_length, + uint16_t data_length, const uint8_t *tail, uint16_t tail_length) { + unsigned char *stream; + + stream = ((args) + SPI_HEADER_SIZE); + + UINT8_TO_STREAM(stream, HCI_TYPE_DATA); + UINT8_TO_STREAM(stream, op_code); + UINT8_TO_STREAM(stream, arg_length); + stream = UINT16_TO_STREAM(stream, arg_length + data_length + tail_length); + + // Send the packet + _spi.write(args, SIMPLE_LINK_HCI_DATA_HEADER_SIZE + arg_length + data_length + tail_length); + + return 0; +} + +void cc3000_hci::data_command_send(uint16_t op_code, uint8_t *buffer, uint8_t arg_length, uint16_t data_length) { + unsigned char *stream = (buffer + SPI_HEADER_SIZE); + + UINT8_TO_STREAM(stream, HCI_TYPE_DATA); + UINT8_TO_STREAM(stream, op_code); + UINT8_TO_STREAM(stream, arg_length); + stream = UINT16_TO_STREAM(stream, arg_length + data_length); + + // Send the command + _spi.write(buffer, arg_length + data_length + SIMPLE_LINK_HCI_DATA_CMND_HEADER_SIZE); + + return; +} + +void cc3000_hci::patch_send(uint8_t op_code, uint8_t *buffer, uint8_t *patch, uint16_t data_length) { + unsigned short usTransLength; + unsigned char *stream = (buffer + SPI_HEADER_SIZE); + UINT8_TO_STREAM(stream, HCI_TYPE_PATCH); + UINT8_TO_STREAM(stream, op_code); + stream = UINT16_TO_STREAM(stream, data_length + SIMPLE_LINK_HCI_PATCH_HEADER_SIZE); + if (data_length <= SL_PATCH_PORTION_SIZE) + { + UINT16_TO_STREAM(stream, data_length); + stream = UINT16_TO_STREAM(stream, data_length); + memcpy((buffer + SPI_HEADER_SIZE) + HCI_PATCH_HEADER_SIZE, patch, data_length); + // Update the opcode of the event we will be waiting for + _spi.write(buffer, data_length + HCI_PATCH_HEADER_SIZE); + } + else + { + + usTransLength = (data_length/SL_PATCH_PORTION_SIZE); + UINT16_TO_STREAM(stream, data_length + SIMPLE_LINK_HCI_PATCH_HEADER_SIZE + usTransLength*SIMPLE_LINK_HCI_PATCH_HEADER_SIZE); + stream = UINT16_TO_STREAM(stream, SL_PATCH_PORTION_SIZE); + memcpy(buffer + SPI_HEADER_SIZE + HCI_PATCH_HEADER_SIZE, patch, SL_PATCH_PORTION_SIZE); + data_length -= SL_PATCH_PORTION_SIZE; + patch += SL_PATCH_PORTION_SIZE; + + // Update the opcode of the event we will be waiting for + _spi.write(buffer, SL_PATCH_PORTION_SIZE + HCI_PATCH_HEADER_SIZE); + + stream = (buffer + SPI_HEADER_SIZE); + while (data_length) + { + if (data_length <= SL_PATCH_PORTION_SIZE) + { + usTransLength = data_length; + data_length = 0; + + } + else + { + usTransLength = SL_PATCH_PORTION_SIZE; + data_length -= usTransLength; + } + + *(unsigned short *)stream = usTransLength; + memcpy(stream + SIMPLE_LINK_HCI_PATCH_HEADER_SIZE, patch, usTransLength); + patch += usTransLength; + + // Update the opcode of the event we will be waiting for + _spi.write((unsigned char *)stream, usTransLength + sizeof(usTransLength)); + } + } +} + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cc3000_netapp.cpp Thu Sep 19 07:55:14 2013 +0000 @@ -0,0 +1,199 @@ +/***************************************************************************** +* +* C++ interface/implementation created by Martin Kojtal (0xc0170). Thanks to +* Jim Carver and Frank Vannieuwkerke for their inital cc3000 mbed port and +* provided help. +* +* This version of "host driver" uses CC3000 Host Driver Implementation. Thus +* read the following copyright: +* +* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the +* distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*****************************************************************************/ +#include "cc3000.h" +#include "cc3000_netapp.h" + +namespace mbed_cc3000 { + +cc3000_netapp::cc3000_netapp(cc3000_simple_link &simple_link, cc3000_nvmem &nvmem, cc3000_hci &hci , cc3000_event &event) : + _simple_link(simple_link), _nvmem(nvmem), _hci(hci), _event(event) { + +} + +cc3000_netapp::~cc3000_netapp() { + +} + +int32_t cc3000_netapp::config_mac_adrress(uint8_t * mac) { + return _nvmem.set_mac_address(mac); +} + +int32_t cc3000_netapp::dhcp(uint32_t *ip, uint32_t *subnet_mask,uint32_t *default_gateway, uint32_t *dns_server) { + int8_t scRet; + uint8_t *ptr; + uint8_t *args; + + scRet = EFAIL; + ptr = _simple_link.get_transmit_buffer(); + args = (ptr + HEADERS_SIZE_CMD); + + // Fill in temporary command buffer + ARRAY_TO_STREAM(args,ip,4); + ARRAY_TO_STREAM(args,subnet_mask,4); + ARRAY_TO_STREAM(args,default_gateway,4); + args = UINT32_TO_STREAM(args, 0); + ARRAY_TO_STREAM(args,dns_server,4); + + // Initiate a HCI command + _hci.command_send(HCI_NETAPP_DHCP, ptr, NETAPP_DHCP_PARAMS_LEN); + + // Wait for command complete event + _event.simplelink_wait_event(HCI_NETAPP_DHCP, &scRet); + + return(scRet); +} + +#ifndef CC3000_TINY_DRIVER +void cc3000_netapp::ipconfig( tNetappIpconfigRetArgs * ipconfig ) { + uint8_t *ptr; + + ptr = _simple_link.get_transmit_buffer(); + + // Initiate a HCI command + _hci.command_send(HCI_NETAPP_IPCONFIG, ptr, 0); + + // Wait for command complete event + _event.simplelink_wait_event(HCI_NETAPP_IPCONFIG, ipconfig ); +} + + +int32_t cc3000_netapp::timeout_values(uint32_t *dhcp, uint32_t *arp,uint32_t *keep_alive, uint32_t *inactivity) { + int8_t scRet; + uint8_t *ptr; + uint8_t *args; + + scRet = EFAIL; + ptr = _simple_link.get_transmit_buffer(); + args = (ptr + HEADERS_SIZE_CMD); + + // Set minimal values of timers + MIN_TIMER_SET(*dhcp) + MIN_TIMER_SET(*arp) + MIN_TIMER_SET(*keep_alive) + MIN_TIMER_SET(*inactivity) + + // Fill in temporary command buffer + args = UINT32_TO_STREAM(args, *dhcp); + args = UINT32_TO_STREAM(args, *arp); + args = UINT32_TO_STREAM(args, *keep_alive); + args = UINT32_TO_STREAM(args, *inactivity); + + // Initiate a HCI command + _hci.command_send(HCI_NETAPP_SET_TIMERS, ptr, NETAPP_SET_TIMER_PARAMS_LEN); + + // Wait for command complete event + _event.simplelink_wait_event(HCI_NETAPP_SET_TIMERS, &scRet); + + return(scRet); +} + +int32_t cc3000_netapp::ping_send(uint32_t *ip, uint32_t ping_attempts, uint32_t ping_size, uint32_t ping_timeout) { + int8_t scRet; + uint8_t *ptr, *args; + + scRet = EFAIL; + ptr = _simple_link.get_transmit_buffer(); + args = (ptr + HEADERS_SIZE_CMD); + + // Fill in temporary command buffer + args = UINT32_TO_STREAM(args, *ip); + args = UINT32_TO_STREAM(args, ping_attempts); + args = UINT32_TO_STREAM(args, ping_size); + args = UINT32_TO_STREAM(args, ping_timeout); + + // Initiate a HCI command + _hci.command_send(HCI_NETAPP_PING_SEND, ptr, NETAPP_PING_SEND_PARAMS_LEN); + + // Wait for command complete event + _event.simplelink_wait_event(HCI_NETAPP_PING_SEND, &scRet); + + return(scRet); +} + +void cc3000_netapp::ping_report() { + uint8_t *ptr; + int8_t scRet; + ptr = _simple_link.get_transmit_buffer(); + + + scRet = EFAIL; + + // Initiate a HCI command + _hci.command_send(HCI_NETAPP_PING_REPORT, ptr, 0); + + // Wait for command complete event + _event.simplelink_wait_event(HCI_NETAPP_PING_REPORT, &scRet); +} + +int32_t cc3000_netapp::ping_stop() { + int8_t scRet; + uint8_t *ptr; + + scRet = EFAIL; + ptr = _simple_link.get_transmit_buffer(); + + // Initiate a HCI command + _hci.command_send(HCI_NETAPP_PING_STOP, ptr, 0); + + // Wait for command complete event + _event.simplelink_wait_event(HCI_NETAPP_PING_STOP, &scRet); + + return(scRet); +} + +int32_t cc3000_netapp::arp_flush() { + int8_t scRet; + uint8_t *ptr; + + scRet = EFAIL; + ptr = _simple_link.get_transmit_buffer(); + + // Initiate a HCI command + _hci.command_send(HCI_NETAPP_ARP_FLUSH, ptr, 0); + + // Wait for command complete event + _event.simplelink_wait_event(HCI_NETAPP_ARP_FLUSH, &scRet); + + return(scRet); +} +#endif + +} /* end of cc3000 namespace */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cc3000_netapp.h Thu Sep 19 07:55:14 2013 +0000 @@ -0,0 +1,88 @@ +/***************************************************************************** +* +* C++ interface/implementation created by Martin Kojtal (0xc0170). Thanks to +* Jim Carver and Frank Vannieuwkerke for their inital cc3000 mbed port and +* provided help. +* +* This version of "host driver" uses CC3000 Host Driver Implementation. Thus +* read the following copyright: +* +* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the +* distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*****************************************************************************/ +#ifndef CC3000_NETAPP_H +#define CC3000_NETAPP_H + +#define MIN_TIMER_VAL_SECONDS 20 +#define MIN_TIMER_SET(t) if ((0 != t) && (t < MIN_TIMER_VAL_SECONDS)) \ + { \ + t = MIN_TIMER_VAL_SECONDS; \ + } + + +#define NETAPP_DHCP_PARAMS_LEN (20) +#define NETAPP_SET_TIMER_PARAMS_LEN (20) +#define NETAPP_SET_DEBUG_LEVEL_PARAMS_LEN (4) +#define NETAPP_PING_SEND_PARAMS_LEN (16) + + +typedef struct _netapp_dhcp_ret_args_t +{ + uint8_t aucIP[4]; + uint8_t aucSubnetMask[4]; + uint8_t aucDefaultGateway[4]; + uint8_t aucDHCPServer[4]; + uint8_t aucDNSServer[4]; +}tNetappDhcpParams; + +typedef struct _netapp_ipconfig_ret_args_t +{ + uint8_t aucIP[4]; + uint8_t aucSubnetMask[4]; + uint8_t aucDefaultGateway[4]; + uint8_t aucDHCPServer[4]; + uint8_t aucDNSServer[4]; + uint8_t uaMacAddr[6]; + uint8_t uaSSID[32]; +}tNetappIpconfigRetArgs; + + +/*Ping send report parameters*/ +typedef struct _netapp_pingreport_args +{ + uint32_t packets_sent; + uint32_t packets_received; + uint32_t min_round_time; + uint32_t max_round_time; + uint32_t avg_round_time; +} netapp_pingreport_args_t; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cc3000_nvmem.cpp Thu Sep 19 07:55:14 2013 +0000 @@ -0,0 +1,186 @@ +/***************************************************************************** +* +* C++ interface/implementation created by Martin Kojtal (0xc0170). Thanks to +* Jim Carver and Frank Vannieuwkerke for their inital cc3000 mbed port and +* provided help. +* +* This version of "host driver" uses CC3000 Host Driver Implementation. Thus +* read the following copyright: +* +* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the +* distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*****************************************************************************/ +#include "cc3000.h" +#include "cc3000_nvmem.h" +#include "cc3000_common.h" + +namespace mbed_cc3000 { + +cc3000_nvmem::cc3000_nvmem(cc3000_hci &hci, cc3000_event &event, cc3000_simple_link &simple_link) + : _hci(hci), _event(event), _simple_link(simple_link) { + +} + +cc3000_nvmem::~cc3000_nvmem() { + +} + +int32_t cc3000_nvmem::read(uint32_t file_id, uint32_t length, uint32_t offset, uint8_t *buff) { + uint8_t ucStatus = 0xFF; + uint8_t *ptr; + uint8_t *args; + + ptr = _simple_link.get_transmit_buffer(); + args = (ptr + HEADERS_SIZE_CMD); + // Fill in HCI packet structure + args = UINT32_TO_STREAM(args, file_id); + args = UINT32_TO_STREAM(args, length); + args = UINT32_TO_STREAM(args, offset); + + // Initiate HCI command + _hci.command_send(HCI_CMND_NVMEM_READ, ptr, NVMEM_READ_PARAMS_LEN); + _event.simplelink_wait_event(HCI_CMND_NVMEM_READ, &ucStatus); + + // If data is present, read it even when an error is returned. + // Note: It is the users responsibility to ignore the data when an error is returned. + // Wait for the data in a synchronous way. + // We assume the buffer is large enough to also store nvmem parameters. + _event.simplelink_wait_data(buff, 0, 0); + + return(ucStatus); +} + +int32_t cc3000_nvmem::write(uint32_t file_id, uint32_t length, uint32_t entry_offset, uint8_t *buff) { + int32_t iRes; + uint8_t *ptr; + uint8_t *args; + + iRes = EFAIL; + + ptr = _simple_link.get_transmit_buffer(); + args = (ptr + SPI_HEADER_SIZE + HCI_DATA_CMD_HEADER_SIZE); + + // Fill in HCI packet structure + args = UINT32_TO_STREAM(args, file_id); + args = UINT32_TO_STREAM(args, 12); + args = UINT32_TO_STREAM(args, length); + args = UINT32_TO_STREAM(args, entry_offset); + + memcpy((ptr + SPI_HEADER_SIZE + HCI_DATA_CMD_HEADER_SIZE + + NVMEM_WRITE_PARAMS_LEN),buff,length); + + // Initiate a HCI command on the data channel + _hci.data_command_send(HCI_CMND_NVMEM_WRITE, ptr, NVMEM_WRITE_PARAMS_LEN, length); + + _event.simplelink_wait_event(HCI_EVNT_NVMEM_WRITE, &iRes); + + return(iRes); +} + +uint8_t cc3000_nvmem::set_mac_address(uint8_t *mac) { + return write(NVMEM_MAC_FILEID, MAC_ADDR_LEN, 0, mac); +} + +uint8_t cc3000_nvmem::get_mac_address(uint8_t *mac) { + return read(NVMEM_MAC_FILEID, MAC_ADDR_LEN, 0, mac); +} + +uint8_t cc3000_nvmem::write_patch(uint32_t file_id, uint32_t length, const uint8_t *data) { + uint8_t status = 0; + uint16_t offset = 0; + uint8_t* spDataPtr = (uint8_t*)data; + + while ((status == 0) && (length >= SP_PORTION_SIZE)) + { + status = write(file_id, SP_PORTION_SIZE, offset, spDataPtr); + offset += SP_PORTION_SIZE; + length -= SP_PORTION_SIZE; + spDataPtr += SP_PORTION_SIZE; + } + + if (status !=0) + { + // NVMEM error occurred + return status; + } + + if (length != 0) + { + // If length MOD 512 is nonzero, write the remaining bytes. + status = write(file_id, length, offset, spDataPtr); + } + + return status; +} + +int32_t cc3000_nvmem::create_entry(uint32_t file_id, uint32_t new_len) { + uint8_t *ptr; + uint8_t *args; + uint16_t retval; + + ptr = _simple_link.get_transmit_buffer(); + args = (ptr + HEADERS_SIZE_CMD); + + // Fill in HCI packet structure + args = UINT32_TO_STREAM(args, file_id); + args = UINT32_TO_STREAM(args, new_len); + + // Initiate a HCI command + _hci.command_send(HCI_CMND_NVMEM_CREATE_ENTRY,ptr, NVMEM_CREATE_PARAMS_LEN); + + _event.simplelink_wait_event(HCI_CMND_NVMEM_CREATE_ENTRY, &retval); + + return(retval); +} + +#ifndef CC3000_TINY_DRIVER +uint8_t cc3000_nvmem::read_sp_version(uint8_t* patch_ver) { + uint8_t *ptr; + // 1st byte is the status and the rest is the SP version + uint8_t retBuf[5]; + + ptr = _simple_link.get_transmit_buffer(); + + // Initiate a HCI command, no args are required + _hci.command_send(HCI_CMND_READ_SP_VERSION, ptr, 0); + _event.simplelink_wait_event(HCI_CMND_READ_SP_VERSION, retBuf); + + // package ID + *patch_ver = retBuf[3]; + // package build number + *(patch_ver+1) = retBuf[4]; + + return(retBuf[0]); +} + +#endif + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cc3000_nvmem.h Thu Sep 19 07:55:14 2013 +0000 @@ -0,0 +1,100 @@ +/***************************************************************************** +* +* C++ interface/implementation created by Martin Kojtal (0xc0170). Thanks to +* Jim Carver and Frank Vannieuwkerke for their inital cc3000 mbed port and +* provided help. +* +* This version of "host driver" uses CC3000 Host Driver Implementation. Thus +* read the following copyright: +* +* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the +* distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*****************************************************************************/ +#ifndef CC3000_NVMEM_H +#define CC3000_NVMEM_H + +#define NVMEM_READ_PARAMS_LEN (12) +#define NVMEM_CREATE_PARAMS_LEN (8) +#define NVMEM_WRITE_PARAMS_LEN (16) + + +/**************************************************************************** +** +** Definitions for File IDs +** +****************************************************************************/ +/* --------------------------------------------------------- EEPROM FAT table --------------------------------------------------------- + + File ID Offset File Size Used Size Parameter + # ID address (bytes) (bytes) + -------------------------------------------------------------------------------------------------------------------------------------- + 0 NVMEM_NVS_FILEID 0x50 0x1A0 0x1A RF Calibration results table(generated automatically by TX Bip) + 1 NVMEM_NVS_SHADOW_FILEID 0x1F0 0x1A0 0x1A NVS Shadow + 2 NVMEM_WLAN_CONFIG_FILEID 0x390 0x1000 0x64 WLAN configuration + 3 NVMEM_WLAN_CONFIG_SHADOW_FILEID 0x1390 0x1000 0x64 WLAN configuration shadow + 4 NVMEM_WLAN_DRIVER_SP_FILEID 0x2390 0x2000 variable WLAN Driver ROM Patches + 5 NVMEM_WLAN_FW_SP_FILEID 0x4390 0x2000 variable WLAN FW Patches + 6 NVMEM_MAC_FILEID 0x6390 0x10 0x10 6 bytes of MAC address + 7 NVMEM_FRONTEND_VARS_FILEID 0x63A0 0x10 0x10 Frontend Vars + 8 NVMEM_IP_CONFIG_FILEID 0x63B0 0x40 0x40 IP configuration + 9 NVMEM_IP_CONFIG_SHADOW_FILEID 0x63F0 0x40 0x40 IP configuration shadow +10 NVMEM_BOOTLOADER_SP_FILEID 0x6430 0x400 variable Bootloader Patches +11 NVMEM_RM_FILEID 0x6830 0x200 0x7F Radio parameters +12 NVMEM_AES128_KEY_FILEID 0x6A30 0x10 0x10 AES128 key file +13 NVMEM_SHARED_MEM_FILEID 0x6A40 0x50 0x44 Host-CC3000 shared memory file +14 NVMEM_USER_FILE_1_FILEID 0x6A90 variable variable 1st user file +15 NVMEM_USER_FILE_2_FILEID variable variable variable 2nd user file +*/ +/* NVMEM file ID - system files*/ +#define NVMEM_NVS_FILEID (0) +#define NVMEM_NVS_SHADOW_FILEID (1) +#define NVMEM_WLAN_CONFIG_FILEID (2) +#define NVMEM_WLAN_CONFIG_SHADOW_FILEID (3) +#define NVMEM_WLAN_DRIVER_SP_FILEID (4) +#define NVMEM_WLAN_FW_SP_FILEID (5) +#define NVMEM_MAC_FILEID (6) +#define NVMEM_FRONTEND_VARS_FILEID (7) +#define NVMEM_IP_CONFIG_FILEID (8) +#define NVMEM_IP_CONFIG_SHADOW_FILEID (9) +#define NVMEM_BOOTLOADER_SP_FILEID (10) +#define NVMEM_RM_FILEID (11) + +/* NVMEM file ID - user files*/ +#define NVMEM_AES128_KEY_FILEID (12) +#define NVMEM_SHARED_MEM_FILEID (13) +#define NVMEM_USER_FILE_1_FILEID (14) +#define NVMEM_USER_FILE_2_FILEID (15) + +/* max entry in order to invalid nvmem */ +#define NVMEM_MAX_ENTRY (16) + + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cc3000_security.cpp Thu Sep 19 07:55:14 2013 +0000 @@ -0,0 +1,381 @@ +/***************************************************************************** +* +* C++ interface/implementation created by Martin Kojtal (0xc0170). Thanks to +* Jim Carver and Frank Vannieuwkerke for their inital cc3000 mbed port and +* provided help. +* +* This version of "host driver" uses CC3000 Host Driver Implementation. Thus +* read the following copyright: +* +* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the +* distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*****************************************************************************/ +#include "cc3000.h" + +namespace mbed_cc3000 { + +#ifndef CC3000_UNENCRYPTED_SMART_CONFIG + +// forward sbox +static const uint8_t sbox[256] = { +//0 1 2 3 4 5 6 7 8 9 A B C D E F +0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, //0 +0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, //1 +0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, //2 +0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, //3 +0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, //4 +0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, //5 +0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, //6 +0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, //7 +0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, //8 +0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, //9 +0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, //A +0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, //B +0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, //C +0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, //D +0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, //E +0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 }; //F +// inverse sbox +static const uint8_t rsbox[256] = +{ 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb +, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb +, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e +, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25 +, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92 +, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84 +, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06 +, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b +, 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73 +, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e +, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b +, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4 +, 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f +, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef +, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61 +, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d }; +// round constant +static const uint8_t Rcon[11] = {0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36}; + +void cc3000_security::expandKey(uint8_t *expanded_key, uint8_t *key) { + uint16_t ii, buf1; + for (ii=0;ii<16;ii++) + expanded_key[ii] = key[ii]; + for (ii=1;ii<11;ii++) + { + buf1 = expanded_key[ii*16 - 4]; + expanded_key[ii*16 + 0] = sbox[expanded_key[ii*16 - 3]]^expanded_key[(ii-1)*16 + 0]^Rcon[ii]; + expanded_key[ii*16 + 1] = sbox[expanded_key[ii*16 - 2]]^expanded_key[(ii-1)*16 + 1]; + expanded_key[ii*16 + 2] = sbox[expanded_key[ii*16 - 1]]^expanded_key[(ii-1)*16 + 2]; + expanded_key[ii*16 + 3] = sbox[buf1 ]^expanded_key[(ii-1)*16 + 3]; + expanded_key[ii*16 + 4] = expanded_key[(ii-1)*16 + 4]^expanded_key[ii*16 + 0]; + expanded_key[ii*16 + 5] = expanded_key[(ii-1)*16 + 5]^expanded_key[ii*16 + 1]; + expanded_key[ii*16 + 6] = expanded_key[(ii-1)*16 + 6]^expanded_key[ii*16 + 2]; + expanded_key[ii*16 + 7] = expanded_key[(ii-1)*16 + 7]^expanded_key[ii*16 + 3]; + expanded_key[ii*16 + 8] = expanded_key[(ii-1)*16 + 8]^expanded_key[ii*16 + 4]; + expanded_key[ii*16 + 9] = expanded_key[(ii-1)*16 + 9]^expanded_key[ii*16 + 5]; + expanded_key[ii*16 +10] = expanded_key[(ii-1)*16 +10]^expanded_key[ii*16 + 6]; + expanded_key[ii*16 +11] = expanded_key[(ii-1)*16 +11]^expanded_key[ii*16 + 7]; + expanded_key[ii*16 +12] = expanded_key[(ii-1)*16 +12]^expanded_key[ii*16 + 8]; + expanded_key[ii*16 +13] = expanded_key[(ii-1)*16 +13]^expanded_key[ii*16 + 9]; + expanded_key[ii*16 +14] = expanded_key[(ii-1)*16 +14]^expanded_key[ii*16 +10]; + expanded_key[ii*16 +15] = expanded_key[(ii-1)*16 +15]^expanded_key[ii*16 +11]; + } +} + +uint8_t cc3000_security::galois_mul2(uint8_t value) { + if (value >> 7) { + value = value << 1; + return (value ^ 0x1b); + } else { + return (value << 1); + } +} + +void cc3000_security::aes_encr(uint8_t *state, uint8_t *expanded_key) { + uint8_t buf1, buf2, buf3, round; + + for (round = 0; round < 9; round ++) + { + // addroundkey, sbox and shiftrows + // row 0 + state[ 0] = sbox[(state[ 0] ^ expanded_key[(round*16) ])]; + state[ 4] = sbox[(state[ 4] ^ expanded_key[(round*16) + 4])]; + state[ 8] = sbox[(state[ 8] ^ expanded_key[(round*16) + 8])]; + state[12] = sbox[(state[12] ^ expanded_key[(round*16) + 12])]; + // row 1 + buf1 = state[1] ^ expanded_key[(round*16) + 1]; + state[ 1] = sbox[(state[ 5] ^ expanded_key[(round*16) + 5])]; + state[ 5] = sbox[(state[ 9] ^ expanded_key[(round*16) + 9])]; + state[ 9] = sbox[(state[13] ^ expanded_key[(round*16) + 13])]; + state[13] = sbox[buf1]; + // row 2 + buf1 = state[2] ^ expanded_key[(round*16) + 2]; + buf2 = state[6] ^ expanded_key[(round*16) + 6]; + state[ 2] = sbox[(state[10] ^ expanded_key[(round*16) + 10])]; + state[ 6] = sbox[(state[14] ^ expanded_key[(round*16) + 14])]; + state[10] = sbox[buf1]; + state[14] = sbox[buf2]; + // row 3 + buf1 = state[15] ^ expanded_key[(round*16) + 15]; + state[15] = sbox[(state[11] ^ expanded_key[(round*16) + 11])]; + state[11] = sbox[(state[ 7] ^ expanded_key[(round*16) + 7])]; + state[ 7] = sbox[(state[ 3] ^ expanded_key[(round*16) + 3])]; + state[ 3] = sbox[buf1]; + + // mixcolums ////////// + // col1 + buf1 = state[0] ^ state[1] ^ state[2] ^ state[3]; + buf2 = state[0]; + buf3 = state[0]^state[1]; buf3=galois_mul2(buf3); state[0] = state[0] ^ buf3 ^ buf1; + buf3 = state[1]^state[2]; buf3=galois_mul2(buf3); state[1] = state[1] ^ buf3 ^ buf1; + buf3 = state[2]^state[3]; buf3=galois_mul2(buf3); state[2] = state[2] ^ buf3 ^ buf1; + buf3 = state[3]^buf2; buf3=galois_mul2(buf3); state[3] = state[3] ^ buf3 ^ buf1; + // col2 + buf1 = state[4] ^ state[5] ^ state[6] ^ state[7]; + buf2 = state[4]; + buf3 = state[4]^state[5]; buf3=galois_mul2(buf3); state[4] = state[4] ^ buf3 ^ buf1; + buf3 = state[5]^state[6]; buf3=galois_mul2(buf3); state[5] = state[5] ^ buf3 ^ buf1; + buf3 = state[6]^state[7]; buf3=galois_mul2(buf3); state[6] = state[6] ^ buf3 ^ buf1; + buf3 = state[7]^buf2; buf3=galois_mul2(buf3); state[7] = state[7] ^ buf3 ^ buf1; + // col3 + buf1 = state[8] ^ state[9] ^ state[10] ^ state[11]; + buf2 = state[8]; + buf3 = state[8]^state[9]; buf3=galois_mul2(buf3); state[8] = state[8] ^ buf3 ^ buf1; + buf3 = state[9]^state[10]; buf3=galois_mul2(buf3); state[9] = state[9] ^ buf3 ^ buf1; + buf3 = state[10]^state[11]; buf3=galois_mul2(buf3); state[10] = state[10] ^ buf3 ^ buf1; + buf3 = state[11]^buf2; buf3=galois_mul2(buf3); state[11] = state[11] ^ buf3 ^ buf1; + // col4 + buf1 = state[12] ^ state[13] ^ state[14] ^ state[15]; + buf2 = state[12]; + buf3 = state[12]^state[13]; buf3=galois_mul2(buf3); state[12] = state[12] ^ buf3 ^ buf1; + buf3 = state[13]^state[14]; buf3=galois_mul2(buf3); state[13] = state[13] ^ buf3 ^ buf1; + buf3 = state[14]^state[15]; buf3=galois_mul2(buf3); state[14] = state[14] ^ buf3 ^ buf1; + buf3 = state[15]^buf2; buf3=galois_mul2(buf3); state[15] = state[15] ^ buf3 ^ buf1; + + } + // 10th round without mixcols + state[ 0] = sbox[(state[ 0] ^ expanded_key[(round*16) ])]; + state[ 4] = sbox[(state[ 4] ^ expanded_key[(round*16) + 4])]; + state[ 8] = sbox[(state[ 8] ^ expanded_key[(round*16) + 8])]; + state[12] = sbox[(state[12] ^ expanded_key[(round*16) + 12])]; + // row 1 + buf1 = state[1] ^ expanded_key[(round*16) + 1]; + state[ 1] = sbox[(state[ 5] ^ expanded_key[(round*16) + 5])]; + state[ 5] = sbox[(state[ 9] ^ expanded_key[(round*16) + 9])]; + state[ 9] = sbox[(state[13] ^ expanded_key[(round*16) + 13])]; + state[13] = sbox[buf1]; + // row 2 + buf1 = state[2] ^ expanded_key[(round*16) + 2]; + buf2 = state[6] ^ expanded_key[(round*16) + 6]; + state[ 2] = sbox[(state[10] ^ expanded_key[(round*16) + 10])]; + state[ 6] = sbox[(state[14] ^ expanded_key[(round*16) + 14])]; + state[10] = sbox[buf1]; + state[14] = sbox[buf2]; + // row 3 + buf1 = state[15] ^ expanded_key[(round*16) + 15]; + state[15] = sbox[(state[11] ^ expanded_key[(round*16) + 11])]; + state[11] = sbox[(state[ 7] ^ expanded_key[(round*16) + 7])]; + state[ 7] = sbox[(state[ 3] ^ expanded_key[(round*16) + 3])]; + state[ 3] = sbox[buf1]; + // last addroundkey + state[ 0]^=expanded_key[160]; + state[ 1]^=expanded_key[161]; + state[ 2]^=expanded_key[162]; + state[ 3]^=expanded_key[163]; + state[ 4]^=expanded_key[164]; + state[ 5]^=expanded_key[165]; + state[ 6]^=expanded_key[166]; + state[ 7]^=expanded_key[167]; + state[ 8]^=expanded_key[168]; + state[ 9]^=expanded_key[169]; + state[10]^=expanded_key[170]; + state[11]^=expanded_key[171]; + state[12]^=expanded_key[172]; + state[13]^=expanded_key[173]; + state[14]^=expanded_key[174]; + state[15]^=expanded_key[175]; +} + +void cc3000_security::aes_decr(uint8_t *state, uint8_t *expanded_key) { + uint8_t buf1, buf2, buf3; + int8_t round; + round = 9; + + // initial addroundkey + state[ 0]^=expanded_key[160]; + state[ 1]^=expanded_key[161]; + state[ 2]^=expanded_key[162]; + state[ 3]^=expanded_key[163]; + state[ 4]^=expanded_key[164]; + state[ 5]^=expanded_key[165]; + state[ 6]^=expanded_key[166]; + state[ 7]^=expanded_key[167]; + state[ 8]^=expanded_key[168]; + state[ 9]^=expanded_key[169]; + state[10]^=expanded_key[170]; + state[11]^=expanded_key[171]; + state[12]^=expanded_key[172]; + state[13]^=expanded_key[173]; + state[14]^=expanded_key[174]; + state[15]^=expanded_key[175]; + + // 10th round without mixcols + state[ 0] = rsbox[state[ 0]] ^ expanded_key[(round*16) ]; + state[ 4] = rsbox[state[ 4]] ^ expanded_key[(round*16) + 4]; + state[ 8] = rsbox[state[ 8]] ^ expanded_key[(round*16) + 8]; + state[12] = rsbox[state[12]] ^ expanded_key[(round*16) + 12]; + // row 1 + buf1 = rsbox[state[13]] ^ expanded_key[(round*16) + 1]; + state[13] = rsbox[state[ 9]] ^ expanded_key[(round*16) + 13]; + state[ 9] = rsbox[state[ 5]] ^ expanded_key[(round*16) + 9]; + state[ 5] = rsbox[state[ 1]] ^ expanded_key[(round*16) + 5]; + state[ 1] = buf1; + // row 2 + buf1 = rsbox[state[ 2]] ^ expanded_key[(round*16) + 10]; + buf2 = rsbox[state[ 6]] ^ expanded_key[(round*16) + 14]; + state[ 2] = rsbox[state[10]] ^ expanded_key[(round*16) + 2]; + state[ 6] = rsbox[state[14]] ^ expanded_key[(round*16) + 6]; + state[10] = buf1; + state[14] = buf2; + // row 3 + buf1 = rsbox[state[ 3]] ^ expanded_key[(round*16) + 15]; + state[ 3] = rsbox[state[ 7]] ^ expanded_key[(round*16) + 3]; + state[ 7] = rsbox[state[11]] ^ expanded_key[(round*16) + 7]; + state[11] = rsbox[state[15]] ^ expanded_key[(round*16) + 11]; + state[15] = buf1; + + for (round = 8; round >= 0; round--) + { + // barreto + //col1 + buf1 = galois_mul2(galois_mul2(state[0]^state[2])); + buf2 = galois_mul2(galois_mul2(state[1]^state[3])); + state[0] ^= buf1; state[1] ^= buf2; state[2] ^= buf1; state[3] ^= buf2; + //col2 + buf1 = galois_mul2(galois_mul2(state[4]^state[6])); + buf2 = galois_mul2(galois_mul2(state[5]^state[7])); + state[4] ^= buf1; state[5] ^= buf2; state[6] ^= buf1; state[7] ^= buf2; + //col3 + buf1 = galois_mul2(galois_mul2(state[8]^state[10])); + buf2 = galois_mul2(galois_mul2(state[9]^state[11])); + state[8] ^= buf1; state[9] ^= buf2; state[10] ^= buf1; state[11] ^= buf2; + //col4 + buf1 = galois_mul2(galois_mul2(state[12]^state[14])); + buf2 = galois_mul2(galois_mul2(state[13]^state[15])); + state[12] ^= buf1; state[13] ^= buf2; state[14] ^= buf1; state[15] ^= buf2; + // mixcolums ////////// + // col1 + buf1 = state[0] ^ state[1] ^ state[2] ^ state[3]; + buf2 = state[0]; + buf3 = state[0]^state[1]; buf3=galois_mul2(buf3); state[0] = state[0] ^ buf3 ^ buf1; + buf3 = state[1]^state[2]; buf3=galois_mul2(buf3); state[1] = state[1] ^ buf3 ^ buf1; + buf3 = state[2]^state[3]; buf3=galois_mul2(buf3); state[2] = state[2] ^ buf3 ^ buf1; + buf3 = state[3]^buf2; buf3=galois_mul2(buf3); state[3] = state[3] ^ buf3 ^ buf1; + // col2 + buf1 = state[4] ^ state[5] ^ state[6] ^ state[7]; + buf2 = state[4]; + buf3 = state[4]^state[5]; buf3=galois_mul2(buf3); state[4] = state[4] ^ buf3 ^ buf1; + buf3 = state[5]^state[6]; buf3=galois_mul2(buf3); state[5] = state[5] ^ buf3 ^ buf1; + buf3 = state[6]^state[7]; buf3=galois_mul2(buf3); state[6] = state[6] ^ buf3 ^ buf1; + buf3 = state[7]^buf2; buf3=galois_mul2(buf3); state[7] = state[7] ^ buf3 ^ buf1; + // col3 + buf1 = state[8] ^ state[9] ^ state[10] ^ state[11]; + buf2 = state[8]; + buf3 = state[8]^state[9]; buf3=galois_mul2(buf3); state[8] = state[8] ^ buf3 ^ buf1; + buf3 = state[9]^state[10]; buf3=galois_mul2(buf3); state[9] = state[9] ^ buf3 ^ buf1; + buf3 = state[10]^state[11]; buf3=galois_mul2(buf3); state[10] = state[10] ^ buf3 ^ buf1; + buf3 = state[11]^buf2; buf3=galois_mul2(buf3); state[11] = state[11] ^ buf3 ^ buf1; + // col4 + buf1 = state[12] ^ state[13] ^ state[14] ^ state[15]; + buf2 = state[12]; + buf3 = state[12]^state[13]; buf3=galois_mul2(buf3); state[12] = state[12] ^ buf3 ^ buf1; + buf3 = state[13]^state[14]; buf3=galois_mul2(buf3); state[13] = state[13] ^ buf3 ^ buf1; + buf3 = state[14]^state[15]; buf3=galois_mul2(buf3); state[14] = state[14] ^ buf3 ^ buf1; + buf3 = state[15]^buf2; buf3=galois_mul2(buf3); state[15] = state[15] ^ buf3 ^ buf1; + + // addroundkey, rsbox and shiftrows + // row 0 + state[ 0] = rsbox[state[ 0]] ^ expanded_key[(round*16) ]; + state[ 4] = rsbox[state[ 4]] ^ expanded_key[(round*16) + 4]; + state[ 8] = rsbox[state[ 8]] ^ expanded_key[(round*16) + 8]; + state[12] = rsbox[state[12]] ^ expanded_key[(round*16) + 12]; + // row 1 + buf1 = rsbox[state[13]] ^ expanded_key[(round*16) + 1]; + state[13] = rsbox[state[ 9]] ^ expanded_key[(round*16) + 13]; + state[ 9] = rsbox[state[ 5]] ^ expanded_key[(round*16) + 9]; + state[ 5] = rsbox[state[ 1]] ^ expanded_key[(round*16) + 5]; + state[ 1] = buf1; + // row 2 + buf1 = rsbox[state[ 2]] ^ expanded_key[(round*16) + 10]; + buf2 = rsbox[state[ 6]] ^ expanded_key[(round*16) + 14]; + state[ 2] = rsbox[state[10]] ^ expanded_key[(round*16) + 2]; + state[ 6] = rsbox[state[14]] ^ expanded_key[(round*16) + 6]; + state[10] = buf1; + state[14] = buf2; + // row 3 + buf1 = rsbox[state[ 3]] ^ expanded_key[(round*16) + 15]; + state[ 3] = rsbox[state[ 7]] ^ expanded_key[(round*16) + 3]; + state[ 7] = rsbox[state[11]] ^ expanded_key[(round*16) + 7]; + state[11] = rsbox[state[15]] ^ expanded_key[(round*16) + 11]; + state[15] = buf1; + } +} + +void cc3000_security::aes_encrypt(uint8_t *state, uint8_t *key) { + // expand the key into 176 bytes + expandKey(_expanded_key, key); + aes_encr(state, _expanded_key); +} + +void cc3000_security::aes_decrypt(uint8_t *state, uint8_t *key) { + expandKey(_expanded_key, key); // expand the key into 176 bytes + aes_decr(state, _expanded_key); +} + +int32_t cc3000_security::aes_read_key(uint8_t *key) { + int32_t returnValue; + + returnValue = nvmem_read(NVMEM_AES128_KEY_FILEID, AES128_KEY_SIZE, 0, key); + + return returnValue; +} + +int32_t cc3000_security::aes_write_key(uint8_t *key) { + int32_t returnValue; + + returnValue = nvmem_write(NVMEM_AES128_KEY_FILEID, AES128_KEY_SIZE, 0, key); + + return returnValue; +} +#endif + +} /* end of cc3000 namespace */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cc3000_server.cpp Thu Sep 19 07:55:14 2013 +0000 @@ -0,0 +1,94 @@ +/***************************************************************************** +* +* C++ interface/implementation created by Martin Kojtal (0xc0170). Thanks to +* Jim Carver and Frank Vannieuwkerke for their inital cc3000 mbed port and +* provided help. +* +* This version of "host driver" uses CC3000 Host Driver Implementation. Thus +* read the following copyright: +* +* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the +* distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*****************************************************************************/ +#include "cc3000.h" + +namespace mbed_cc3000 { +cc3000_server::cc3000_server(cc3000 &cc3000_ref, sockaddr socket_add) : _socket_address(socket_add), _cc3000(cc3000_ref) { + _current_socket = -1; +} + +cc3000_server::cc3000_server(cc3000 &cc3000_ref, sockaddr socket_add, int16_t socket) : _socket_address(socket_add), _cc3000(cc3000_ref) { + _current_socket = socket; +} + +int32_t cc3000_server::accept(void) { + int32_t client_descriptor = -2; + sockaddr dest_address; + + socklen_t address_length = sizeof(dest_address); + _current_socket = 0; + +#if (CC3000_DEBUG == 1) + printf("Waiting for receiving a connection.\n"); +#endif + while((client_descriptor == -1) || (client_descriptor == -2)) + { + client_descriptor = _cc3000._socket.accept(_current_socket,&dest_address, &address_length); + } +#if (CC3000_DEBUG == 1) + printf("Received.\n"); +#endif + _current_socket = client_descriptor; + + return _current_socket; +} + +int32_t cc3000_server::receive(void *buffer, uint16_t length, uint32_t flags) { + return _cc3000._socket.recv(_current_socket, buffer, length, flags); +} + +int32_t cc3000_server::send(void *buffer, uint16_t length, uint32_t flags) { + return _cc3000._socket.send(_current_socket, buffer, length, flags); +} + +void cc3000_server::bind(void) { + _cc3000._socket.bind(_current_socket, &_socket_address, sizeof(sockaddr)); +} + +void cc3000_server::listen(uint32_t backlog) { + _cc3000._socket.listen(_current_socket, backlog); +} + +void cc3000_server::close(void) { + _cc3000._socket.closesocket(_current_socket); +} + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cc3000_simplelink.cpp Thu Sep 19 07:55:14 2013 +0000 @@ -0,0 +1,185 @@ +/***************************************************************************** +* +* C++ interface/implementation created by Martin Kojtal (0xc0170). Thanks to +* Jim Carver and Frank Vannieuwkerke for their inital cc3000 mbed port and +* provided help. +* +* This version of "host driver" uses CC3000 Host Driver Implementation. Thus +* read the following copyright: +* +* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the +* distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*****************************************************************************/ +#include "cc3000.h" +#include "cc3000_common.h" + +namespace mbed_cc3000 { + +cc3000_simple_link::cc3000_simple_link() { + _rx_buffer[CC3000_RX_BUFFER_SIZE - 1] = CC3000_BUFFER_MAGIC_NUMBER; + _tx_buffer[CC3000_TX_BUFFER_SIZE - 1] = CC3000_BUFFER_MAGIC_NUMBER; +} + +cc3000_simple_link::~cc3000_simple_link() { +} + +uint8_t cc3000_simple_link::get_data_received_flag() { + return _data_received_flag; +} + +void *cc3000_simple_link::get_func_pointer(FunctionNumber function){ + void *result; + /* casting to void *, will be casted back once used */ + switch(function) { + case FW_PATCHES: + result = (void *)_fFWPatches; + break; + case DRIVER_PATCHES: + result = (void *)_fDriverPatches; + break; + case BOOTLOADER_PATCHES: + result = (void *)_fBootLoaderPatches; + break; + // case WLAN_CB: + // result = (void *)_fWlanCB; + // break; + default: + result = 0; + } + return result; +} + +uint8_t *cc3000_simple_link::get_transmit_buffer() { + return _tx_buffer; +} + +uint8_t *cc3000_simple_link::get_received_buffer() { + return _rx_buffer; +} + +void cc3000_simple_link::set_received_buffer(uint8_t value) { + *_rx_buffer = value; +} + +void cc3000_simple_link::set_transmit_buffer(uint8_t value) { + *_tx_buffer = value; +} + +void cc3000_simple_link::set_op_code(uint16_t code) { + _rx_event_opcode = code; +} + +void cc3000_simple_link::set_pending_data(uint16_t value) { + _rx_data_pending = value; +} + +uint16_t cc3000_simple_link::get_pending_data() { + return _rx_data_pending; +} + +void cc3000_simple_link::set_number_free_buffers(uint16_t value) { + _free_buffers = value; +} + +void cc3000_simple_link::set_number_of_released_packets(uint16_t value) { + _released_packets = value; +} + + +void cc3000_simple_link::set_tx_complete_signal(bool value) { + _tx_complete_signal = value; +} + +bool cc3000_simple_link::get_tx_complete_signal() { + return _tx_complete_signal; +} + +void cc3000_simple_link::set_data_received_flag(uint8_t value) { + _data_received_flag = value; +} + +uint16_t cc3000_simple_link::get_number_free_buffers() { + return _free_buffers; +} + +uint16_t cc3000_simple_link::get_buffer_length() { + return _buffer_length; +} + +void cc3000_simple_link::set_buffer_length(uint16_t value) { + _buffer_length = value; +} + +uint16_t cc3000_simple_link::get_op_code() { + return _rx_event_opcode; +} + +uint16_t cc3000_simple_link::get_released_packets() { + return _released_packets; +} + +uint16_t cc3000_simple_link::get_sent_packets() { + return _sent_packets; +} + +void cc3000_simple_link::set_sent_packets(uint16_t value) { + _sent_packets = value; +} + +void cc3000_simple_link::set_transmit_error(int32_t value){ + _transmit_data_error = value; +} + +int32_t cc3000_simple_link::get_transmit_error(){ + return _transmit_data_error; +} + +void cc3000_simple_link::set_buffer_size(uint16_t value) { + _buffer_size = value; +} + +uint16_t cc3000_simple_link::get_buffer_size(void) { + return _buffer_size; +} + +uint8_t *cc3000_simple_link::get_received_data(void) { + return _received_data; +} + +void cc3000_simple_link::set_received_data(uint8_t *pointer) { + _received_data = pointer; +} + +//void cc3000_simple_link::set_wlan_cb(tWlanCB fpointer) { +// _fWlanCB = fpointer; +//} + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cc3000_simplelink.h Thu Sep 19 07:55:14 2013 +0000 @@ -0,0 +1,48 @@ +/***************************************************************************** +* +* C++ interface/implementation created by Martin Kojtal (0xc0170). Thanks to +* Jim Carver and Frank Vannieuwkerke for their inital cc3000 mbed port and +* provided help. +* +* This version of "host driver" uses CC3000 Host Driver Implementation. Thus +* read the following copyright: +* +* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the +* distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*****************************************************************************/ +#ifndef CC3000_SIMPLELINK_H +#define CC3000_SIMPLELINK_H + +typedef uint8_t *(*tFWPatches)(uint32_t *usLength); +typedef uint8_t *(*tDriverPatches)(uint32_t *usLength); +typedef uint8_t *(*tBootLoaderPatches)(uint32_t *usLength); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cc3000_socket.cpp Thu Sep 19 07:55:14 2013 +0000 @@ -0,0 +1,602 @@ +/***************************************************************************** +* +* C++ interface/implementation created by Martin Kojtal (0xc0170). Thanks to +* Jim Carver and Frank Vannieuwkerke for their inital cc3000 mbed port and +* provided help. +* +* This version of "host driver" uses CC3000 Host Driver Implementation. Thus +* read the following copyright: +* +* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the +* distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*****************************************************************************/ +#include "cc3000.h" +#include "cc3000_socket.h" +#include "cc3000_event.h" //TODO - remove this +#include "cc3000_common.h" + +namespace mbed_cc3000 { + +cc3000_socket::cc3000_socket(cc3000_simple_link &simplelink, cc3000_hci &hci, cc3000_event &event) + : _simple_link(simplelink), _hci(hci), _event(event) +{ + +} + +cc3000_socket::~cc3000_socket() +{ + +} + +int32_t cc3000_socket::HostFlowControlConsumeBuff(int32_t sd) { +#ifndef SEND_NON_BLOCKING + /* wait in busy loop */ + do + { + // When the last transmission failed, return the last failure reason. + // Note that the buffer will not be allocated in this case + if (_simple_link.get_transmit_error() != 0) + { + errno = _simple_link.get_transmit_error(); + _simple_link.set_transmit_error(0); + return errno; + } + + if(SOCKET_STATUS_ACTIVE != _event.get_socket_active_status(sd)) + return -1; + } while(0 == _simple_link.get_number_free_buffers()); + + uint16_t free_buffer = _simple_link.get_number_free_buffers(); + free_buffer--; + _simple_link.set_number_free_buffers(free_buffer); + + return 0; +#else + + // When the last transmission failed, return the last failure reason. + // Note that the buffer will not be allocated in this case + if (_simple_link.get_transmit_error() != 0) + { + errno = _simple_link.get_transmit_error(); + _simple_link.set_transmit_error(0); + return errno; + } + if(SOCKET_STATUS_ACTIVE != get_socket_active_status(sd)) + return -1; + + // If there are no available buffers, return -2. It is recommended to use + // select or receive to see if there is any buffer occupied with received data + // If so, call receive() to release the buffer. + if(0 == _simple_link.get_number_free_buffers()) + { + return -2; + } + else + { + uint16 free_buffer = _simple_link.get_number_free_buffers(); + free_buffer--; + _simple_link.set_number_free_buffers(free_buffer); + return 0; + } +#endif +} + +int32_t cc3000_socket::socket(int32_t domain, int32_t type, int32_t protocol) { + int32_t ret; + uint8_t *ptr, *args; + + ret = EFAIL; + ptr = _simple_link.get_transmit_buffer(); + args = (ptr + HEADERS_SIZE_CMD); + + // Fill in HCI packet structure + args = UINT32_TO_STREAM(args, domain); + args = UINT32_TO_STREAM(args, type); + args = UINT32_TO_STREAM(args, protocol); + + // Initiate a HCI command + _hci.command_send(HCI_CMND_SOCKET, ptr, SOCKET_OPEN_PARAMS_LEN); + + // Since we are in blocking state - wait for event complete + _event.simplelink_wait_event(HCI_CMND_SOCKET, &ret); + + // Process the event + errno = ret; + + _event.set_socket_active_status(ret, SOCKET_STATUS_ACTIVE); + + return(ret); +} + +int32_t cc3000_socket::closesocket(int32_t sd) { + int32_t ret; + uint8_t *ptr, *args; + + ret = EFAIL; + ptr = _simple_link.get_transmit_buffer(); + args = (ptr + HEADERS_SIZE_CMD); + + // Fill in HCI packet structure + args = UINT32_TO_STREAM(args, sd); + + // Initiate a HCI command + _hci.command_send(HCI_CMND_CLOSE_SOCKET, ptr, SOCKET_CLOSE_PARAMS_LEN); + + // Since we are in blocking state - wait for event complete + _event.simplelink_wait_event(HCI_CMND_CLOSE_SOCKET, &ret); + errno = ret; + + // since 'close' call may result in either OK (and then it closed) or error, mark this socket as invalid + _event.set_socket_active_status(sd, SOCKET_STATUS_INACTIVE); + + return(ret); +} + +int32_t cc3000_socket::accept(int32_t sd, sockaddr *addr, socklen_t *addrlen) { + int32_t ret; + uint8_t *ptr, *args; + tBsdReturnParams tAcceptReturnArguments; + + ret = EFAIL; + ptr = _simple_link.get_transmit_buffer(); + args = (ptr + HEADERS_SIZE_CMD); + + // Fill in temporary command buffer + args = UINT32_TO_STREAM(args, sd); + + // Initiate a HCI command + _hci.command_send(HCI_CMND_ACCEPT, ptr, SOCKET_ACCEPT_PARAMS_LEN); + + // Since we are in blocking state - wait for event complete + _event.simplelink_wait_event(HCI_CMND_ACCEPT, &tAcceptReturnArguments); + + + // need specify return parameters!!! + memcpy(addr, &tAcceptReturnArguments.tSocketAddress, ASIC_ADDR_LEN); + *addrlen = ASIC_ADDR_LEN; + errno = tAcceptReturnArguments.iStatus; + ret = errno; + + // if succeeded, iStatus = new socket descriptor. otherwise - error number + if(M_IS_VALID_SD(ret)) + { + _event.set_socket_active_status(ret, SOCKET_STATUS_ACTIVE); + } + else + { + _event.set_socket_active_status(sd, SOCKET_STATUS_INACTIVE); + } + + return(ret); +} + +int32_t cc3000_socket::bind(int32_t sd, const sockaddr *addr, int32_t addrlen) { + int32_t ret; + uint8_t *ptr, *args; + + ret = EFAIL; + ptr = _simple_link.get_transmit_buffer(); + args = (ptr + HEADERS_SIZE_CMD); + + addrlen = ASIC_ADDR_LEN; + + // Fill in temporary command buffer + args = UINT32_TO_STREAM(args, sd); + args = UINT32_TO_STREAM(args, 0x00000008); + args = UINT32_TO_STREAM(args, addrlen); + ARRAY_TO_STREAM(args, ((uint8_t *)addr), addrlen); + + // Initiate a HCI command + _hci.command_send(HCI_CMND_BIND, ptr, SOCKET_BIND_PARAMS_LEN); + + // Since we are in blocking state - wait for event complete + _event.simplelink_wait_event(HCI_CMND_BIND, &ret); + + errno = ret; + + return(ret); +} + +int32_t cc3000_socket::listen(int32_t sd, int32_t backlog) { + int32_t ret; + uint8_t *ptr, *args; + + ret = EFAIL; + ptr = _simple_link.get_transmit_buffer(); + args = (ptr + HEADERS_SIZE_CMD); + + // Fill in temporary command buffer + args = UINT32_TO_STREAM(args, sd); + args = UINT32_TO_STREAM(args, backlog); + + // Initiate a HCI command + _hci.command_send(HCI_CMND_LISTEN, ptr, SOCKET_LISTEN_PARAMS_LEN); + + // Since we are in blocking state - wait for event complete + _event.simplelink_wait_event(HCI_CMND_LISTEN, &ret); + errno = ret; + + return(ret); +} + +int32_t cc3000_socket::connect(int32_t sd, const sockaddr *addr, int32_t addrlen) { + int32_t ret; + uint8_t *ptr, *args; + + ret = EFAIL; + ptr = _simple_link.get_transmit_buffer(); + args = (ptr + SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE); + addrlen = 8; + + // Fill in temporary command buffer + args = UINT32_TO_STREAM(args, sd); + args = UINT32_TO_STREAM(args, 0x00000008); + args = UINT32_TO_STREAM(args, addrlen); + ARRAY_TO_STREAM(args, ((uint8_t *)addr), addrlen); + + // Initiate a HCI command + _hci.command_send(HCI_CMND_CONNECT, ptr, SOCKET_CONNECT_PARAMS_LEN); + + // Since we are in blocking state - wait for event complete + _event.simplelink_wait_event(HCI_CMND_CONNECT, &ret); + + errno = ret; + + return((int32_t)ret); +} + +int32_t cc3000_socket::select(int32_t nfds, fd_set *readsds, fd_set *writesds, fd_set *exceptsds, struct timeval *timeout) { + uint8_t *ptr, *args; + tBsdSelectRecvParams tParams; + uint32_t is_blocking; + + if( timeout == NULL) + { + is_blocking = 1; /* blocking , infinity timeout */ + } + else + { + is_blocking = 0; /* no blocking, timeout */ + } + + // Fill in HCI packet structure + ptr = _simple_link.get_transmit_buffer(); + args = (ptr + HEADERS_SIZE_CMD); + + // Fill in temporary command buffer + args = UINT32_TO_STREAM(args, nfds); + args = UINT32_TO_STREAM(args, 0x00000014); + args = UINT32_TO_STREAM(args, 0x00000014); + args = UINT32_TO_STREAM(args, 0x00000014); + args = UINT32_TO_STREAM(args, 0x00000014); + args = UINT32_TO_STREAM(args, is_blocking); + args = UINT32_TO_STREAM(args, ((readsds) ? *(uint32_t*)readsds : 0)); + args = UINT32_TO_STREAM(args, ((writesds) ? *(uint32_t*)writesds : 0)); + args = UINT32_TO_STREAM(args, ((exceptsds) ? *(uint32_t*)exceptsds : 0)); + + if (timeout) + { + if ( 0 == timeout->tv_sec && timeout->tv_usec < SELECT_TIMEOUT_MIN_MICRO_SECONDS) + { + timeout->tv_usec = SELECT_TIMEOUT_MIN_MICRO_SECONDS; + } + args = UINT32_TO_STREAM(args, timeout->tv_sec); + args = UINT32_TO_STREAM(args, timeout->tv_usec); + } + + // Initiate a HCI command + _hci.command_send(HCI_CMND_BSD_SELECT, ptr, SOCKET_SELECT_PARAMS_LEN); + + // Since we are in blocking state - wait for event complete + _event.simplelink_wait_event(HCI_EVNT_SELECT, &tParams); + + // Update actually read FD + if (tParams.iStatus >= 0) + { + if (readsds) + { + memcpy(readsds, &tParams.uiRdfd, sizeof(tParams.uiRdfd)); + } + + if (writesds) + { + memcpy(writesds, &tParams.uiWrfd, sizeof(tParams.uiWrfd)); + } + + if (exceptsds) + { + memcpy(exceptsds, &tParams.uiExfd, sizeof(tParams.uiExfd)); + } + + return(tParams.iStatus); + + } + else + { + errno = tParams.iStatus; + return(-1); + } +} + +int32_t cc3000_socket::get_sockopt (int32_t sd, int32_t level, int32_t optname, void *optval, socklen_t *optlen) { + uint8_t *ptr, *args; + tBsdGetSockOptReturnParams tRetParams; + + ptr = _simple_link.get_transmit_buffer(); + args = (ptr + HEADERS_SIZE_CMD); + + // Fill in temporary command buffer + args = UINT32_TO_STREAM(args, sd); + args = UINT32_TO_STREAM(args, level); + args = UINT32_TO_STREAM(args, optname); + + // Initiate a HCI command + _hci.command_send(HCI_CMND_GETSOCKOPT, ptr, SOCKET_GET_SOCK_OPT_PARAMS_LEN); + + // Since we are in blocking state - wait for event complete + _event.simplelink_wait_event(HCI_CMND_GETSOCKOPT, &tRetParams); + + if (((int8_t)tRetParams.iStatus) >= 0) + { + *optlen = 4; + memcpy(optval, tRetParams.ucOptValue, 4); + return (0); + } + else + { + errno = tRetParams.iStatus; + return errno; + } +} + +int32_t cc3000_socket::simple_link_recv(int32_t sd, void *buf, int32_t len, int32_t flags, sockaddr *from, socklen_t *fromlen, int32_t opcode) { + uint8_t *ptr, *args; + tBsdReadReturnParams tSocketReadEvent; + + ptr = _simple_link.get_transmit_buffer(); + args = (ptr + HEADERS_SIZE_CMD); + + // Fill in HCI packet structure + args = UINT32_TO_STREAM(args, sd); + args = UINT32_TO_STREAM(args, len); + args = UINT32_TO_STREAM(args, flags); + + // Generate the read command, and wait for the + _hci.command_send(opcode, ptr, SOCKET_RECV_FROM_PARAMS_LEN); + + // Since we are in blocking state - wait for event complete + _event.simplelink_wait_event(opcode, &tSocketReadEvent); + + // In case the number of bytes is more then zero - read data + if (tSocketReadEvent.iNumberOfBytes > 0) + { + // Wait for the data in a synchronous way. Here we assume that the bug is + // big enough to store also parameters of receive from too.... + _event.simplelink_wait_data((uint8_t *)buf, (uint8_t *)from, (uint8_t *)fromlen); + } + + errno = tSocketReadEvent.iNumberOfBytes; + + return(tSocketReadEvent.iNumberOfBytes); +} + +int32_t cc3000_socket::recv(int32_t sd, void *buf, int32_t len, int32_t flags) { + return(simple_link_recv(sd, buf, len, flags, NULL, NULL, HCI_CMND_RECV)); +} + +int32_t cc3000_socket::recvfrom(int32_t sd, void *buf, int32_t len, int32_t flags, sockaddr *from, socklen_t *fromlen) { + return(simple_link_recv(sd, buf, len, flags, from, fromlen, HCI_CMND_RECVFROM)); +} + +int32_t cc3000_socket::simple_link_send(int32_t sd, const void *buf, int32_t len, int32_t flags, const sockaddr *to, int32_t tolen, int32_t opcode) { + uint8_t uArgSize = 0x00, addrlen = 0x00; + uint8_t *ptr, *pDataPtr = NULL, *args; + uint32_t addr_offset = 0x00; + int32_t res; + tBsdReadReturnParams tSocketSendEvent; + + // Check the bsd_arguments + if (0 != (res = HostFlowControlConsumeBuff(sd))) + { + return res; + } + + //Update the number of sent packets + uint16_t sent_packets = _simple_link.get_sent_packets(); + sent_packets++; + _simple_link.set_sent_packets(sent_packets); + + // Allocate a buffer and construct a packet and send it over spi + ptr = _simple_link.get_transmit_buffer(); + args = (ptr + HEADERS_SIZE_DATA); + + // Update the offset of data and parameters according to the command + switch(opcode) + { + case HCI_CMND_SENDTO: + { + addr_offset = len + sizeof(len) + sizeof(len); + addrlen = 8; + uArgSize = SOCKET_SENDTO_PARAMS_LEN; + pDataPtr = ptr + HEADERS_SIZE_DATA + SOCKET_SENDTO_PARAMS_LEN; + break; + } + + case HCI_CMND_SEND: + { + tolen = 0; + to = NULL; + uArgSize = HCI_CMND_SEND_ARG_LENGTH; + pDataPtr = ptr + HEADERS_SIZE_DATA + HCI_CMND_SEND_ARG_LENGTH; + break; + } + + default: + { + break; + } + } + + // Fill in temporary command buffer + args = UINT32_TO_STREAM(args, sd); + args = UINT32_TO_STREAM(args, uArgSize - sizeof(sd)); + args = UINT32_TO_STREAM(args, len); + args = UINT32_TO_STREAM(args, flags); + + if (opcode == HCI_CMND_SENDTO) + { + args = UINT32_TO_STREAM(args, addr_offset); + args = UINT32_TO_STREAM(args, addrlen); + } + + // Copy the data received from user into the TX Buffer + ARRAY_TO_STREAM(pDataPtr, ((uint8_t *)buf), len); + + // In case we are using SendTo, copy the to parameters + if (opcode == HCI_CMND_SENDTO) + { + ARRAY_TO_STREAM(pDataPtr, ((uint8_t *)to), tolen); + } + + // Initiate a HCI command + _hci.data_send(opcode, ptr, uArgSize, len,(uint8_t*)to, tolen); + if (opcode == HCI_CMND_SENDTO) + _event.simplelink_wait_event(HCI_EVNT_SENDTO, &tSocketSendEvent); + else + _event.simplelink_wait_event(HCI_EVNT_SEND, &tSocketSendEvent); + + return (len); +} + +int32_t cc3000_socket::send(int32_t sd, const void *buf, int32_t len, int32_t flags) { + return(simple_link_send(sd, buf, len, flags, NULL, 0, HCI_CMND_SEND)); +} + +int32_t cc3000_socket::sendto(int32_t sd, const void *buf, int32_t len, int32_t flags, const sockaddr *to, socklen_t tolen) { + return(simple_link_send(sd, buf, len, flags, to, tolen, HCI_CMND_SENDTO)); +} + +int32_t cc3000_socket::mdns_advertiser(uint16_t mdns_enabled, uint8_t *device_service_name, uint16_t device_service_name_length) { + int32_t ret; + uint8_t *pTxBuffer, *pArgs; + + if (device_service_name_length > MDNS_DEVICE_SERVICE_MAX_LENGTH) + { + return EFAIL; + } + + pTxBuffer = _simple_link.get_transmit_buffer(); + pArgs = (pTxBuffer + SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE); + + // Fill in HCI packet structure + pArgs = UINT32_TO_STREAM(pArgs, mdns_enabled); + pArgs = UINT32_TO_STREAM(pArgs, 8); + pArgs = UINT32_TO_STREAM(pArgs, device_service_name_length); + ARRAY_TO_STREAM(pArgs, device_service_name, device_service_name_length); + + // Initiate a HCI command + _hci.command_send(HCI_CMND_MDNS_ADVERTISE, pTxBuffer, SOCKET_MDNS_ADVERTISE_PARAMS_LEN + device_service_name_length); + + // Since we are in blocking state - wait for event complete + _event.simplelink_wait_event(HCI_EVNT_MDNS_ADVERTISE, &ret); + + return ret; +} + + +#ifndef CC3000_TINY_DRIVER +int32_t cc3000_socket::get_host_by_name(uint8_t *hostname, uint16_t name_length, uint32_t *out_ip_addr) { + tBsdGethostbynameParams ret; + uint8_t *ptr, *args; + + errno = EFAIL; + + if (name_length > HOSTNAME_MAX_LENGTH) + { + return errno; + } + + ptr = _simple_link.get_transmit_buffer(); + args = (ptr + SIMPLE_LINK_HCI_CMND_TRANSPORT_HEADER_SIZE); + + // Fill in HCI packet structure + args = UINT32_TO_STREAM(args, 8); + args = UINT32_TO_STREAM(args, name_length); + ARRAY_TO_STREAM(args, hostname, name_length); + + // Initiate a HCI command + _hci.command_send(HCI_CMND_GETHOSTNAME, ptr, SOCKET_GET_HOST_BY_NAME_PARAMS_LEN + name_length - 1); + + // Since we are in blocking state - wait for event complete + _event.simplelink_wait_event(HCI_EVNT_BSD_GETHOSTBYNAME, &ret); + + errno = ret.retVal; + + (*((int32_t*)out_ip_addr)) = ret.outputAddress; + + return (errno); +} + +int32_t cc3000_socket::set_sockopt(int32_t sd, int32_t level, int32_t optname, const void *optval, socklen_t optlen) { + int32_t ret; + uint8_t *ptr, *args; + + ptr = _simple_link.get_transmit_buffer(); + args = (ptr + HEADERS_SIZE_CMD); + + // Fill in temporary command buffer + args = UINT32_TO_STREAM(args, sd); + args = UINT32_TO_STREAM(args, level); + args = UINT32_TO_STREAM(args, optname); + args = UINT32_TO_STREAM(args, 0x00000008); + args = UINT32_TO_STREAM(args, optlen); + ARRAY_TO_STREAM(args, ((uint8_t *)optval), optlen); + + // Initiate a HCI command + _hci.command_send(HCI_CMND_SETSOCKOPT, ptr, SOCKET_SET_SOCK_OPT_PARAMS_LEN + optlen); + + // Since we are in blocking state - wait for event complete + _event.simplelink_wait_event(HCI_CMND_SETSOCKOPT, &ret); + + if (ret >= 0) + { + return (0); + } + else + { + errno = ret; + return ret; + } +} + +#endif + +} /* end of cc3000 namespace */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cc3000_socket.h Thu Sep 19 07:55:14 2013 +0000 @@ -0,0 +1,223 @@ +/***************************************************************************** +* +* C++ interface/implementation created by Martin Kojtal (0xc0170). Thanks to +* Jim Carver and Frank Vannieuwkerke for their inital cc3000 mbed port and +* provided help. +* +* This version of "host driver" uses CC3000 Host Driver Implementation. Thus +* read the following copyright: +* +* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the +* distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*****************************************************************************/ +#ifndef CC3000_SOCKET_H +#define CC3000_SOCKET_H + +#define SOCKET_STATUS_ACTIVE 0 +#define SOCKET_STATUS_INACTIVE 1 + +#define SOCKET_STATUS_INIT_VAL 0xFFFF +#define M_IS_VALID_SD(sd) ((0 <= (sd)) && ((sd) <= 7)) +#define M_IS_VALID_STATUS(status) (((status) == SOCKET_STATUS_ACTIVE)||((status) == SOCKET_STATUS_INACTIVE)) + +#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) + +//#define NULL 0 + +// 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) + + +#define HOSTNAME_MAX_LENGTH (230) // 230 bytes + header shouldn't exceed 8 bit value + +//--------- Address Families -------- + +#define AF_INET 2 +#define AF_INET6 23 + +//------------ Socket Types ------------ + +#define SOCK_STREAM 1 +#define SOCK_DGRAM 2 +#define 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 SOCK_RDM 4 +#define SOCK_SEQPACKET 5 + +//----------- Socket Protocol ---------- + +#define IPPROTO_IP 0 // dummy for IP +#define IPPROTO_ICMP 1 // control message protocol +#define IPPROTO_IPV4 IPPROTO_IP // IP inside IP +#define IPPROTO_TCP 6 // tcp +#define IPPROTO_UDP 17 // user datagram protocol +#define IPPROTO_IPV6 41 // IPv6 in IPv6 +#define IPPROTO_NONE 59 // No next header +#define IPPROTO_RAW 255 // raw IP packet +#define IPPROTO_MAX 256 + +//----------- Socket retunr codes ----------- + +#define SOC_ERROR (-1) // error +#define SOC_IN_PROGRESS (-2) // socket in progress + +//----------- Socket Options ----------- +#define SOL_SOCKET 0xffff // socket level +#define SOCKOPT_RECV_TIMEOUT 1 // optname to configure recv and recvfromtimeout +#define SOCKOPT_NONBLOCK 2 // accept non block mode set SOCK_ON or SOCK_OFF (default block mode ) +#define SOCK_ON 0 // socket non-blocking mode is enabled +#define SOCK_OFF 1 // socket blocking mode is enabled + +#define TCP_NODELAY 0x0001 +#define TCP_BSDURGENT 0x7000 + +#define MAX_PACKET_SIZE 1500 +#define MAX_LISTEN_QUEUE 4 + +#define IOCTL_SOCKET_EVENTMASK + +#define ENOBUFS 55 // No buffer space available + +#define __FD_SETSIZE 32 + +#define ASIC_ADDR_LEN 8 + +#define NO_QUERY_RECIVED -3 + + +typedef struct _in_addr_t +{ + uint32_t s_addr; // load with inet_aton() +} in_addr; + +/*typedef struct _sockaddr_t +{ + unsigned short int sa_family; + unsigned char sa_data[14]; +} sockaddr;*/ + +typedef struct _sockaddr_in_t +{ + int16_t sin_family; // e.g. AF_INET + uint16_t sin_port; // e.g. htons(3490) + in_addr sin_addr; // see struct in_addr, below + uint8_t sin_zero[8]; // zero this if you want to +} sockaddr_in; + +typedef uint32_t socklen_t; + +// The fd_set member is required to be an array of longs. +typedef int32_t __fd_mask; + +// 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)) + +// fd_set for select and pselect. +typedef struct +{ + __fd_mask fds_bits[__FD_SETSIZE / __NFDBITS]; +#define __FDS_BITS(set) ((set)->fds_bits) +} fd_set; + +// We don't use `memset' because this would require a prototype and +// the array isn't too big. +#define __FD_ZERO(set) \ + do { \ + uint32_t __i; \ + fd_set *__arr = (set); \ + for (__i = 0; __i < sizeof (fd_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 'fd_set'. +#define FD_SET(fd, fdsetp) __FD_SET (fd, fdsetp) +#define FD_CLR(fd, fdsetp) __FD_CLR (fd, fdsetp) +#define FD_ISSET(fd, fdsetp) __FD_ISSET (fd, fdsetp) +#define FD_ZERO(fdsetp) __FD_ZERO (fdsetp) + +//Use in case of Big Endian only + +#define htonl(A) ((((uint32_t)(A) & 0xff000000) >> 24) | \ + (((uint32_t)(A) & 0x00ff0000) >> 8) | \ + (((uint32_t)(A) & 0x0000ff00) << 8) | \ + (((uint32_t)(A) & 0x000000ff) << 24)) + +#define ntohl htonl + +//Use in case of Big Endian only +#define htons(A) ((((uint32_t)(A) & 0xff00) >> 8) | \ + (((uint32_t)(A) & 0x00ff) << 8)) + + +#define ntohs htons + +// 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; + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cc3000_spi.cpp Thu Sep 19 07:55:14 2013 +0000 @@ -0,0 +1,302 @@ +/***************************************************************************** +* +* C++ interface/implementation created by Martin Kojtal (0xc0170). Thanks to +* Jim Carver and Frank Vannieuwkerke for their inital cc3000 mbed port and +* provided help. +* +* This version of "host driver" uses CC3000 Host Driver Implementation. Thus +* read the following copyright: +* +* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the +* distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*****************************************************************************/ +#include "cc3000.h" +#include "cc3000_spi.h" + +namespace mbed_cc3000 { + +cc3000_spi::cc3000_spi(PinName cc3000_irq, PinName cc3000_en, PinName cc3000_cs, SPI cc3000_spi, IRQn_Type irq_port, cc3000_event &event, cc3000_simple_link &simple_link) + : _wlan_irq(cc3000_irq), _wlan_en(cc3000_en), _wlan_cs(cc3000_cs), _wlan_spi(cc3000_spi), _irq_port(irq_port), + _event(event), _simple_link(simple_link) { + /* TODO = clear pending interrupts for PORTS. This is dependent on the used chip */ + + _wlan_spi.format(8,1); + _wlan_spi.frequency(12000000); + _function_pointer = _wlan_irq.fall(this, &cc3000_spi::WLAN_IRQHandler); + + _wlan_en = 0; + _wlan_cs = 1; +} + +cc3000_spi::~cc3000_spi() { + +} + +void cc3000_spi::wlan_irq_enable() +{ + NVIC_EnableIRQ(_irq_port); +} + +void cc3000_spi::wlan_irq_disable() { + NVIC_DisableIRQ(_irq_port); +} + +void cc3000_spi::wlan_irq_set(uint8_t value) { + if (value) + { + _wlan_en = 1; + } + else + { + _wlan_en = 0; + } +} + +uint32_t cc3000_spi::wlan_irq_read() { + return _wlan_irq.read(); +} + +void cc3000_spi::close() { + if (_simple_link.get_received_buffer() != 0) + { + _simple_link.set_received_buffer(0); + } + wlan_irq_disable(); +} + +// void cc3000_spi::SpiReceiveHandler() { +// _simple_link.usEventOrDataReceived = 1; +// //_simple_link.pucReceivedData = (unsigned char *)pvBuffer; + +// hci_unsolicited_event_handler(); +// } + + +/* TODO + pRxPacket, pTxPacket do we need to hold this pointer ? + SPIRxHandler - remove? +*/ +void cc3000_spi::open() { + _spi_info.spi_state = eSPI_STATE_POWERUP; + //_spi_info.SPIRxHandler = pfRxHandler; + _spi_info.tx_packet_length = 0; + _spi_info.rx_packet_length = 0; + //_rx_buffer[CC3000_RX_BUFFER_SIZE - 1] = CC3000_BUFFER_MAGIC_NUMBER; + //_tx_buffer[CC3000_TX_BUFFER_SIZE - 1] = CC3000_BUFFER_MAGIC_NUMBER; + wlan_irq_enable(); +} + +uint32_t cc3000_spi::first_write(uint8_t *buffer, uint16_t length) { + _wlan_cs = 0; + wait_us(50); + + /* first 4 bytes of the data */ + write_synchronous(buffer, 4); + wait_us(50); + write_synchronous(buffer + 4, length - 4); + _spi_info.spi_state = eSPI_STATE_IDLE; + _wlan_cs = 1; + + return 0; +} + + +uint32_t cc3000_spi::write(uint8_t *buffer, uint16_t length) { + uint8_t pad = 0; + // check the total length of the packet in order to figure out if padding is necessary + if(!(length & 0x0001)) + { + pad++; + } + buffer[0] = WRITE; + buffer[1] = HI(length + pad); + buffer[2] = LO(length + pad); + buffer[3] = 0; + buffer[4] = 0; + + length += (SPI_HEADER_SIZE + pad); + + // The magic number resides at the end of the TX/RX buffer (1 byte after the allocated size) + // If the magic number is overwitten - buffer overrun occurred - we will be stuck here forever! + uint8_t * transmit_buffer = _simple_link.get_transmit_buffer(); + if (transmit_buffer[CC3000_TX_BUFFER_SIZE - 1] != CC3000_BUFFER_MAGIC_NUMBER) + { + while (1); + } + + if (_spi_info.spi_state == eSPI_STATE_POWERUP) + { + while (_spi_info.spi_state != eSPI_STATE_INITIALIZED); + } + + if (_spi_info.spi_state == eSPI_STATE_INITIALIZED) + { + // TX/RX transaction over SPI after powerup: IRQ is low - send read buffer size command + first_write(buffer, length); + } + else + { + // Prevent occurence of a race condition when 2 back to back packets are sent to the + // device, so the state will move to IDLE and once again to not IDLE due to IRQ + wlan_irq_disable(); + + while (_spi_info.spi_state != eSPI_STATE_IDLE); + + _spi_info.spi_state = eSPI_STATE_WRITE_IRQ; + //_spi_info.pTxPacket = buffer; + _spi_info.tx_packet_length = length; + + // Assert the CS line and wait until the IRQ line is active, then initialize the write operation + _wlan_cs = 0; + + wlan_irq_enable(); + } + + // Wait until the transaction ends + while (_spi_info.spi_state != eSPI_STATE_IDLE); + + return 0; +} + +void cc3000_spi::write_synchronous(uint8_t *data, uint16_t size) { + while(size) + { + _wlan_spi.write(*data++); + size--; + } +} + +void cc3000_spi::read_synchronous(uint8_t *data, uint16_t size) { + for (uint32_t i = 0; i < size; i++) + { + data[i] = _wlan_spi.write(0x03);; + } +} + +uint32_t cc3000_spi::read_data_cont() { + long data_to_recv; + unsigned char *evnt_buff, type; + + //determine the packet type + evnt_buff = _simple_link.get_received_buffer(); + data_to_recv = 0; + STREAM_TO_UINT8((uint8_t *)(evnt_buff + SPI_HEADER_SIZE), HCI_PACKET_TYPE_OFFSET, type); + + switch(type) + { + case HCI_TYPE_DATA: + { + // Read the remaining data.. + STREAM_TO_UINT16((uint8_t *)(evnt_buff + SPI_HEADER_SIZE), HCI_DATA_LENGTH_OFFSET, data_to_recv); + if (!((HEADERS_SIZE_EVNT + data_to_recv) & 1)) + { + data_to_recv++; + } + + if (data_to_recv) + { + read_synchronous(evnt_buff + 10, data_to_recv); + } + break; + } + case HCI_TYPE_EVNT: + { + // Calculate the rest length of the data + STREAM_TO_UINT8((char *)(evnt_buff + SPI_HEADER_SIZE), HCI_EVENT_LENGTH_OFFSET, data_to_recv); + data_to_recv -= 1; + // Add padding byte if needed + if ((HEADERS_SIZE_EVNT + data_to_recv) & 1) + { + data_to_recv++; + } + + if (data_to_recv) + { + read_synchronous(evnt_buff + 10, data_to_recv); + } + + _spi_info.spi_state = eSPI_STATE_READ_EOT; + break; + } + } + return (0); +} + +void cc3000_spi::write_wlan_en(uint8_t value) { + if (value) { + _wlan_en = 1; + } else { + _wlan_en = 0; + } +} + +void cc3000_spi::WLAN_IRQHandler() { + if (_spi_info.spi_state == eSPI_STATE_POWERUP) + { + // Inform HCI Layer that IRQ occured after powerup + _spi_info.spi_state = eSPI_STATE_INITIALIZED; + } + else if (_spi_info.spi_state == eSPI_STATE_IDLE) + { + _spi_info.spi_state = eSPI_STATE_READ_IRQ; + /* IRQ line goes low - acknowledge it */ + _wlan_cs = 0; + read_synchronous(_simple_link.get_received_buffer(), 10); + _spi_info.spi_state = eSPI_STATE_READ_EOT; + + + // The header was read - continue with the payload read + if (!read_data_cont()) + { + // All the data was read - finalize handling by switching to the task + // Trigger Rx processing + wlan_irq_disable(); + _wlan_cs = 1; + // The magic number resides at the end of the TX/RX buffer (1 byte after the allocated size) + // If the magic number is overwitten - buffer overrun occurred - we will be stuck here forever! + uint8_t *received_buffer = _simple_link.get_received_buffer(); + if (received_buffer[CC3000_RX_BUFFER_SIZE - 1] != CC3000_BUFFER_MAGIC_NUMBER) + { + while (1); + } + _spi_info.spi_state = eSPI_STATE_IDLE; + _event.received_handler(received_buffer + SPI_HEADER_SIZE); + } + } + else if (_spi_info.spi_state == eSPI_STATE_WRITE_IRQ) + { + write_synchronous(_simple_link.get_transmit_buffer(), _spi_info.tx_packet_length); + _spi_info.spi_state = eSPI_STATE_IDLE; + _wlan_cs = 1; + } +} + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cc3000_spi.h Thu Sep 19 07:55:14 2013 +0000 @@ -0,0 +1,251 @@ +/***************************************************************************** +* +* C++ interface/implementation created by Martin Kojtal (0xc0170). Thanks to +* Jim Carver and Frank Vannieuwkerke for their inital cc3000 mbed port and +* provided help. +* +* This version of "host driver" uses CC3000 Host Driver Implementation. Thus +* read the following copyright: +* +* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the +* distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*****************************************************************************/ +#ifndef CC3000_SPI_H +#define CC3000_SPI_H + +typedef struct +{ + uint16_t tx_packet_length; + uint16_t rx_packet_length; + uint32_t spi_state; +} tSpiInfo; + + +/* =========================================================================================== + SPI + =========================================================================================== */ +#define READ 3 +#define WRITE 1 + +#define HI(value) (((value) & 0xFF00) >> 8) +#define LO(value) ((value) & 0x00FF) + +#define HEADERS_SIZE_EVNT (SPI_HEADER_SIZE + 5) + +#define SPI_HEADER_SIZE (5) + +#define eSPI_STATE_POWERUP (0) +#define eSPI_STATE_INITIALIZED (1) +#define eSPI_STATE_IDLE (2) +#define eSPI_STATE_WRITE_IRQ (3) +#define eSPI_STATE_WRITE_FIRST_PORTION (4) +#define eSPI_STATE_WRITE_EOT (5) +#define eSPI_STATE_READ_IRQ (6) +#define eSPI_STATE_READ_FIRST_PORTION (7) +#define eSPI_STATE_READ_EOT (8) + +// The magic number that resides at the end of the TX/RX buffer (1 byte after the allocated size) +// for the purpose of detection of the overrun. The location of the memory where the magic number +// resides shall never be written. In case it is written - overrun occured and either recevie function +// or send function will be stuck forever. +#define CC3000_BUFFER_MAGIC_NUMBER (0xDE) + +/* =========================================================================================== + HCI + =========================================================================================== */ + +#define SL_PATCH_PORTION_SIZE (1000) + +#define SPI_HEADER_SIZE (5) +#define SIMPLE_LINK_HCI_CMND_HEADER_SIZE (4) +#define HEADERS_SIZE_CMD (SPI_HEADER_SIZE + SIMPLE_LINK_HCI_CMND_HEADER_SIZE) +#define SIMPLE_LINK_HCI_DATA_CMND_HEADER_SIZE (5) +#define SIMPLE_LINK_HCI_DATA_HEADER_SIZE (5) +#define SIMPLE_LINK_HCI_PATCH_HEADER_SIZE (2) + +// Values that can be used as HCI Commands and HCI Packet header defines +#define HCI_TYPE_CMND 0x1 +#define HCI_TYPE_DATA 0x2 +#define HCI_TYPE_PATCH 0x3 +#define HCI_TYPE_EVNT 0x4 + + +#define HCI_EVENT_PATCHES_DRV_REQ (1) +#define HCI_EVENT_PATCHES_FW_REQ (2) +#define HCI_EVENT_PATCHES_BOOTLOAD_REQ (3) + + +#define HCI_CMND_WLAN_BASE (0x0000) +#define HCI_CMND_WLAN_CONNECT 0x0001 +#define HCI_CMND_WLAN_DISCONNECT 0x0002 +#define HCI_CMND_WLAN_IOCTL_SET_SCANPARAM 0x0003 +#define HCI_CMND_WLAN_IOCTL_SET_CONNECTION_POLICY 0x0004 +#define HCI_CMND_WLAN_IOCTL_ADD_PROFILE 0x0005 +#define HCI_CMND_WLAN_IOCTL_DEL_PROFILE 0x0006 +#define HCI_CMND_WLAN_IOCTL_GET_SCAN_RESULTS 0x0007 +#define HCI_CMND_EVENT_MASK 0x0008 +#define HCI_CMND_WLAN_IOCTL_STATUSGET 0x0009 +#define HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_START 0x000A +#define HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_STOP 0x000B +#define HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_SET_PREFIX 0x000C +#define HCI_CMND_WLAN_CONFIGURE_PATCH 0x000D + + +#define HCI_CMND_SOCKET_BASE 0x1000 +#define HCI_CMND_SOCKET 0x1001 +#define HCI_CMND_BIND 0x1002 +#define HCI_CMND_RECV 0x1004 +#define HCI_CMND_ACCEPT 0x1005 +#define HCI_CMND_LISTEN 0x1006 +#define HCI_CMND_CONNECT 0x1007 +#define HCI_CMND_BSD_SELECT 0x1008 +#define HCI_CMND_SETSOCKOPT 0x1009 +#define HCI_CMND_GETSOCKOPT 0x100A +#define HCI_CMND_CLOSE_SOCKET 0x100B +#define HCI_CMND_RECVFROM 0x100D +#define HCI_CMND_GETHOSTNAME 0x1010 +#define HCI_CMND_MDNS_ADVERTISE 0x1011 + + +#define HCI_DATA_BASE 0x80 + +#define HCI_CMND_SEND (0x01 + HCI_DATA_BASE) +#define HCI_CMND_SENDTO (0x03 + HCI_DATA_BASE) +#define HCI_DATA_BSD_RECVFROM (0x04 + HCI_DATA_BASE) +#define HCI_DATA_BSD_RECV (0x05 + HCI_DATA_BASE) + + +#define HCI_CMND_NVMEM_CBASE (0x0200) + + +#define HCI_CMND_NVMEM_CREATE_ENTRY (0x0203) +#define HCI_CMND_NVMEM_SWAP_ENTRY (0x0205) +#define HCI_CMND_NVMEM_READ (0x0201) +#define HCI_CMND_NVMEM_WRITE (0x0090) +#define HCI_CMND_NVMEM_WRITE_PATCH (0x0204) +#define HCI_CMND_READ_SP_VERSION (0x0207) + +#define HCI_CMND_READ_BUFFER_SIZE 0x400B +#define HCI_CMND_SIMPLE_LINK_START 0x4000 + +#define HCI_CMND_NETAPP_BASE 0x2000 + +#define HCI_NETAPP_DHCP (0x0001 + HCI_CMND_NETAPP_BASE) +#define HCI_NETAPP_PING_SEND (0x0002 + HCI_CMND_NETAPP_BASE) +#define HCI_NETAPP_PING_REPORT (0x0003 + HCI_CMND_NETAPP_BASE) +#define HCI_NETAPP_PING_STOP (0x0004 + HCI_CMND_NETAPP_BASE) +#define HCI_NETAPP_IPCONFIG (0x0005 + HCI_CMND_NETAPP_BASE) +#define HCI_NETAPP_ARP_FLUSH (0x0006 + HCI_CMND_NETAPP_BASE) +#define HCI_NETAPP_SET_DEBUG_LEVEL (0x0008 + HCI_CMND_NETAPP_BASE) +#define HCI_NETAPP_SET_TIMERS (0x0009 + HCI_CMND_NETAPP_BASE) + +// Values that can be used as HCI Events defines +#define HCI_EVNT_WLAN_BASE 0x0000 +#define HCI_EVNT_WLAN_CONNECT 0x0001 +#define HCI_EVNT_WLAN_DISCONNECT \ + 0x0002 +#define HCI_EVNT_WLAN_IOCTL_ADD_PROFILE \ + 0x0005 + + +#define HCI_EVNT_SOCKET HCI_CMND_SOCKET +#define HCI_EVNT_BIND HCI_CMND_BIND +#define HCI_EVNT_RECV HCI_CMND_RECV +#define HCI_EVNT_ACCEPT HCI_CMND_ACCEPT +#define HCI_EVNT_LISTEN HCI_CMND_LISTEN +#define HCI_EVNT_CONNECT HCI_CMND_CONNECT +#define HCI_EVNT_SELECT HCI_CMND_BSD_SELECT +#define HCI_EVNT_CLOSE_SOCKET HCI_CMND_CLOSE_SOCKET +#define HCI_EVNT_RECVFROM HCI_CMND_RECVFROM +#define HCI_EVNT_SETSOCKOPT HCI_CMND_SETSOCKOPT +#define HCI_EVNT_GETSOCKOPT HCI_CMND_GETSOCKOPT +#define HCI_EVNT_BSD_GETHOSTBYNAME HCI_CMND_GETHOSTNAME +#define HCI_EVNT_MDNS_ADVERTISE HCI_CMND_MDNS_ADVERTISE + +#define HCI_EVNT_SEND 0x1003 +#define HCI_EVNT_WRITE 0x100E +#define HCI_EVNT_SENDTO 0x100F + +#define HCI_EVNT_PATCHES_REQ 0x1000 + +#define HCI_EVNT_UNSOL_BASE 0x4000 + +#define HCI_EVNT_WLAN_UNSOL_BASE (0x8000) + +#define HCI_EVNT_WLAN_UNSOL_CONNECT (0x0001 + HCI_EVNT_WLAN_UNSOL_BASE) +#define HCI_EVNT_WLAN_UNSOL_DISCONNECT (0x0002 + HCI_EVNT_WLAN_UNSOL_BASE) +#define HCI_EVNT_WLAN_UNSOL_INIT (0x0004 + HCI_EVNT_WLAN_UNSOL_BASE) +#define HCI_EVNT_WLAN_TX_COMPLETE (0x0008 + HCI_EVNT_WLAN_UNSOL_BASE) +#define HCI_EVNT_WLAN_UNSOL_DHCP (0x0010 + HCI_EVNT_WLAN_UNSOL_BASE) +#define HCI_EVNT_WLAN_ASYNC_PING_REPORT (0x0040 + HCI_EVNT_WLAN_UNSOL_BASE) +#define HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE (0x0080 + HCI_EVNT_WLAN_UNSOL_BASE) +#define HCI_EVNT_WLAN_KEEPALIVE (0x0200 + HCI_EVNT_WLAN_UNSOL_BASE) +#define HCI_EVNT_BSD_TCP_CLOSE_WAIT (0x0800 + HCI_EVNT_WLAN_UNSOL_BASE) + +#define HCI_EVNT_DATA_UNSOL_FREE_BUFF \ + 0x4100 + +#define HCI_EVNT_NVMEM_CREATE_ENTRY \ + HCI_CMND_NVMEM_CREATE_ENTRY +#define HCI_EVNT_NVMEM_SWAP_ENTRY HCI_CMND_NVMEM_SWAP_ENTRY + +#define HCI_EVNT_NVMEM_READ HCI_CMND_NVMEM_READ +#define HCI_EVNT_NVMEM_WRITE (0x0202) + +#define HCI_EVNT_READ_SP_VERSION \ + HCI_CMND_READ_SP_VERSION + +#define HCI_EVNT_INPROGRESS 0xFFFF + + +#define HCI_DATA_RECVFROM 0x84 +#define HCI_DATA_RECV 0x85 +#define HCI_DATA_NVMEM 0x91 + +#define HCI_EVENT_CC3000_CAN_SHUT_DOWN 0x99 + +// Prototypes for the structures for HCI APIs. +#define HCI_DATA_HEADER_SIZE (5) +#define HCI_EVENT_HEADER_SIZE (5) +#define HCI_DATA_CMD_HEADER_SIZE (5) +#define HCI_PATCH_HEADER_SIZE (6) + +#define HCI_PACKET_TYPE_OFFSET (0) +#define HCI_PACKET_ARGSIZE_OFFSET (2) +#define HCI_PACKET_LENGTH_OFFSET (3) + + +#define HCI_EVENT_OPCODE_OFFSET (1) +#define HCI_EVENT_LENGTH_OFFSET (3) +#define HCI_EVENT_STATUS_OFFSET (4) +#define HCI_DATA_LENGTH_OFFSET (3) + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cc3000_wlan.cpp Thu Sep 19 07:55:14 2013 +0000 @@ -0,0 +1,699 @@ +/***************************************************************************** +* +* C++ interface/implementation created by Martin Kojtal (0xc0170). Thanks to +* Jim Carver and Frank Vannieuwkerke for their inital cc3000 mbed port and +* provided help. +* +* This version of "host driver" uses CC3000 Host Driver Implementation. Thus +* read the following copyright: +* +* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the +* distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*****************************************************************************/ +#include "cc3000.h" + +namespace mbed_cc3000 { + +cc3000_wlan::cc3000_wlan(cc3000_simple_link &simple_link, cc3000_event &event, cc3000_spi &spi, cc3000_hci &hci) : + _simple_link(simple_link), _event(event), _spi(spi), _hci(hci) { + +} + +cc3000_wlan::~cc3000_wlan() { + +} + +void cc3000_wlan::simpleLink_init_start(uint16_t patches_available_host) { + uint8_t *ptr; + uint8_t *args; + + ptr = _simple_link.get_transmit_buffer(); + args = (uint8_t *)(ptr + HEADERS_SIZE_CMD); + + UINT8_TO_STREAM(args, ((patches_available_host) ? SL_PATCHES_REQUEST_FORCE_HOST : SL_PATCHES_REQUEST_DEFAULT)); + + // IRQ Line asserted - send HCI_CMND_SIMPLE_LINK_START to CC3000 + _hci.command_send(HCI_CMND_SIMPLE_LINK_START, ptr, WLAN_SL_INIT_START_PARAMS_LEN); + _event.simplelink_wait_event(HCI_CMND_SIMPLE_LINK_START, 0); +} + +void cc3000_wlan::start(uint16_t patches_available_host) { + uint32_t spi_irq_state; + + _simple_link.set_sent_packets(0); + _simple_link.set_number_of_released_packets(0); + _simple_link.set_op_code(0); + _simple_link.set_number_free_buffers(0); + _simple_link.set_buffer_length(0); + _simple_link.set_buffer_size(0); + _simple_link.set_pending_data(0); + _simple_link.set_transmit_error(0); + _simple_link.set_data_received_flag(0); + _simple_link.set_buffer_size(0); + + // init spi + _spi.open(); + // Check the IRQ line + spi_irq_state = _spi.wlan_irq_read(); + // ASIC 1273 chip enable: toggle WLAN EN line + _spi.write_wlan_en(WLAN_ENABLE); + + if (spi_irq_state) + { + // wait till the IRQ line goes low + while(_spi.wlan_irq_read() != 0) + { + } + } + else + { + // wait till the IRQ line goes high and then low + while(_spi.wlan_irq_read() == 0) + { + } + while(_spi.wlan_irq_read() != 0) + { + } + } + simpleLink_init_start(patches_available_host); + + // Read Buffer's size and finish + _hci.command_send(HCI_CMND_READ_BUFFER_SIZE, _simple_link.get_transmit_buffer(), 0); + _event.simplelink_wait_event(HCI_CMND_READ_BUFFER_SIZE, 0); +} + + +void cc3000_wlan::stop() { + // ASIC 1273 chip disable + _spi.write_wlan_en( WLAN_DISABLE ); + + // Wait till IRQ line goes high... + while(_spi.wlan_irq_read() == 0) + { + } + + // Free the used by WLAN Driver memory + if (_simple_link.get_transmit_buffer()) + { + _simple_link.set_transmit_buffer(0); + } + + _spi.close(); +} + + +int32_t cc3000_wlan::disconnect() { + int32_t ret; + uint8_t *ptr; + + ret = EFAIL; + ptr = _simple_link.get_transmit_buffer(); + + _hci.command_send(HCI_CMND_WLAN_DISCONNECT, ptr, 0); + + // Wait for command complete event + _event.simplelink_wait_event(HCI_CMND_WLAN_DISCONNECT, &ret); + errno = ret; + + return(ret); +} + + +int32_t cc3000_wlan::ioctl_set_connection_policy(uint32_t should_connect_to_open_ap, + uint32_t use_fast_connect, + uint32_t use_profiles) { + int32_t ret; + uint8_t *ptr; + uint8_t *args; + + ret = EFAIL; + ptr = _simple_link.get_transmit_buffer(); + args = (uint8_t *)(ptr + HEADERS_SIZE_CMD); + + // Fill in HCI packet structure + args = UINT32_TO_STREAM(args, should_connect_to_open_ap); + args = UINT32_TO_STREAM(args, use_fast_connect); + args = UINT32_TO_STREAM(args, use_profiles); + + // Initiate a HCI command + _hci.command_send(HCI_CMND_WLAN_IOCTL_SET_CONNECTION_POLICY, ptr, WLAN_SET_CONNECTION_POLICY_PARAMS_LEN); + + // Wait for command complete event + _event.simplelink_wait_event(HCI_CMND_WLAN_IOCTL_SET_CONNECTION_POLICY, &ret); + + return(ret); +} + + +int32_t cc3000_wlan::ioctl_del_profile(uint32_t index) { + int32_t ret; + uint8_t *ptr; + uint8_t *args; + + ptr = _simple_link.get_transmit_buffer(); + args = (uint8_t *)(ptr + HEADERS_SIZE_CMD); + + // Fill in HCI packet structure + args = UINT32_TO_STREAM(args, index); + ret = EFAIL; + + // Initiate a HCI command + _hci.command_send(HCI_CMND_WLAN_IOCTL_DEL_PROFILE, ptr, WLAN_DEL_PROFILE_PARAMS_LEN); + + // Wait for command complete event + _event.simplelink_wait_event(HCI_CMND_WLAN_IOCTL_DEL_PROFILE, &ret); + + return(ret); +} + +int32_t cc3000_wlan::set_event_mask(uint32_t mask) { + int32_t ret; + uint8_t *ptr; + uint8_t *args; + + + if ((mask & HCI_EVNT_WLAN_TX_COMPLETE) == HCI_EVNT_WLAN_TX_COMPLETE) + { + _simple_link.set_tx_complete_signal(0); + + // Since an event is a virtual event - i.e. it is not coming from CC3000 + // there is no need to send anything to the device if it was an only event + if (mask == HCI_EVNT_WLAN_TX_COMPLETE) + { + return 0; + } + + mask &= ~HCI_EVNT_WLAN_TX_COMPLETE; + mask |= HCI_EVNT_WLAN_UNSOL_BASE; + } + else + { + _simple_link.set_tx_complete_signal(1); + } + + ret = EFAIL; + ptr = _simple_link.get_transmit_buffer(); + args = (uint8_t *)(ptr + HEADERS_SIZE_CMD); + + // Fill in HCI packet structure + args = UINT32_TO_STREAM(args, mask); + + // Initiate a HCI command + _hci.command_send(HCI_CMND_EVENT_MASK, ptr, WLAN_SET_MASK_PARAMS_LEN); + + // Wait for command complete event + _event.simplelink_wait_event(HCI_CMND_EVENT_MASK, &ret); + + return(ret); +} + + +int32_t cc3000_wlan::smart_config_start(uint32_t encrypted_flag) { + int32_t ret; + uint8_t *ptr; + uint8_t *args; + + ret = EFAIL; + ptr = _simple_link.get_transmit_buffer(); + args = (uint8_t *)(ptr + HEADERS_SIZE_CMD); + + // Fill in HCI packet structure + args = UINT32_TO_STREAM(args, encrypted_flag); + ret = EFAIL; + + _hci.command_send(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_START, ptr, WLAN_SMART_CONFIG_START_PARAMS_LEN); + + // Wait for command complete event + _event.simplelink_wait_event(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_START, &ret); + + return(ret); +} + + +int32_t cc3000_wlan::smart_config_stop(void) { + int32_t ret; + uint8_t *ptr; + + ret = EFAIL; + ptr = _simple_link.get_transmit_buffer(); + + _hci.command_send(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_STOP, ptr, 0); + + // Wait for command complete event + _event.simplelink_wait_event(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_STOP, &ret); + + return(ret); +} + +int32_t cc3000_wlan::smart_config_set_prefix(uint8_t *new_prefix) { + int32_t ret; + uint8_t *ptr; + uint8_t *args; + + ret = EFAIL; + ptr = _simple_link.get_transmit_buffer(); + args = (ptr + HEADERS_SIZE_CMD); + + if (new_prefix == NULL) + return ret; + else // with the new Smart Config, prefix must be TTT + { + *new_prefix = 'T'; + *(new_prefix + 1) = 'T'; + *(new_prefix + 2) = 'T'; + } + + ARRAY_TO_STREAM(args, new_prefix, SL_SIMPLE_CONFIG_PREFIX_LENGTH); + + _hci.command_send(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_SET_PREFIX, ptr, SL_SIMPLE_CONFIG_PREFIX_LENGTH); + + // Wait for command complete event + _event.simplelink_wait_event(HCI_CMND_WLAN_IOCTL_SIMPLE_CONFIG_SET_PREFIX, &ret); + + return(ret); +} + +#ifndef CC3000_TINY_DRIVER +int32_t cc3000_wlan::connect(uint32_t sec_type, const uint8_t *ssid, int32_t ssid_len, uint8_t *bssid, + uint8_t *key, int32_t key_len) { + int32_t ret; + uint8_t *ptr; + uint8_t *args; + uint8_t bssid_zero[] = {0, 0, 0, 0, 0, 0}; + + ret = EFAIL; + ptr = _simple_link.get_transmit_buffer(); + args = (ptr + HEADERS_SIZE_CMD); + + // Fill in command buffer + args = UINT32_TO_STREAM(args, 0x0000001c); + args = UINT32_TO_STREAM(args, ssid_len); + args = UINT32_TO_STREAM(args, sec_type); + args = UINT32_TO_STREAM(args, 0x00000010 + ssid_len); + args = UINT32_TO_STREAM(args, key_len); + args = UINT16_TO_STREAM(args, 0); + + // padding shall be zeroed + if(bssid) + { + ARRAY_TO_STREAM(args, bssid, ETH_ALEN); + } + else + { + ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN); + } + + ARRAY_TO_STREAM(args, ssid, ssid_len); + + if(key_len && key) + { + ARRAY_TO_STREAM(args, key, key_len); + } + + // Initiate a HCI command + _hci.command_send(HCI_CMND_WLAN_CONNECT, ptr, WLAN_CONNECT_PARAM_LEN + ssid_len + key_len - 1); + + // Wait for command complete event + _event.simplelink_wait_event(HCI_CMND_WLAN_CONNECT, &ret); + errno = ret; + + return(ret); +} + +int32_t cc3000_wlan::add_profile(uint32_t sec_type, + uint8_t* ssid, + uint32_t ssid_length, + uint8_t *b_ssid, + uint32_t priority, + uint32_t pairwise_cipher_or_tx_key_len, + uint32_t group_cipher_tx_key_index, + uint32_t key_mgmt, + uint8_t* pf_or_key, + uint32_t pass_phrase_len) { + uint16_t arg_len = 0x00; + int32_t ret; + uint8_t *ptr; + int32_t i = 0; + uint8_t *args; + uint8_t bssid_zero[] = {0, 0, 0, 0, 0, 0}; + + ptr = _simple_link.get_transmit_buffer(); + args = (ptr + HEADERS_SIZE_CMD); + + args = UINT32_TO_STREAM(args, sec_type); + + // Setup arguments in accordance with the security type + switch (sec_type) + { + //OPEN + case WLAN_SEC_UNSEC: + { + args = UINT32_TO_STREAM(args, 0x00000014); + args = UINT32_TO_STREAM(args, ssid_length); + args = UINT16_TO_STREAM(args, 0); + if(b_ssid) + { + ARRAY_TO_STREAM(args, b_ssid, ETH_ALEN); + } + else + { + ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN); + } + args = UINT32_TO_STREAM(args, priority); + ARRAY_TO_STREAM(args, ssid, ssid_length); + + arg_len = WLAN_ADD_PROFILE_NOSEC_PARAM_LEN + ssid_length; + } + break; + + //WEP + case WLAN_SEC_WEP: + { + args = UINT32_TO_STREAM(args, 0x00000020); + args = UINT32_TO_STREAM(args, ssid_length); + args = UINT16_TO_STREAM(args, 0); + if(b_ssid) + { + ARRAY_TO_STREAM(args, b_ssid, ETH_ALEN); + } + else + { + ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN); + } + args = UINT32_TO_STREAM(args, priority); + args = UINT32_TO_STREAM(args, 0x0000000C + ssid_length); + args = UINT32_TO_STREAM(args, pairwise_cipher_or_tx_key_len); + args = UINT32_TO_STREAM(args, group_cipher_tx_key_index); + ARRAY_TO_STREAM(args, ssid, ssid_length); + + for(i = 0; i < 4; i++) + { + uint8_t *p = &pf_or_key[i * pairwise_cipher_or_tx_key_len]; + + ARRAY_TO_STREAM(args, p, pairwise_cipher_or_tx_key_len); + } + + arg_len = WLAN_ADD_PROFILE_WEP_PARAM_LEN + ssid_length + + pairwise_cipher_or_tx_key_len * 4; + + } + break; + + //WPA + //WPA2 + case WLAN_SEC_WPA: + case WLAN_SEC_WPA2: + { + args = UINT32_TO_STREAM(args, 0x00000028); + args = UINT32_TO_STREAM(args, ssid_length); + args = UINT16_TO_STREAM(args, 0); + if(b_ssid) + { + ARRAY_TO_STREAM(args, b_ssid, ETH_ALEN); + } + else + { + ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN); + } + args = UINT32_TO_STREAM(args, priority); + args = UINT32_TO_STREAM(args, pairwise_cipher_or_tx_key_len); + args = UINT32_TO_STREAM(args, group_cipher_tx_key_index); + args = UINT32_TO_STREAM(args, key_mgmt); + args = UINT32_TO_STREAM(args, 0x00000008 + ssid_length); + args = UINT32_TO_STREAM(args, pass_phrase_len); + ARRAY_TO_STREAM(args, ssid, ssid_length); + ARRAY_TO_STREAM(args, pf_or_key, pass_phrase_len); + + arg_len = WLAN_ADD_PROFILE_WPA_PARAM_LEN + ssid_length + pass_phrase_len; + } + + break; + } + + // Initiate a HCI command + _hci.command_send(HCI_CMND_WLAN_IOCTL_ADD_PROFILE, ptr, arg_len); + + // Wait for command complete event + _event.simplelink_wait_event(HCI_CMND_WLAN_IOCTL_ADD_PROFILE, &ret); + + return(ret); +} + +int32_t cc3000_wlan::ioctl_get_scan_results(uint32_t scan_timeout, uint8_t *results) { + uint8_t *ptr; + uint8_t *args; + + ptr = _simple_link.get_transmit_buffer(); + args = (ptr + HEADERS_SIZE_CMD); + + // Fill in temporary command buffer + args = UINT32_TO_STREAM(args, scan_timeout); + + // Initiate a HCI command + _hci.command_send(HCI_CMND_WLAN_IOCTL_GET_SCAN_RESULTS, ptr, WLAN_GET_SCAN_RESULTS_PARAMS_LEN); + + // Wait for command complete event + _event.simplelink_wait_event(HCI_CMND_WLAN_IOCTL_GET_SCAN_RESULTS, results); + + return(0); +} + +int32_t cc3000_wlan::ioctl_set_scan_params(uint32_t enable, + uint32_t min_dwell_time, + uint32_t max_dwell_time, + uint32_t num_probe_requests, + uint32_t channel_mask, + int32_t rssi_threshold, + uint32_t snr_threshold, + uint32_t default_tx_power, + uint32_t *interval_list) { + uint32_t uiRes; + uint8_t *ptr; + uint8_t *args; + + ptr = _simple_link.get_transmit_buffer(); + args = (ptr + HEADERS_SIZE_CMD); + + // Fill in temporary command buffer + args = UINT32_TO_STREAM(args, 36); + args = UINT32_TO_STREAM(args, enable); + args = UINT32_TO_STREAM(args, min_dwell_time); + args = UINT32_TO_STREAM(args, max_dwell_time); + args = UINT32_TO_STREAM(args, num_probe_requests); + args = UINT32_TO_STREAM(args, channel_mask); + args = UINT32_TO_STREAM(args, rssi_threshold); + args = UINT32_TO_STREAM(args, snr_threshold); + args = UINT32_TO_STREAM(args, default_tx_power); + ARRAY_TO_STREAM(args, interval_list, sizeof(uint32_t) * SL_SET_SCAN_PARAMS_INTERVAL_LIST_SIZE); + + // Initiate a HCI command + _hci.command_send(HCI_CMND_WLAN_IOCTL_SET_SCANPARAM, ptr, WLAN_SET_SCAN_PARAMS_LEN); + + // Wait for command complete event + _event.simplelink_wait_event(HCI_CMND_WLAN_IOCTL_SET_SCANPARAM, &uiRes); + + return(uiRes); +} + +int32_t cc3000_wlan::ioctl_statusget(void) { + int32_t ret; + uint8_t *ptr; + + ret = EFAIL; + ptr = _simple_link.get_transmit_buffer(); + + _hci.command_send(HCI_CMND_WLAN_IOCTL_STATUSGET,ptr, 0); + + // Wait for command complete event + _event.simplelink_wait_event(HCI_CMND_WLAN_IOCTL_STATUSGET, &ret); + + return(ret); +} + +#else +int32_t cc3000_wlan::wlan_add_profile(uint32_t sec_type, + uint8_t *ssid, + uint32_t ssid_length, + uint8_t *b_ssid, + uint32_t priority, + uint32_t pairwise_cipher_or_tx_key_len, + uint32_t group_cipher_tx_key_index, + uint32_t key_mgmt, + uint8_t* pf_or_key, + uint32_t pass_phrase_length) +{ + return -1; +} + +int32_t cc3000_wlan::connect(const uint8_t *ssid, int32_t ssid_len) { + int32_t ret; + uint8_t *ptr; + uint8_t *args; + uint8_t bssid_zero[] = {0, 0, 0, 0, 0, 0}; + + ret = EFAIL; + ptr = _simple_link.get_transmit_buffer(); + args = (ptr + HEADERS_SIZE_CMD); + + // Fill in command buffer + args = UINT32_TO_STREAM(args, 0x0000001c); + args = UINT32_TO_STREAM(args, ssid_len); + args = UINT32_TO_STREAM(args, 0); + args = UINT32_TO_STREAM(args, 0x00000010 + ssid_len); + args = UINT32_TO_STREAM(args, 0); + args = UINT16_TO_STREAM(args, 0); + + // padding shall be zeroed + ARRAY_TO_STREAM(args, bssid_zero, ETH_ALEN); + ARRAY_TO_STREAM(args, ssid, ssid_len); + + // Initiate a HCI command + _hci.command_send(HCI_CMND_WLAN_CONNECT, ptr, WLAN_CONNECT_PARAM_LEN + ssid_len - 1); + + // Wait for command complete event + _event.simplelink_wait_event(HCI_CMND_WLAN_CONNECT, &ret); + errno = ret; + + return(ret); +} +#endif + + + +#ifndef CC3000_UNENCRYPTED_SMART_CONFIG +int32_t cc3000_wlan::smart_config_process(void) { + int32_t returnValue; + uint32_t ssidLen, keyLen; + uint8_t *decKeyPtr; + uint8_t *ssidPtr; + + // read the key from EEPROM - fileID 12 + returnValue = aes_read_key(key); + + if (returnValue != 0) + return returnValue; + + // read the received data from fileID #13 and parse it according to the followings: + // 1) SSID LEN - not encrypted + // 2) SSID - not encrypted + // 3) KEY LEN - not encrypted. always 32 bytes long + // 4) Security type - not encrypted + // 5) KEY - encrypted together with true key length as the first byte in KEY + // to elaborate, there are two corner cases: + // 1) the KEY is 32 bytes long. In this case, the first byte does not represent KEY length + // 2) the KEY is 31 bytes long. In this case, the first byte represent KEY length and equals 31 + returnValue = nvmem_read(NVMEM_SHARED_MEM_FILEID, SMART_CONFIG_PROFILE_SIZE, 0, profileArray); + + if (returnValue != 0) + return returnValue; + + ssidPtr = &profileArray[1]; + + ssidLen = profileArray[0]; + + decKeyPtr = &profileArray[profileArray[0] + 3]; + + aes_decrypt(decKeyPtr, key); + if (profileArray[profileArray[0] + 1] > 16) + aes_decrypt((uint8_t *)(decKeyPtr + 16), key); + + if (*(uint8_t *)(decKeyPtr +31) != 0) + { + if (*decKeyPtr == 31) + { + keyLen = 31; + decKeyPtr++; + } + else + { + keyLen = 32; + } + } + else + { + keyLen = *decKeyPtr; + decKeyPtr++; + } + + // add a profile + switch (profileArray[profileArray[0] + 2]) + { + case WLAN_SEC_UNSEC://None + { + returnValue = wlan_add_profile(profileArray[profileArray[0] + 2], // security type + ssidPtr, // SSID + ssidLen, // SSID length + NULL, // BSSID + 1, // Priority + 0, 0, 0, 0, 0); + + break; + } + + case WLAN_SEC_WEP://WEP + { + returnValue = wlan_add_profile(profileArray[profileArray[0] + 2], // security type + ssidPtr, // SSID + ssidLen, // SSID length + NULL, // BSSID + 1, // Priority + keyLen, // KEY length + 0, // KEY index + 0, + decKeyPtr, // KEY + 0); + + break; + } + + case WLAN_SEC_WPA: //WPA + case WLAN_SEC_WPA2: //WPA2 + { + returnValue = wlan_add_profile(WLAN_SEC_WPA2, // security type + ssidPtr, + ssidLen, + NULL, // BSSID + 1, // Priority + 0x18, // PairwiseCipher + 0x1e, // GroupCipher + 2, // KEY management + decKeyPtr, // KEY + keyLen); // KEY length + + break; + } + } + + return returnValue; +} +#endif + +}