cc3000 hostdriver with the mbed socket interface
Fork of cc3000_hostdriver_mbedsocket by
cc3000.h
- Committer:
- Kojto
- Date:
- 2013-10-03
- Revision:
- 20:30b6ed7bf8fd
- Parent:
- 19:9fdf8b4e41bf
- Child:
- 22:d23c59fec0dc
File content as of revision 20:30b6ed7bf8fd:
/***************************************************************************** * * 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