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