cc3000 hostdriver with the mbed socket interface
Fork of cc3000_hostdriver_mbedsocket by
Diff: cc3000.h
- Revision:
- 20:30b6ed7bf8fd
- Parent:
- 19:9fdf8b4e41bf
- Child:
- 22:d23c59fec0dc
--- a/cc3000.h Thu Oct 03 09:49:03 2013 +0200 +++ b/cc3000.h Thu Oct 03 17:15:45 2013 +0200 @@ -1,715 +1,715 @@ -/***************************************************************************** -* -* 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 - -#if CC3000_DEBUG == 1 - - // DBG_SOCKET, mbed socket specific debug messages - #define DBG_SOCKET(x, ...) std::printf("[CC3000 : SOCKET] "x"\r\n", ##__VA_ARGS__); - - // DBG_HCI, prints a message for every recieved HCI event, quite a lot of debug - #define DBG_HCI(x, ...) std::printf("[CC3000 : HCI] "x"\r\n", ##__VA_ARGS__); - - // DBG_CC, General cc3000 debug messages - #define DBG_CC(x, ...) std::printf("[CC3000] "x"\r\n", ##__VA_ARGS__); -#else - #define DBG_SOCKET(x, ...) - #define DBG_HCI(x, ...) - #define DBG_CC(x, ...) -#endif - -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 socket(int32_t domain, int32_t type, int32_t protocol); - 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 HostFlowControlConsumeBuff(int32_t sd); - int32_t closesocket(int32_t sd); - int32_t listen(int32_t sd, int32_t backlog); - 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 getsockopt (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 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 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 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); -#ifndef CC3000_TINY_DRIVER - int32_t gethostbyname(uint8_t *hostname, uint16_t name_length, uint32_t *out_ip_addr); - int32_t setsockopt(int32_t sd, int32_t level, int32_t optname, const void *optval, socklen_t optlen); -#endif -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 - */ - uint8_t get_mac_address(uint8_t address[6]); - /** Set the cc3000's mac address - * \param address Mac address to be set - * \return - */ - uint8_t 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; - } -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; -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 +/***************************************************************************** +* +* 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 + +#if CC3000_DEBUG == 1 + + // DBG_SOCKET, mbed socket specific debug messages + #define DBG_SOCKET(x, ...) std::printf("[CC3000 : SOCKET] "x"\r\n", ##__VA_ARGS__); + + // DBG_HCI, prints a message for every recieved HCI event, quite a lot of debug + #define DBG_HCI(x, ...) std::printf("[CC3000 : HCI] "x"\r\n", ##__VA_ARGS__); + + // DBG_CC, General cc3000 debug messages + #define DBG_CC(x, ...) std::printf("[CC3000] "x"\r\n", ##__VA_ARGS__); +#else + #define DBG_SOCKET(x, ...) + #define DBG_HCI(x, ...) + #define DBG_CC(x, ...) +#endif + +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 socket(int32_t domain, int32_t type, int32_t protocol); + 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 HostFlowControlConsumeBuff(int32_t sd); + int32_t closesocket(int32_t sd); + int32_t listen(int32_t sd, int32_t backlog); + 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 getsockopt (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 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 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 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); +#ifndef CC3000_TINY_DRIVER + int32_t gethostbyname(uint8_t *hostname, uint16_t name_length, uint32_t *out_ip_addr); + int32_t setsockopt(int32_t sd, int32_t level, int32_t optname, const void *optval, socklen_t optlen); +#endif +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 + */ + uint8_t get_mac_address(uint8_t address[6]); + /** Set the cc3000's mac address + * \param address Mac address to be set + * \return + */ + uint8_t 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; + } +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; +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