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.
Dependents: cc3000_hello_world_demo cc3000_simple_socket_demo cc3000_ntp_demo cc3000_ping_demo ... more
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); 00099 } 00100 00101 void cc3000::init(const char *ip, const char *mask, const char *gateway) { 00102 _wlan.start(0); 00103 _netapp.dhcp((uint32_t *)ip, (uint32_t *)mask, (uint32_t *)gateway, (uint32_t *)ip); //dns = ip 00104 _wlan.stop(); 00105 wait(1); 00106 _wlan.start(0); 00107 00108 _status.enabled = 1; 00109 _wlan.set_event_mask(HCI_EVNT_WLAN_UNSOL_INIT | HCI_EVNT_WLAN_KEEPALIVE); 00110 } 00111 00112 int cc3000::connect(unsigned int timeout_ms) { 00113 Timer t; 00114 int ret = 0; 00115 00116 if (_smart_config == false) { 00117 _wlan.ioctl_set_connection_policy(0, 0, 0); 00118 } else { 00119 tUserFS user_info; 00120 get_user_file_info((uint8_t *)&user_info, sizeof(user_info)); 00121 if (user_info.FTC == 1) { 00122 _wlan.ioctl_set_connection_policy(0, 1, 1); 00123 } else { 00124 DBG_CC("Smart config is not set. Please run the first time configuration."); 00125 return -1; 00126 } 00127 } 00128 00129 t.start(); 00130 while (is_connected() == false) { 00131 if (strlen((const char *)_phrase) < 8) { 00132 if (connect_open(_ssid)) { 00133 break; 00134 } 00135 } else { 00136 #ifndef CC3000_TINY_DRIVER 00137 if (connect_secure(_ssid,_phrase, _sec)) { 00138 break; 00139 } 00140 #else 00141 return -1; /* secure connection not supported with TINY_DRIVER */ 00142 #endif 00143 } 00144 00145 if (t.read_ms() > timeout_ms) { 00146 ret = -1; 00147 DBG_CC("Connection to AP failed"); 00148 break; 00149 } 00150 } 00151 00152 while (is_dhcp_configured() == false) 00153 { 00154 if (t.read_ms() > timeout_ms) { 00155 ret = -1; 00156 DBG_CC("Connection to AP failed"); 00157 break; 00158 } 00159 } 00160 00161 return ret; 00162 } 00163 00164 char* cc3000::getMACAddress() { 00165 return mac_addr; 00166 } 00167 00168 char* cc3000::getIPAddress() { 00169 return ip_addr; 00170 } 00171 00172 char* cc3000::getGateway() { 00173 return gateway; 00174 } 00175 00176 char* cc3000::getNetworkMask() { 00177 return networkmask; 00178 } 00179 00180 int cc3000::disconnect(void){ 00181 if (_wlan.disconnect()) { 00182 return -1; 00183 } else { 00184 return 0; 00185 } 00186 } 00187 00188 #endif 00189 00190 void cc3000::usync_callback(int32_t event_type, uint8_t *data, uint8_t length) { 00191 if (event_type == HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE) { 00192 DBG_CC("Callback : HCI_EVNT_WLAN_ASYNC_SIMPLE_CONFIG_DONE"); 00193 _status.smart_config_complete = 1; 00194 _status.stop_smart_config = 1; 00195 } 00196 00197 if (event_type == HCI_EVNT_WLAN_UNSOL_CONNECT) { 00198 DBG_CC("Callback : HCI_EVNT_WLAN_UNSOL_CONNECT"); 00199 _status.connected = 1; 00200 // Connect message is always followed by a DHCP message, connection is not useable until then 00201 _status.dhcp = 0; 00202 } 00203 00204 if (event_type == HCI_EVNT_WLAN_UNSOL_DISCONNECT) { 00205 DBG_CC("Callback : HCI_EVNT_WLAN_UNSOL_DISCONNECT"); 00206 _status.connected = 0; 00207 _status.dhcp = 0; 00208 _status.dhcp_configured = 0; 00209 } 00210 00211 if (event_type == HCI_EVNT_WLAN_UNSOL_DHCP) { 00212 #if (CC3000_ETH_COMPAT == 1) 00213 _socket.inet_ntoa_r ( htonl(*((uint32_t *)(&data[NETAPP_IPCONFIG_IP_OFFSET]))), ip_addr, 17); 00214 _socket.inet_ntoa_r ( htonl(*((uint32_t *)(&data[NETAPP_IPCONFIG_GW_OFFSET]))), gateway, 17); 00215 _socket.inet_ntoa_r ( htonl(*((uint32_t *)(&data[NETAPP_IPCONFIG_SUBNET_OFFSET]))), networkmask, 17); 00216 _socket.inet_ntoa_r ( htonl(*((uint32_t *)(&data[NETAPP_IPCONFIG_MAC_OFFSET]))), mac_addr, 19); 00217 #endif 00218 if (*(data + NETAPP_IPCONFIG_MAC_OFFSET) == 0) { 00219 _status.dhcp = 1; 00220 DBG_CC("Callback : HCI_EVNT_WLAN_UNSOL_DHCP %i.%i.%i.%i", data[3], data[2], data[1], data[0]); 00221 } else { 00222 DBG_CC("Callback : HCI_EVNT_WLAN_UNSOL_DHCP - Disconnecting"); 00223 _status.dhcp = 0; 00224 } 00225 } 00226 00227 if (event_type == HCI_EVENT_CC3000_CAN_SHUT_DOWN) { 00228 // Note this means the modules is idle, so it could be shutdown.. 00229 //DBG_CC("Callback : HCI_EVENT_CC3000_CAN_SHUT_DOWN"); 00230 _status.ok_to_shut_down = 1; 00231 } 00232 00233 if (event_type == HCI_EVNT_WLAN_ASYNC_PING_REPORT) { 00234 DBG_CC("Callback : HCI_EVNT_WLAN_ASYNC_PING_REPORT"); 00235 memcpy(&_ping_report, data, length); 00236 } 00237 00238 if (event_type == HCI_EVNT_BSD_TCP_CLOSE_WAIT) { 00239 uint8_t socketnum = data[0]; 00240 DBG_CC("Callback : HCI_EVNT_BSD_TCP_CLOSE_WAIT - Socket : %d", socketnum); 00241 if (socketnum < MAX_SOCKETS) { 00242 _closed_sockets[socketnum] = true; /* clients socket is closed */ 00243 } 00244 } 00245 } 00246 00247 void cc3000::start_smart_config(const uint8_t *smart_config_key) { 00248 _status.smart_config_complete = 0; 00249 _wlan.ioctl_set_connection_policy(0, 0, 0); 00250 00251 if (_status.connected == 1) { 00252 disconnect(); 00253 } 00254 00255 //Wait until CC3000 is disconected 00256 while (_status.connected == 1) { 00257 wait_us(5); 00258 _event.hci_unsolicited_event_handler(); 00259 } 00260 00261 // Trigger the Smart Config process 00262 _wlan.smart_config_set_prefix(cc3000_prefix); 00263 // Start the Smart Config process with AES disabled 00264 _wlan.smart_config_start(0); 00265 00266 DBG_CC("Waiting for smartconfig to be completed"); 00267 00268 // Wait for Smart config finished 00269 while (_status.smart_config_complete == 0) { 00270 wait_ms(100); 00271 } 00272 00273 DBG_CC("Smartconfig finished"); 00274 00275 #ifndef CC3000_UNENCRYPTED_SMART_CONFIG 00276 // create new entry for AES encryption key 00277 _nvmem.create_entry(NVMEM_AES128_KEY_FILEID, 16); 00278 // write AES key to NVMEM 00279 _security.aes_write_key((uint8_t *)(&smart_config_key[0])); 00280 // Decrypt configuration information and add profile 00281 _wlan.smart_config_process(); 00282 #endif 00283 00284 // Configure to connect automatically to the AP retrieved in the 00285 // Smart config process 00286 _wlan.ioctl_set_connection_policy(0, 0, 1); 00287 00288 // reset the CC3000 00289 _wlan.stop(); 00290 _status.enabled = 0; 00291 wait(5); 00292 _wlan.start(0); 00293 _status.enabled = 1; 00294 00295 // Mask out all non-required events 00296 _wlan.set_event_mask(HCI_EVNT_WLAN_KEEPALIVE | HCI_EVNT_WLAN_UNSOL_INIT); 00297 } 00298 00299 bool cc3000::connect_secure(const uint8_t *ssid, const uint8_t *key, int32_t security_mode) { 00300 #ifdef CC3000_TINY_DRIVER 00301 return false; /* not supported*/ 00302 #else 00303 uint32_t ret; 00304 00305 //_wlan.disconnect(); 00306 wait_ms(3); 00307 ret = _wlan.connect(security_mode, ssid, strlen((const char *)ssid), 0, (uint8_t *)key, strlen((const char *)key)); 00308 if (ret == 0) { /* TODO static internal cc3000 state 0 to TRUE */ 00309 ret = true; 00310 } else { 00311 ret = false; 00312 } 00313 return ret; 00314 #endif 00315 } 00316 00317 bool cc3000::connect_non_blocking(const uint8_t *ssid, const uint8_t *key, int32_t security_mode) 00318 { 00319 bool ret = false; 00320 00321 if (key == 0) { 00322 if (connect_open(ssid)) { 00323 ret = true; 00324 } 00325 } else { 00326 #ifndef CC3000_TINY_DRIVER 00327 if (connect_secure(ssid,key,security_mode)) { 00328 ret = true; 00329 } 00330 #else 00331 /* secure connection not supported with TINY_DRIVER */ 00332 #endif 00333 } 00334 00335 return ret; 00336 } 00337 00338 bool cc3000::connect_to_AP(const uint8_t *ssid, const uint8_t *key, int32_t security_mode) { 00339 Timer t; 00340 bool ret = true; 00341 00342 t.start(); 00343 while (is_connected() == false) { 00344 if (key == 0) { 00345 if (connect_open(ssid)) { 00346 break; 00347 } 00348 } else { 00349 #ifndef CC3000_TINY_DRIVER 00350 if (connect_secure(ssid,key,security_mode)) { 00351 break; 00352 } 00353 #else 00354 return false; /* secure connection not supported with TINY_DRIVER */ 00355 #endif 00356 } 00357 00358 /* timeout 10 seconds */ 00359 if (t.read_ms() > 10000) { 00360 ret = false; 00361 DBG_CC("Connection to AP failed"); 00362 break; 00363 } 00364 } 00365 00366 return ret; 00367 } 00368 00369 void cc3000::start(uint8_t patch) { 00370 _wlan.start(patch); 00371 _status.enabled = 1; 00372 _wlan.set_event_mask(HCI_EVNT_WLAN_UNSOL_INIT | HCI_EVNT_WLAN_KEEPALIVE); 00373 } 00374 00375 void cc3000::stop(void) { 00376 _wlan.stop(); 00377 _status.enabled = 0; 00378 } 00379 00380 void cc3000::restart(uint8_t patch) { 00381 _wlan.stop(); 00382 _status.enabled = 0; 00383 wait_ms(500); 00384 _wlan.start(patch); 00385 _status.enabled = 1; 00386 } 00387 00388 bool cc3000::connect_open(const uint8_t *ssid) { 00389 _wlan.disconnect(); 00390 wait_ms(3); 00391 uint32_t ret; 00392 #ifndef CC3000_TINY_DRIVER 00393 ret = _wlan.connect(0,ssid, strlen((const char *)ssid), 0, 0, 0); 00394 #else 00395 ret = _wlan.connect(ssid, strlen((const char *)ssid)); 00396 #endif 00397 if (ret == 0) { 00398 ret = true; 00399 } else { 00400 ret = false; 00401 } 00402 return ret; 00403 } 00404 00405 bool cc3000::is_enabled() 00406 { 00407 return _status.enabled; 00408 } 00409 00410 bool cc3000::is_connected() { 00411 if (( _status.connected ) && ( _status.dhcp )) { 00412 return 1; 00413 } else { 00414 return 0; 00415 } 00416 } 00417 00418 bool cc3000::is_dhcp_configured() { 00419 return _status.dhcp; 00420 } 00421 00422 bool cc3000::is_smart_confing_completed() { 00423 return _status.smart_config_complete; 00424 } 00425 00426 uint8_t cc3000::get_mac_address(uint8_t address[6]) { 00427 return _nvmem.get_mac_address(address); 00428 } 00429 00430 uint8_t cc3000::set_mac_address(uint8_t address[6]) { 00431 return _nvmem.set_mac_address(address); 00432 } 00433 00434 void cc3000::get_user_file_info(uint8_t *info_file, size_t size) { 00435 _nvmem.read( NVMEM_USER_FILE_1_FILEID, size, 0, info_file); 00436 } 00437 00438 uint8_t cc3000::read_sp_version(uint8_t firmware[2]){ 00439 return _nvmem.read_sp_version(firmware); 00440 } 00441 00442 uint8_t cc3000::write_patch(uint32_t file_id, uint32_t length, const uint8_t *data){ 00443 if(file_id == NVMEM_WLAN_DRIVER_SP_FILEID || file_id == NVMEM_WLAN_FW_SP_FILEID){ 00444 return _nvmem.write_patch(file_id, length, data); 00445 } 00446 else return (1); // error 00447 } 00448 00449 #ifndef CC3000_TINY_DRIVER 00450 bool cc3000::get_ip_config(tNetappIpconfigRetArgs *ip_config) { 00451 if ((_status.dhcp == false) || (_status.connected == false)) { 00452 return false; 00453 } 00454 00455 _netapp.ipconfig(ip_config); 00456 return true; 00457 } 00458 #endif 00459 00460 void cc3000::delete_profiles(void) { 00461 _wlan.ioctl_set_connection_policy(0, 0, 0); 00462 _wlan.ioctl_del_profile(255); 00463 00464 tUserFS user_info; 00465 get_user_file_info((uint8_t *)&user_info, sizeof(user_info)); 00466 user_info.FTC = 0; 00467 set_user_file_info((uint8_t *)&user_info, sizeof(user_info)); 00468 } 00469 00470 void cc3000::set_user_file_info(uint8_t *info_file, size_t size) { 00471 _nvmem.write( NVMEM_USER_FILE_1_FILEID, size, 0, info_file); 00472 } 00473 00474 uint32_t cc3000::ping(uint32_t ip, uint8_t attempts, uint16_t timeout, uint8_t size) { 00475 #ifndef CC3000_TINY_DRIVER 00476 uint32_t reversed_ip = (ip >> 24) | ((ip >> 8) & 0xFF00) | ((ip << 8) & 0xFF0000) | (ip << 24); 00477 00478 _ping_report.packets_received = 0; 00479 if (_netapp.ping_send(&reversed_ip, attempts, size, timeout) == -1) { 00480 DBG_CC("Failed to send ping"); 00481 return 0; 00482 } 00483 wait_ms(timeout*attempts*2); 00484 00485 /* known issue of cc3000 - sent number is send + received */ 00486 // TODO : Remove the Sent/recv'd counts until ti fix the firmware issue? 00487 DBG_CC("Sent: %d",_ping_report.packets_sent); 00488 DBG_CC("Received: %d",_ping_report.packets_received); 00489 DBG_CC("Min time: %d",_ping_report.min_round_time); 00490 DBG_CC("Max time: %d",_ping_report.max_round_time); 00491 DBG_CC("Avg time: %d",_ping_report.avg_round_time); 00492 00493 return _ping_report.packets_received; 00494 #else 00495 return 0; 00496 #endif 00497 } 00498 00499 /* Conversion between uint types and C strings */ 00500 uint8_t* UINT32_TO_STREAM_f (uint8_t *p, uint32_t u32) 00501 { 00502 *(p)++ = (uint8_t)(u32); 00503 *(p)++ = (uint8_t)((u32) >> 8); 00504 *(p)++ = (uint8_t)((u32) >> 16); 00505 *(p)++ = (uint8_t)((u32) >> 24); 00506 return p; 00507 } 00508 00509 00510 uint8_t* UINT16_TO_STREAM_f (uint8_t *p, uint16_t u16) 00511 { 00512 *(p)++ = (uint8_t)(u16); 00513 *(p)++ = (uint8_t)((u16) >> 8); 00514 return p; 00515 } 00516 00517 00518 uint16_t STREAM_TO_UINT16_f(uint8_t *p, uint16_t offset) 00519 { 00520 return (uint16_t)((uint16_t)((uint16_t) 00521 (*(p + offset + 1)) << 8) + (uint16_t)(*(p + offset))); 00522 } 00523 00524 00525 uint32_t STREAM_TO_UINT32_f(uint8_t *p, uint16_t offset) 00526 { 00527 return (uint32_t)((uint32_t)((uint32_t) 00528 (*(p + offset + 3)) << 24) + (uint32_t)((uint32_t) 00529 (*(p + offset + 2)) << 16) + (uint32_t)((uint32_t) 00530 (*(p + offset + 1)) << 8) + (uint32_t)(*(p + offset))); 00531 } 00532 00533 } // mbed_cc3000 namespace 00534
Generated on Tue Jul 12 2022 23:07:36 by
1.7.2
SimpleLink Wi-Fi CC3000
Avnet Wi-Go System