Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
cc3000.cpp
00001 /***************************************************************************** 00002 * 00003 * C++ interface/implementation created by Martin Kojtal (0xc0170). Thanks to 00004 * Jim Carver and Frank Vannieuwkerke for their inital cc3000 mbed port and 00005 * provided help. 00006 * 00007 * This version of "host driver" uses CC3000 Host Driver Implementation. Thus 00008 * read the following copyright: 00009 * 00010 * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ 00011 * 00012 * Redistribution and use in source and binary forms, with or without 00013 * modification, are permitted provided that the following conditions 00014 * are met: 00015 * 00016 * Redistributions of source code must retain the above copyright 00017 * notice, this list of conditions and the following disclaimer. 00018 * 00019 * Redistributions in binary form must reproduce the above copyright 00020 * notice, this list of conditions and the following disclaimer in the 00021 * documentation and/or other materials provided with the 00022 * distribution. 00023 * 00024 * Neither the name of Texas Instruments Incorporated nor the names of 00025 * its contributors may be used to endorse or promote products derived 00026 * from this software without specific prior written permission. 00027 * 00028 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00029 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00030 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 00031 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 00032 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00033 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00034 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00035 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00036 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00037 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00038 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00039 * 00040 *****************************************************************************/ 00041 #include "cc3000.h" 00042 #include "cc3000_event.h" 00043 00044 namespace mbed_cc3000 { 00045 00046 /* TODO this prefix remove? verify */ 00047 static uint8_t cc3000_prefix[] = {'T', 'T', 'T'}; 00048 cc3000 *cc3000::_inst; 00049 00050 cc3000::cc3000(PinName cc3000_irq, PinName cc3000_en, PinName cc3000_cs, SPI cc3000_spi) 00051 : _event(_simple_link, _hci, _spi, *this), _socket(_simple_link, _hci, _event), 00052 _spi(cc3000_irq, cc3000_en, cc3000_cs, cc3000_spi, _event, _simple_link), _hci(_spi), 00053 _nvmem(_hci, _event, _simple_link), _netapp(_simple_link, _nvmem, _hci, _event), 00054 _wlan(_simple_link, _event, _spi, _hci) { 00055 _simple_link.set_tx_complete_signal(1); 00056 memset(&_status, 0, sizeof(_status)); 00057 _inst = this; 00058 } 00059 00060 cc3000::~cc3000() { 00061 } 00062 00063 #if (CC3000_ETH_COMPAT == 1) 00064 cc3000::cc3000(PinName cc3000_irq, PinName cc3000_en, PinName cc3000_cs, SPI cc3000_spi, const char *ssid, 00065 const char *phrase, Security sec, bool smart_config) 00066 : _event(_simple_link, _hci, _spi, *this), _socket(_simple_link, _hci, _event), 00067 _spi(cc3000_irq, cc3000_en, cc3000_cs, cc3000_spi, _event, _simple_link), _hci(_spi), 00068 _nvmem(_hci, _event, _simple_link), _netapp(_simple_link, _nvmem, _hci, _event), 00069 _wlan(_simple_link, _event, _spi, _hci), _sec(sec), _smart_config(smart_config) { 00070 _simple_link.set_tx_complete_signal(1); 00071 memset(&_status, 0, sizeof(_status)); 00072 strcpy((char *)_ssid, ssid); 00073 strcpy((char *)_phrase, phrase); 00074 _inst = this; 00075 } 00076 00077 // Ethernet library compatible, functions return strings 00078 // Caches the ipconfig from the usync callback 00079 static char mac_addr[19]= "\0"; 00080 static char ip_addr[17] = "\0"; 00081 static char gateway[17] = "\0"; 00082 static char networkmask[17] = "\0"; 00083 00084 void cc3000::init() { 00085 _wlan.start(0); 00086 00087 uint32_t subnet[4] = {0}; 00088 uint32_t ip[4] = {0}; 00089 uint32_t getway[4] = {0}; 00090 uint32_t dns[4] = {0}; 00091 00092 _netapp.dhcp(ip, subnet, getway, dns); 00093 _wlan.stop(); 00094 wait(1); 00095 _wlan.start(0); 00096 00097 _status.enabled = 1; 00098 _wlan.set_event_mask(HCI_EVNT_WLAN_UNSOL_INIT | HCI_EVNT_WLAN_KEEPALIVE | HCI_EVNT_WLAN_ASYNC_PING_REPORT); 00099 } 00100 00101 void cc3000::init(const char *ip, const char *mask, const char *gateway) { 00102 _netapp.dhcp((uint32_t *)ip, (uint32_t *)mask, (uint32_t *)gateway, (uint32_t *)ip); //dns = ip 00103 _wlan.stop(); 00104 wait(1); 00105 _wlan.start(0); 00106 00107 _status.enabled = 1; 00108 _wlan.set_event_mask(HCI_EVNT_WLAN_UNSOL_INIT | HCI_EVNT_WLAN_KEEPALIVE | HCI_EVNT_WLAN_ASYNC_PING_REPORT); 00109 } 00110 00111 int cc3000::connect(unsigned int timeout_ms) { 00112 Timer t; 00113 int ret = 0; 00114 00115 if (_smart_config == false) { 00116 _wlan.ioctl_set_connection_policy(0, 0, 0); 00117 } else { 00118 tUserFS user_info; 00119 get_user_file_info((uint8_t *)&user_info, sizeof(user_info)); 00120 if (user_info.FTC == 1) { 00121 _wlan.ioctl_set_connection_policy(0, 1, 1); 00122 } else { 00123 DBG_CC("Smart config is not set. Please run the first time configuration."); 00124 return -1; 00125 } 00126 } 00127 00128 t.start(); 00129 while (is_connected() == false) { 00130 if (strlen((const char *)_phrase) < 8) { 00131 if (connect_open(_ssid)) { 00132 break; 00133 } 00134 } else { 00135 #ifndef CC3000_TINY_DRIVER 00136 if (connect_secure(_ssid,_phrase, _sec)) { 00137 break; 00138 } 00139 #else 00140 return -1; /* secure connection not supported with TINY_DRIVER */ 00141 #endif 00142 } 00143 00144 if (t.read_ms() > timeout_ms) { 00145 ret = -1; 00146 DBG_CC("Connection to AP failed"); 00147 break; 00148 } 00149 } 00150 00151 while (is_dhcp_configured() == false) 00152 { 00153 if (t.read_ms() > timeout_ms) { 00154 ret = -1; 00155 DBG_CC("Connection to AP failed"); 00156 break; 00157 } 00158 } 00159 00160 return ret; 00161 } 00162 00163 char* cc3000::getMACAddress() { 00164 return mac_addr; 00165 } 00166 00167 char* cc3000::getIPAddress() { 00168 return ip_addr; 00169 } 00170 00171 char* cc3000::getGateway() { 00172 return gateway; 00173 } 00174 00175 char* cc3000::getNetworkMask() { 00176 return networkmask; 00177 } 00178 00179 int cc3000::disconnect(void){ 00180 if (_wlan.disconnect()) { 00181 return -1; 00182 } else { 00183 return 0; 00184 } 00185 } 00186 00187 #endif 00188 00189 void cc3000::usync_callback(int32_t event_type, uint8_t *data, uint8_t length) { 00190 if (event_type == HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE) { 00191 DBG_CC("Callback : HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE"); 00192 _status.smart_config_complete = 1; 00193 _status.stop_smart_config = 1; 00194 } 00195 00196 if (event_type == HCI_EVNT_WLAN_UNSOL_CONNECT) { 00197 DBG_CC("Callback : HCI_EVNT_WLAN_UNSOL_CONNECT"); 00198 _status.connected = 1; 00199 // Connect message is always followed by a DHCP message, connection is not useable until then 00200 _status.dhcp = 0; 00201 } 00202 00203 if (event_type == HCI_EVNT_WLAN_UNSOL_DISCONNECT) { 00204 DBG_CC("Callback : HCI_EVNT_WLAN_UNSOL_DISCONNECT"); 00205 _status.connected = 0; 00206 _status.dhcp = 0; 00207 _status.dhcp_configured = 0; 00208 } 00209 00210 if (event_type == HCI_EVNT_WLAN_UNSOL_DHCP) { 00211 #if (CC3000_ETH_COMPAT == 1) 00212 _socket.inet_ntoa_r ( htonl(*((uint32_t *)(&data[NETAPP_IPCONFIG_IP_OFFSET]))), ip_addr, 17); 00213 _socket.inet_ntoa_r ( htonl(*((uint32_t *)(&data[NETAPP_IPCONFIG_GW_OFFSET]))), gateway, 17); 00214 _socket.inet_ntoa_r ( htonl(*((uint32_t *)(&data[NETAPP_IPCONFIG_SUBNET_OFFSET]))), networkmask, 17); 00215 _socket.inet_ntoa_r ( htonl(*((uint32_t *)(&data[NETAPP_IPCONFIG_MAC_OFFSET]))), mac_addr, 19); 00216 #endif 00217 if (*(data + NETAPP_IPCONFIG_MAC_OFFSET) == 0) { 00218 _status.dhcp = 1; 00219 DBG_CC("Callback : HCI_EVNT_WLAN_UNSOL_DHCP %i.%i.%i.%i", data[3], data[2], data[1], data[0]); 00220 } else { 00221 DBG_CC("Callback : HCI_EVNT_WLAN_UNSOL_DHCP - Disconnecting"); 00222 _status.dhcp = 0; 00223 } 00224 } 00225 00226 if (event_type == HCI_EVENT_CC3000_CAN_SHUT_DOWN) { 00227 // Note this means the modules is idle, so it could be shutdown.. 00228 //DBG_CC("Callback : HCI_EVENT_CC3000_CAN_SHUT_DOWN"); 00229 _status.ok_to_shut_down = 1; 00230 } 00231 00232 if (event_type == HCI_EVNT_WLAN_ASYNC_PING_REPORT) { 00233 DBG_CC("Callback : HCI_EVNT_WLAN_ASYNC_PING_REPORT"); 00234 memcpy(&_ping_report, data, length); 00235 } 00236 00237 if (event_type == HCI_EVNT_BSD_TCP_CLOSE_WAIT) { 00238 uint8_t socketnum = data[0]; 00239 DBG_CC("Callback : HCI_EVNT_BSD_TCP_CLOSE_WAIT - Socket : %d", socketnum); 00240 if (socketnum < MAX_SOCKETS) { 00241 _closed_sockets[socketnum] = true; /* clients socket is closed */ 00242 } 00243 } 00244 } 00245 00246 void cc3000::start_smart_config(const uint8_t *smart_config_key) { 00247 _status.smart_config_complete = 0; 00248 _wlan.ioctl_set_connection_policy(0, 0, 0); 00249 00250 if (_status.connected == 1) { 00251 disconnect(); 00252 } 00253 00254 //Wait until CC3000 is disconected 00255 while (_status.connected == 1) { 00256 wait_us(5); 00257 _event.hci_unsolicited_event_handler(); 00258 } 00259 00260 // Trigger the Smart Config process 00261 _wlan.smart_config_set_prefix(cc3000_prefix); 00262 // Start the Smart Config process with AES disabled 00263 _wlan.smart_config_start(0); 00264 00265 DBG_CC("Waiting for smartconfig to be completed"); 00266 00267 // Wait for Smart config finished 00268 while (_status.smart_config_complete == 0) { 00269 wait_ms(100); 00270 } 00271 00272 DBG_CC("Smartconfig finished"); 00273 00274 #ifndef CC3000_UNENCRYPTED_SMART_CONFIG 00275 // create new entry for AES encryption key 00276 _nvmem.create_entry(NVMEM_AES128_KEY_FILEID, 16); 00277 // write AES key to NVMEM 00278 _security.aes_write_key((uint8_t *)(&smart_config_key[0])); 00279 // Decrypt configuration information and add profile 00280 _wlan.smart_config_process(); 00281 #endif 00282 00283 // Configure to connect automatically to the AP retrieved in the 00284 // Smart config process 00285 _wlan.ioctl_set_connection_policy(0, 0, 1); 00286 00287 // reset the CC3000 00288 _wlan.stop(); 00289 _status.enabled = 0; 00290 wait(5); 00291 _wlan.start(0); 00292 _status.enabled = 1; 00293 00294 // Mask out all non-required events 00295 _wlan.set_event_mask(HCI_EVNT_WLAN_KEEPALIVE | HCI_EVNT_WLAN_UNSOL_INIT | HCI_EVNT_WLAN_ASYNC_PING_REPORT); 00296 } 00297 00298 bool cc3000::connect_secure(const uint8_t *ssid, const uint8_t *key, int32_t security_mode) { 00299 #ifdef CC3000_TINY_DRIVER 00300 return false; /* not supported*/ 00301 #else 00302 uint32_t ret; 00303 00304 //_wlan.disconnect(); 00305 wait_ms(3); 00306 ret = _wlan.connect(security_mode, ssid, strlen((const char *)ssid), 0, (uint8_t *)key, strlen((const char *)key)); 00307 if (ret == 0) { /* TODO static internal cc3000 state 0 to TRUE */ 00308 ret = true; 00309 } else { 00310 ret = false; 00311 } 00312 return ret; 00313 #endif 00314 } 00315 00316 bool cc3000::connect_non_blocking(const uint8_t *ssid, const uint8_t *key, int32_t security_mode) 00317 { 00318 bool ret = false; 00319 00320 if (key == 0) { 00321 if (connect_open(ssid)) { 00322 ret = true; 00323 } 00324 } else { 00325 #ifndef CC3000_TINY_DRIVER 00326 if (connect_secure(ssid,key,security_mode)) { 00327 ret = true; 00328 } 00329 #else 00330 /* secure connection not supported with TINY_DRIVER */ 00331 #endif 00332 } 00333 00334 return ret; 00335 } 00336 00337 bool cc3000::connect_to_AP(const uint8_t *ssid, const uint8_t *key, int32_t security_mode) { 00338 Timer t; 00339 bool ret = true; 00340 00341 t.start(); 00342 while (is_connected() == false) { 00343 if (key == 0) { 00344 if (connect_open(ssid)) { 00345 break; 00346 } 00347 } else { 00348 #ifndef CC3000_TINY_DRIVER 00349 if (connect_secure(ssid,key,security_mode)) { 00350 break; 00351 } 00352 #else 00353 return false; /* secure connection not supported with TINY_DRIVER */ 00354 #endif 00355 } 00356 00357 /* timeout 10 seconds */ 00358 if (t.read_ms() > 10000) { 00359 ret = false; 00360 DBG_CC("Connection to AP failed"); 00361 break; 00362 } 00363 } 00364 00365 return ret; 00366 } 00367 00368 void cc3000::start(uint8_t patch) { 00369 _wlan.start(patch); 00370 _status.enabled = 1; 00371 _wlan.set_event_mask(HCI_EVNT_WLAN_UNSOL_INIT | HCI_EVNT_WLAN_KEEPALIVE | HCI_EVNT_WLAN_ASYNC_PING_REPORT); 00372 } 00373 00374 void cc3000::stop(void) { 00375 _wlan.stop(); 00376 _status.enabled = 0; 00377 } 00378 00379 void cc3000::restart(uint8_t patch) { 00380 _wlan.stop(); 00381 _status.enabled = 0; 00382 wait_ms(500); 00383 _wlan.start(patch); 00384 _status.enabled = 1; 00385 } 00386 00387 bool cc3000::connect_open(const uint8_t *ssid) { 00388 _wlan.disconnect(); 00389 wait_ms(3); 00390 uint32_t ret; 00391 #ifndef CC3000_TINY_DRIVER 00392 ret = _wlan.connect(0,ssid, strlen((const char *)ssid), 0, 0, 0); 00393 #else 00394 ret = _wlan.connect(ssid, strlen((const char *)ssid)); 00395 #endif 00396 if (ret == 0) { 00397 ret = true; 00398 } else { 00399 ret = false; 00400 } 00401 return ret; 00402 } 00403 00404 bool cc3000::is_enabled() 00405 { 00406 return _status.enabled; 00407 } 00408 00409 bool cc3000::is_connected() { 00410 if (( _status.connected ) && ( _status.dhcp )) { 00411 return 1; 00412 } else { 00413 return 0; 00414 } 00415 } 00416 00417 bool cc3000::is_dhcp_configured() { 00418 return _status.dhcp; 00419 } 00420 00421 bool cc3000::is_smart_confing_completed() { 00422 return _status.smart_config_complete; 00423 } 00424 00425 uint8_t cc3000::get_mac_address(uint8_t address[6]) { 00426 return _nvmem.get_mac_address(address); 00427 } 00428 00429 uint8_t cc3000::set_mac_address(uint8_t address[6]) { 00430 return _nvmem.set_mac_address(address); 00431 } 00432 00433 void cc3000::get_user_file_info(uint8_t *info_file, size_t size) { 00434 _nvmem.read( NVMEM_USER_FILE_1_FILEID, size, 0, info_file); 00435 } 00436 00437 #ifndef CC3000_TINY_DRIVER 00438 bool cc3000::get_ip_config(tNetappIpconfigRetArgs *ip_config) { 00439 if ((_status.dhcp == false) || (_status.connected == false)) { 00440 return false; 00441 } 00442 00443 _netapp.ipconfig(ip_config); 00444 return true; 00445 } 00446 #endif 00447 00448 void cc3000::delete_profiles(void) { 00449 _wlan.ioctl_set_connection_policy(0, 0, 0); 00450 _wlan.ioctl_del_profile(255); 00451 00452 tUserFS user_info; 00453 get_user_file_info((uint8_t *)&user_info, sizeof(user_info)); 00454 user_info.FTC = 0; 00455 set_user_file_info((uint8_t *)&user_info, sizeof(user_info)); 00456 } 00457 00458 void cc3000::set_user_file_info(uint8_t *info_file, size_t size) { 00459 _nvmem.write( NVMEM_USER_FILE_1_FILEID, size, 0, info_file); 00460 } 00461 00462 uint32_t cc3000::ping(uint32_t ip, uint8_t attempts, uint16_t timeout, uint8_t size) { 00463 #ifndef CC3000_TINY_DRIVER 00464 uint32_t reversed_ip = (ip >> 24) | ((ip >> 8) & 0xFF00) | ((ip << 8) & 0xFF0000) | (ip << 24); 00465 00466 _ping_report.packets_received = 0; 00467 if (_netapp.ping_send(&reversed_ip, attempts, size, timeout) == -1) { 00468 DBG_CC("Failed to send ping"); 00469 return 0; 00470 } 00471 wait_ms(timeout*attempts*2); 00472 00473 /* known issue of cc3000 - sent number is send + received */ 00474 // TODO : Remove the Sent/recv'd counts until ti fix the firmware issue? 00475 DBG_CC("Sent: %d",_ping_report.packets_sent); 00476 DBG_CC("Received: %d",_ping_report.packets_received); 00477 DBG_CC("Min time: %d",_ping_report.min_round_time); 00478 DBG_CC("Max time: %d",_ping_report.max_round_time); 00479 DBG_CC("Avg time: %d",_ping_report.avg_round_time); 00480 00481 return _ping_report.packets_received; 00482 #else 00483 return 0; 00484 #endif 00485 } 00486 00487 /* Conversion between uint types and C strings */ 00488 uint8_t* UINT32_TO_STREAM_f (uint8_t *p, uint32_t u32) 00489 { 00490 *(p)++ = (uint8_t)(u32); 00491 *(p)++ = (uint8_t)((u32) >> 8); 00492 *(p)++ = (uint8_t)((u32) >> 16); 00493 *(p)++ = (uint8_t)((u32) >> 24); 00494 return p; 00495 } 00496 00497 00498 uint8_t* UINT16_TO_STREAM_f (uint8_t *p, uint16_t u16) 00499 { 00500 *(p)++ = (uint8_t)(u16); 00501 *(p)++ = (uint8_t)((u16) >> 8); 00502 return p; 00503 } 00504 00505 00506 uint16_t STREAM_TO_UINT16_f(uint8_t *p, uint16_t offset) 00507 { 00508 return (uint16_t)((uint16_t)((uint16_t) 00509 (*(p + offset + 1)) << 8) + (uint16_t)(*(p + offset))); 00510 } 00511 00512 00513 uint32_t STREAM_TO_UINT32_f(uint8_t *p, uint16_t offset) 00514 { 00515 return (uint32_t)((uint32_t)((uint32_t) 00516 (*(p + offset + 3)) << 24) + (uint32_t)((uint32_t) 00517 (*(p + offset + 2)) << 16) + (uint32_t)((uint32_t) 00518 (*(p + offset + 1)) << 8) + (uint32_t)(*(p + offset))); 00519 } 00520 00521 } // mbed_cc3000 namespace 00522 00523
Generated on Tue Jul 12 2022 18:55:00 by
