Toyomasa Watarai
/
Mbed-example-WS-W27
Mbed Cloud example program for workshop in W27 2018.
Embed:
(wiki syntax)
Show/hide line numbers
WNC14A2AInterface.cpp
Go to the documentation of this file.
00001 /** 00002 * copyright (c) 2017-2018, James Flynn 00003 * SPDX-License-Identifier: Apache-2.0 00004 */ 00005 00006 /* 00007 * Licensed under the Apache License, Version 2.0 (the "License"); 00008 * you may not use this file except in compliance with the License. 00009 * You may obtain a copy of the License at 00010 * 00011 * http://www.apache.org/licenses/LICENSE-2.0 00012 * 00013 * Unless required by applicable law or agreed to in writing, software 00014 * distributed under the License is distributed on an "AS IS" BASIS, 00015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00016 * 00017 * See the License for the specific language governing permissions and 00018 * limitations under the License. 00019 * 00020 */ 00021 00022 /** 00023 * @file WNC14A2AInterface.cpp 00024 * @brief WNC14A2A implementation of NetworkInterfaceAPI for Mbed OS 00025 * 00026 * @author James Flynn 00027 * 00028 * @date 1-Feb-2018 00029 */ 00030 00031 #include "WNC14A2AInterface.h" 00032 #include <Thread.h> 00033 #include "mbed_events.h" 00034 #include "WNCIO.h" 00035 00036 #include <string> 00037 #include <ctype.h> 00038 00039 #define WNC_DEBUG 0 //1=enable the WNC startup debug output 00040 //0=disable the WNC startup debug output 00041 #define STOP_ON_FE 1 //1=hang forever if a fatal error occurs 00042 //0=simply return failed response for all socket calls 00043 #define DISPLAY_FE 1 //1 to display the fatal error when it occurs 00044 //0 to NOT display the fatal error 00045 #define RESETON_FE 0 //1 to cause the MCU to reset on fatal error 00046 //0 to NOT reset the MCU 00047 00048 /** Error Handling macros & data 00049 * @brief The macros CHK_WNCFE is used to check if a fatal error has occured. If it has 00050 * then execute the action specified: fail, void, null, resume 00051 * 00052 * CHK_WNCFE( condition-to-check, fail|void|null|resume ) 00053 * 00054 * 'fail' if you want FATAL_WNC_ERROR to be called. 00055 * 'void' if you want to execute a void return 00056 * 'null' if you want to execute a null return 00057 * 'resume' if you simply want to resume program execution 00058 * 00059 * There are several settings that control how FATAL_WNC_ERROR behaves: 00060 * 1) RESETON_FE determines if the system will reset or hang. 00061 * 2) DISPLAY_FE determine if an error message is generated or not 00062 * 00063 * The DISPLAY_FE setting determines if a failure message is displayed. 00064 * If set to 1, user sees this messageo: 00065 * 00066 * WNC FAILED @ source-file-name:source-file-line-number 00067 * 00068 * if not set, nothing is displayed. 00069 */ 00070 00071 #define FATAL_FLAG WncController::WNC_NO_RESPONSE 00072 #define WNC_GOOD WncController::WNC_ON 00073 00074 #define RETfail return -1 00075 #define RETvoid return 00076 #define RETnull return NULL 00077 #define RETresume 00078 00079 #define DORET(x) RET##x 00080 00081 #define TOSTR(x) #x 00082 #define INTSTR(x) TOSTR(x) 00083 #define FATAL_STR (char*)(__FILE__ ":" INTSTR(__LINE__)) 00084 00085 #if RESETON_FE == 1 //reset on fatal error 00086 #define MCURESET ((*((volatile unsigned long *)0xE000ED0CU))=(unsigned long)((0x5fa<<16) | 0x04L)) 00087 #define RSTMSG "RESET MCU! " 00088 #else 00089 #define MCURESET 00090 #define RSTMSG "" 00091 #endif 00092 00093 #if DISPLAY_FE == 1 //display fatal error message 00094 #define PFE {if(_debugUart)_debugUart->printf((char*)RSTMSG "\r\n>>WNC FAILED @ %s\r\n", FATAL_STR);} 00095 #else 00096 #define PFE 00097 #endif 00098 00099 #if STOP_ON_FE == 1 //halt cpu on fatal error 00100 #define FATAL_WNC_ERROR(v) {_fatal_err_loc=FATAL_STR;PFE;MCURESET;while(1);} 00101 #else 00102 #define FATAL_WNC_ERROR(v) {_fatal_err_loc=FATAL_STR;PFE;DORET(v);} 00103 #endif 00104 00105 #define CHK_WNCFE(x,y) if( x ){FATAL_WNC_ERROR(y);} 00106 00107 // 00108 // Define different levels of debug output 00109 // 00110 #define DBGMSG_DRV 0x04 //driver enter/exit info 00111 #define DBGMSG_EQ 0x08 //driver event queue info 00112 #define DBGMSG_SMS 0x10 //driver SMS info 00113 #define DBGMSG_ARRY 0x20 //dump driver arrays 00114 00115 #define WNC14A2A_READ_TIMEOUTMS 4000 //duration to read no data to receive in MS 00116 #define WNC14A2A_COMMUNICATION_TIMEOUT 100 //how long (ms) to wait for a WNC14A2A connect response 00117 #define WNC_BUFF_SIZE 1500 //total number of bytes in a single WNC call 00118 #define UART_BUFF_SIZE 4096 //size of our internal uart buffer.. define in *.json file 00119 00120 #define EQ_FREQ 250 //frequency in ms to check for Tx/Rx data 00121 #define EQ_FREQ_SLOW 2000 //frequency in ms to check when in slow monitor mode 00122 00123 // 00124 // The WNC device does not generate interrutps on received data, so this software polls 00125 // for data availablility. To implement a non-blocking mode, simulate interrupts using 00126 // mbed OS Event Queues. These Constants are used to manage the Rx/Tx states. 00127 // 00128 #define READ_INIT 10 00129 #define READ_START 11 00130 #define READ_ACTIVE 12 00131 #define DATA_AVAILABLE 13 00132 #define TX_IDLE 20 00133 #define TX_STARTING 21 00134 #define TX_ACTIVE 22 00135 #define TX_COMPLETE 23 00136 00137 #if MBED_CONF_APP_WNC_DEBUG == true 00138 #define debugOutput(...) WNC14A2AInterface::_dbOut(__VA_ARGS__) 00139 #define debugDump_arry(...) WNC14A2AInterface::_dbDump_arry(__VA_ARGS__) 00140 #else 00141 #define debugOutput(...) {/* __VA_ARGS__ */} 00142 #define debugDump_arry(...) {/* __VA_ARGS__ */} 00143 #endif 00144 00145 /* Constructor 00146 * 00147 * @brief May be invoked with or without the debug pointer. 00148 * @note After the constructor has completed, call check 00149 * m_errors to determine if any errors occured. Possible values: 00150 * NSAPI_ERROR_UNSUPPORTED 00151 * NSAPI_ERROR_DEVICE_ERROR 00152 */ 00153 WNC14A2AInterface::WNC14A2AInterface(WNCDebug *dbg) : 00154 m_wncpoweredup(0), 00155 m_debug(0), 00156 m_pwnc(NULL), 00157 m_errors(NSAPI_ERROR_OK), 00158 m_smsmoning(0), 00159 _active_socket(0), 00160 mdmUart(MBED_CONF_WNC14A2A_LIBRARY_WNC_TXD,MBED_CONF_WNC14A2A_LIBRARY_WNC_RXD,115200), 00161 wnc_io(&mdmUart) 00162 { 00163 _debugUart = dbg; 00164 memset(_mac_address,0x00,sizeof(_mac_address)); 00165 memset(_socTxS,0x00,sizeof(_socTxS)); 00166 memset(_socRxS,0x00,sizeof(_socRxS)); 00167 for( unsigned int i=0; i<WNC14A2A_SOCKET_COUNT; i++ ) { 00168 _sockets[i].socket = i; 00169 _sockets[i].addr = NULL; 00170 _sockets[i].opened=false; 00171 00172 _sockets[i].connected=false; 00173 _sockets[i].proto=1; 00174 _socRxS[i].m_rx_socket=i; 00175 _socTxS[i].m_tx_socket=i; 00176 } 00177 } 00178 00179 //! Standard destructor 00180 WNC14A2AInterface::~WNC14A2AInterface() 00181 { 00182 if( m_pwnc ) 00183 delete m_pwnc; //free the existing WncControllerK64F object 00184 } 00185 00186 // - - - - - - - 00187 // SMS Functions 00188 // - - - - - - - 00189 00190 char* WNC14A2AInterface::getSMSnbr( void ) 00191 { 00192 char * ret=NULL; 00193 string iccid_str; 00194 static string msisdn_str; 00195 00196 if( !m_pwnc ) { 00197 m_errors=NSAPI_ERROR_DEVICE_ERROR; 00198 return NULL; 00199 } 00200 CHK_WNCFE(( m_pwnc->getWncStatus() == FATAL_FLAG ), null); 00201 00202 _pwnc_mutex.lock(); 00203 if( !m_pwnc->getICCID(&iccid_str) ) { 00204 _pwnc_mutex.unlock(); 00205 return ret; 00206 } 00207 00208 if( m_pwnc->convertICCIDtoMSISDN(iccid_str, &msisdn_str) ) 00209 ret = (char*)msisdn_str.c_str(); 00210 _pwnc_mutex.unlock(); 00211 return ret; 00212 } 00213 00214 void WNC14A2AInterface::sms_attach(void (*callback)(IOTSMS *)) 00215 { 00216 debugOutput("ENTER/EXIT sms_attach()"); 00217 _sms_cb = callback; 00218 } 00219 00220 void WNC14A2AInterface::sms_start(void) 00221 { 00222 _pwnc_mutex.lock(); 00223 m_pwnc->deleteSMSTextFromMem('*'); 00224 _pwnc_mutex.unlock(); 00225 } 00226 00227 void WNC14A2AInterface::sms_listen(uint16_t pp) 00228 { 00229 debugOutput("ENTER sms_listen(%d)",pp); 00230 00231 if( m_smsmoning ) 00232 m_smsmoning = false; 00233 if( pp < 1) 00234 pp = 30; 00235 00236 debugOutput("setup sms_listen event queue"); 00237 _smsThread.start(callback(&sms_queue,&EventQueue::dispatch_forever)); 00238 00239 sms_start(); 00240 sms_queue.call_every(pp*1000, mbed::Callback<void()>((WNC14A2AInterface*)this,&WNC14A2AInterface::handle_sms_event)); 00241 00242 m_smsmoning = true; 00243 debugOutput("EXIT sms_listen()"); 00244 } 00245 00246 void WNC14A2AInterface::handle_sms_event() 00247 { 00248 int msgs_available; 00249 debugOutput("ENTER handle_sms_event()"); 00250 00251 if ( _sms_cb && m_smsmoning ) { 00252 _pwnc_mutex.lock(); 00253 msgs_available = m_pwnc->readUnreadSMSText(&m_smsmsgs, true); 00254 _pwnc_mutex.unlock(); 00255 if( msgs_available ) { 00256 debugOutput("Have %d unread texts present",m_smsmsgs.msgCount); 00257 for( int i=0; i< m_smsmsgs.msgCount; i++ ) { 00258 m_MsgText.number = m_smsmsgs.e[i].number; 00259 m_MsgText.date = m_smsmsgs.e[i].date; 00260 m_MsgText.time = m_smsmsgs.e[i].time; 00261 m_MsgText.msg = m_smsmsgs.e[i].msg; 00262 _sms_cb(&m_MsgText); 00263 } 00264 } 00265 } 00266 debugOutput("EXIT handle_sms_event"); 00267 } 00268 00269 int WNC14A2AInterface::getSMS(IOTSMS **pmsg) 00270 { 00271 int msgs_available=0; 00272 00273 debugOutput("ENTER getSMS()"); 00274 if( !m_pwnc ) 00275 m_errors=NSAPI_ERROR_DEVICE_ERROR; 00276 else{ 00277 CHK_WNCFE((m_pwnc->getWncStatus()==FATAL_FLAG), fail); 00278 _pwnc_mutex.lock(); 00279 msgs_available = m_pwnc->readUnreadSMSText(&m_smsmsgs, true); 00280 _pwnc_mutex.unlock(); 00281 } 00282 00283 if( msgs_available ) { 00284 debugOutput("Have %d unread texts present",m_smsmsgs.msgCount); 00285 for( int i=0; i< m_smsmsgs.msgCount; i++ ) { 00286 m_MsgText_array[i].number = m_smsmsgs.e[i].number; 00287 m_MsgText_array[i].date = m_smsmsgs.e[i].date; 00288 m_MsgText_array[i].time = m_smsmsgs.e[i].time; 00289 m_MsgText_array[i].msg = m_smsmsgs.e[i].msg; 00290 pmsg[i] = (IOTSMS*)&m_MsgText_array[i]; 00291 } 00292 msgs_available = m_smsmsgs.msgCount; 00293 } 00294 debugOutput("EXIT getSMS"); 00295 return msgs_available; 00296 } 00297 00298 00299 int WNC14A2AInterface::sendIOTSms(const string& number, const string& message) 00300 { 00301 debugOutput("ENTER sendIOTSms(%s,%s)",number.c_str(), message.c_str()); 00302 00303 if( !m_pwnc ) 00304 return (m_errors=NSAPI_ERROR_DEVICE_ERROR); 00305 CHK_WNCFE((m_pwnc->getWncStatus()==FATAL_FLAG), fail); 00306 00307 _pwnc_mutex.lock(); 00308 int i = m_pwnc->sendSMSText((char*)number.c_str(), message.c_str()); 00309 _pwnc_mutex.unlock(); 00310 00311 debugOutput("EXIT sendIOTSms(%s,%s)",number.c_str(), message.c_str()); 00312 return i; 00313 } 00314 00315 00316 // - - - - - - - - - - - 00317 // WNC Control Functions 00318 // - - - - - - - - - - - 00319 00320 nsapi_error_t WNC14A2AInterface::connect() //can be called with no arguments or with arguments 00321 { 00322 debugOutput("ENTER connect(void)"); 00323 return connect(NULL,NULL,NULL); 00324 } 00325 00326 nsapi_error_t WNC14A2AInterface::connect(const char *apn, const char *username, const char *password) 00327 { 00328 // 00329 // GPIO Pins used to initialize the WNC parts on the Avnet WNC Shield 00330 // 00331 // on powerup, 0 = boot mode, 1 = normal boot 00332 // 0=let modem sleep, 1=keep modem awake -- Note: pulled high on shield 00333 // active high 00334 // 0 = disabled (all signals high impedence, 1 = translation active 00335 // WNC doesn't utilize RTS/CTS but the pin is connected 00336 00337 static DigitalOut mdm_uart2_rx_boot_mode_sel(MBED_CONF_WNC14A2A_LIBRARY_WNC_RX_BOOT_SEL); 00338 static DigitalOut mdm_power_on(MBED_CONF_WNC14A2A_LIBRARY_WNC_POWER_ON); 00339 static DigitalOut mdm_wakeup_in(MBED_CONF_WNC14A2A_LIBRARY_WNC_WAKEUP); 00340 static DigitalOut mdm_reset(MBED_CONF_WNC14A2A_LIBRARY_WNC_RESET); 00341 static DigitalOut shield_3v3_1v8_sig_trans_ena(MBED_CONF_WNC14A2A_LIBRARY_WNC_LVLTRANSLATOR); 00342 static DigitalOut mdm_uart1_cts(MBED_CONF_WNC14A2A_LIBRARY_WNC_CTS); 00343 00344 //! associations for the controller class to use. Order of pins is critical. 00345 static WncControllerK64F_fk::WncGpioPinListK64F wncPinList = { 00346 &mdm_uart2_rx_boot_mode_sel, 00347 &mdm_power_on, 00348 &mdm_wakeup_in, 00349 &mdm_reset, 00350 &shield_3v3_1v8_sig_trans_ena, 00351 &mdm_uart1_cts 00352 }; 00353 00354 debugOutput("ENTER connect(apn,user,pass)"); 00355 00356 if( m_pwnc == NULL ) { 00357 m_pwnc = new WncControllerK64F_fk::WncControllerK64F(&wncPinList, &wnc_io, _debugUart); 00358 if( !m_pwnc ) { 00359 debugOutput("FAILED to open WncControllerK64!"); 00360 m_errors = NSAPI_ERROR_DEVICE_ERROR; 00361 return NSAPI_ERROR_NO_MEMORY; 00362 } 00363 CHK_WNCFE((m_pwnc->getWncStatus()==FATAL_FLAG), fail); 00364 #if MBED_CONF_APP_WNC_DEBUG == true 00365 m_pwnc->enableDebug( (MBED_CONF_APP_WNC_DEBUG_SETTING&1), (MBED_CONF_APP_WNC_DEBUG_SETTING&2) ); 00366 #endif 00367 } 00368 00369 _eqThread.start(callback(&wnc_queue,&EventQueue::dispatch_forever)); 00370 00371 if (!apn) 00372 apn = "m2m.com.attz"; 00373 00374 _pwnc_mutex.lock(); 00375 if (!m_wncpoweredup) { 00376 debugOutput("call powerWncOn(%s,40)",apn); 00377 m_wncpoweredup=m_pwnc->powerWncOn(apn,40); 00378 m_errors = m_wncpoweredup? 1:0; 00379 } 00380 else { //powerWncOn already called, set a new APN 00381 debugOutput("set APN=%s",apn); 00382 m_errors = m_pwnc->setApnName(apn)? 1:0; 00383 } 00384 00385 m_errors |= m_pwnc->getWncNetworkingStats(&myNetStats)? 2:0; 00386 _pwnc_mutex.unlock(); 00387 00388 debugOutput("EXIT connect (%02X)",m_errors); 00389 return (!m_errors)? NSAPI_ERROR_NO_CONNECTION : NSAPI_ERROR_OK; 00390 } 00391 00392 const char* WNC14A2AInterface::getWNCRev(void) 00393 { 00394 if( m_pwnc ) { 00395 const char * str = m_pwnc->getFirmRev(); 00396 return &str[12]; 00397 } 00398 else 00399 return NULL; 00400 } 00401 00402 00403 const char *WNC14A2AInterface::get_ip_address() 00404 { 00405 const char *ptr=NULL; 00406 00407 if( !m_pwnc ) { 00408 m_errors=NSAPI_ERROR_DEVICE_ERROR; 00409 return ptr; 00410 } 00411 CHK_WNCFE((m_pwnc->getWncStatus()==FATAL_FLAG), null); 00412 00413 _pwnc_mutex.lock(); 00414 if ( m_pwnc->getWncNetworkingStats(&myNetStats) ) { 00415 _pwnc_mutex.unlock(); 00416 ptr = &myNetStats.ip[0]; 00417 } 00418 else{ 00419 _pwnc_mutex.unlock(); 00420 m_errors=NSAPI_ERROR_NO_CONNECTION; 00421 } 00422 return ptr; 00423 } 00424 00425 const char *WNC14A2AInterface::get_mac_address() 00426 { 00427 string mac, str; 00428 debugOutput("ENTER get_mac_address()"); 00429 00430 if( m_pwnc ) { 00431 CHK_WNCFE((m_pwnc->getWncStatus()==FATAL_FLAG), null); 00432 _pwnc_mutex.lock(); 00433 if( m_pwnc->getICCID(&str) ) { 00434 _pwnc_mutex.unlock(); 00435 mac = str.substr(3,20); 00436 mac[2]=mac[5]=mac[8]=mac[11]=mac[14]=':'; 00437 strncpy(_mac_address, mac.c_str(), mac.length()); 00438 debugOutput("EXIT get_mac_address() - %s",_mac_address); 00439 return _mac_address; 00440 } 00441 _pwnc_mutex.unlock(); 00442 } 00443 debugOutput("EXIT get_mac_address() - NULL"); 00444 return NULL; 00445 } 00446 00447 NetworkStack *WNC14A2AInterface::get_stack() { 00448 debugOutput("ENTER/EXIT get_stack()"); 00449 return this; 00450 } 00451 00452 nsapi_error_t WNC14A2AInterface::disconnect() 00453 { 00454 debugOutput("ENTER/EXIT disconnect()"); 00455 return NSAPI_ERROR_OK; 00456 } 00457 00458 nsapi_error_t WNC14A2AInterface::set_credentials(const char *apn, const char *username, const char *password) 00459 { 00460 00461 m_errors=NSAPI_ERROR_OK; 00462 debugOutput("ENTER set_credentials()"); 00463 00464 if( !m_pwnc ) 00465 return (m_errors=NSAPI_ERROR_DEVICE_ERROR); 00466 CHK_WNCFE((m_pwnc->getWncStatus()==FATAL_FLAG), fail); 00467 00468 if( !apn ) 00469 return (m_errors=NSAPI_ERROR_PARAMETER); 00470 00471 _pwnc_mutex.lock(); 00472 if( !m_pwnc->setApnName(apn) ) 00473 m_errors=NSAPI_ERROR_DEVICE_ERROR; 00474 _pwnc_mutex.unlock(); 00475 debugOutput("EXIT set_credentials()"); 00476 return m_errors; 00477 } 00478 00479 bool WNC14A2AInterface::registered() 00480 { 00481 debugOutput("ENTER registered()"); 00482 m_errors=NSAPI_ERROR_OK; 00483 00484 if( !m_pwnc ) { 00485 return (m_errors=NSAPI_ERROR_DEVICE_ERROR); 00486 } 00487 CHK_WNCFE((m_pwnc->getWncStatus()==FATAL_FLAG), fail); 00488 00489 _pwnc_mutex.lock(); 00490 if ( m_pwnc->getWncStatus() != WNC_GOOD ) 00491 m_errors=NSAPI_ERROR_NO_CONNECTION; 00492 _pwnc_mutex.unlock(); 00493 00494 debugOutput("EXIT registered()"); 00495 return (m_errors==NSAPI_ERROR_OK); 00496 } 00497 00498 00499 void WNC14A2AInterface::doDebug( int v ) 00500 { 00501 #if MBED_CONF_APP_WNC_DEBUG == true 00502 m_debug= v; 00503 debugOutput("SET debug flag to 0x%02X",v); 00504 #endif 00505 } 00506 00507 /** function to dump a user provided array. 00508 * 00509 * @author James Flynn 00510 * @param data pointer to the data array to dump 00511 * @param size number of bytes to dump 00512 * @return void 00513 * @date 1-Feb-2018 00514 */ 00515 void WNC14A2AInterface::_dbDump_arry( const uint8_t* data, unsigned int size ) 00516 { 00517 #if MBED_CONF_APP_WNC_DEBUG == true 00518 char buffer[256]; 00519 unsigned int i, k; 00520 00521 if( _debugUart != NULL && (m_debug & DBGMSG_ARRY) ) { 00522 for (i=0; i<size; i+=16) { 00523 sprintf(buffer,"[WNC Driver]:0x%04X: ",i); 00524 _debugUart->puts(buffer); 00525 for (k=0; k<16; k++) { 00526 sprintf(buffer, "%02X ", data[i+k]); 00527 _debugUart->puts(buffer); 00528 } 00529 _debugUart->puts(" -- "); 00530 for (k=0; k<16; k++) { 00531 sprintf(buffer, "%2c", isprint(data[i+k])? data[i+k]:'.'); 00532 _debugUart->puts(buffer); 00533 } 00534 _debugUart->puts("\n\r"); 00535 } 00536 } 00537 #endif 00538 } 00539 00540 void WNC14A2AInterface::_dbOut(const char *format, ...) 00541 { 00542 #if MBED_CONF_APP_WNC_DEBUG == true 00543 char buffer[256]; 00544 00545 sprintf(buffer,"[WNC Driver]: "); 00546 if( _debugUart != NULL && (m_debug & (DBGMSG_DRV|DBGMSG_EQ|DBGMSG_SMS)) ) { 00547 va_list args; 00548 va_start (args, format); 00549 _debugUart->puts(buffer); 00550 if( m_debug & DBGMSG_DRV ) 00551 vsnprintf(buffer, sizeof(buffer), format, args); 00552 if( m_debug & DBGMSG_EQ ) 00553 vsnprintf(buffer, sizeof(buffer), format, args); 00554 if( m_debug & DBGMSG_SMS ) 00555 vsnprintf(buffer, sizeof(buffer), format, args); 00556 _debugUart->puts(buffer); 00557 _debugUart->putc('\n'); 00558 va_end (args); 00559 } 00560 #endif 00561 } 00562 00563 // - - - - - - - - - - - - - - - 00564 // WNC Socket Based operatioins 00565 // - - - - - - - - - - - - - - - 00566 00567 nsapi_error_t WNC14A2AInterface::gethostbyname(const char* name, SocketAddress *address, nsapi_version_t version) 00568 { 00569 nsapi_error_t ret = NSAPI_ERROR_OK; 00570 char ipAddrStr[25]; 00571 00572 debugOutput("ENTER gethostbyname(); IP=%s; PORT=%d; URL=%s;", address->get_ip_address(), address->get_port(), name); 00573 00574 if( !m_pwnc ) 00575 return (m_errors=NSAPI_ERROR_DEVICE_ERROR); 00576 CHK_WNCFE((m_pwnc->getWncStatus()==FATAL_FLAG), fail); 00577 00578 memset(ipAddrStr,0x00,sizeof(ipAddrStr)); 00579 00580 //Execute DNS query. 00581 _pwnc_mutex.lock(); 00582 if( !m_pwnc->resolveUrl(_active_socket, name) ) 00583 ret = m_errors = NSAPI_ERROR_DEVICE_ERROR; 00584 00585 //Get IP address that the URL was resolved to 00586 if( !m_pwnc->getIpAddr(_active_socket, ipAddrStr) ) 00587 ret = m_errors = NSAPI_ERROR_DEVICE_ERROR; 00588 _pwnc_mutex.unlock(); 00589 00590 address->set_ip_address(ipAddrStr); 00591 00592 debugOutput("EXIT gethostbyname(); IP=%s; PORT=%d; URL=%s;", address->get_ip_address(), address->get_port(), name); 00593 return (m_errors = ret); 00594 } 00595 00596 int WNC14A2AInterface::socket_open(void **handle, nsapi_protocol_t proto) 00597 { 00598 unsigned int i; 00599 00600 debugOutput("ENTER socket_open()"); 00601 00602 //find the next available socket... 00603 for( i=0; i<WNC14A2A_SOCKET_COUNT; i++ ) 00604 if( !_sockets[i].opened ) 00605 break; 00606 00607 if( i == WNC14A2A_SOCKET_COUNT ) { 00608 m_errors=NSAPI_ERROR_NO_SOCKET; 00609 return -1; 00610 } 00611 00612 _sockets[i].socket = i; //save index later 00613 _sockets[i].opened = true; 00614 _sockets[i].connected=false; 00615 _sockets[i].proto = (proto==NSAPI_UDP)?0:1; 00616 _sockets[i]._callback = NULL; 00617 _sockets[i]._cb_data = NULL; 00618 00619 _socRxS[i].m_rx_wnc_state = READ_START; 00620 _socRxS[i].m_rx_disTO = false; 00621 _socTxS[i].m_tx_wnc_state = TX_IDLE; 00622 00623 *handle = &_sockets[i]; 00624 00625 debugOutput("EXIT socket_open; Socket=%d, OPEN=%s, protocol =%s", 00626 i, _sockets[i].opened?"YES":"NO", (!_sockets[i].proto)?"UDP":"TCP"); 00627 00628 return (m_errors = NSAPI_ERROR_OK); 00629 } 00630 00631 int WNC14A2AInterface::socket_connect(void *handle, const SocketAddress &address) 00632 { 00633 WNCSOCKET *wnc = (WNCSOCKET *)handle; 00634 int err = 0; 00635 00636 debugOutput("ENTER socket_connect(); Socket=%d; IP=%s; PORT=%d;", wnc->socket, address.get_ip_address(), address.get_port()); 00637 00638 if (!wnc->opened ) 00639 return (m_errors = NSAPI_ERROR_NO_SOCKET); 00640 00641 wnc->addr = address; 00642 00643 _pwnc_mutex.lock(); 00644 if( wnc->url.empty() ) 00645 err = !m_pwnc->openSocketIpAddr(wnc->socket, address.get_ip_address(), address.get_port(), wnc->proto, WNC14A2A_COMMUNICATION_TIMEOUT); 00646 else 00647 err = !m_pwnc->openSocketUrl(wnc->socket, wnc->url.c_str(), wnc->addr.get_port(), wnc->proto); 00648 _pwnc_mutex.unlock(); 00649 00650 if( !err ) { 00651 wnc->connected = true; 00652 _socRxS[wnc->socket].m_rx_wnc_state = READ_START; 00653 _socTxS[wnc->socket].m_tx_wnc_state = TX_IDLE; 00654 00655 if( wnc->_callback != NULL ) 00656 wnc->_callback( wnc->_cb_data ); 00657 } 00658 00659 return err; 00660 } 00661 00662 int WNC14A2AInterface::socket_close(void *handle) 00663 { 00664 WNCSOCKET *wnc = (WNCSOCKET*)handle; 00665 RXEVENT *rxsock; 00666 TXEVENT *txsock; 00667 bool err = false; 00668 00669 debugOutput("ENTER socket_close()"); 00670 00671 rxsock = &_socRxS[wnc->socket]; 00672 txsock = &_socTxS[wnc->socket]; 00673 00674 txsock->m_tx_wnc_state = TX_IDLE; //reset TX state 00675 if( rxsock->m_rx_wnc_state != READ_START ) { //reset RX state 00676 rxsock->m_rx_disTO=false; 00677 while( rxsock->m_rx_wnc_state != DATA_AVAILABLE ) 00678 wait(1); //someone called close while a read was happening 00679 } 00680 00681 _pwnc_mutex.lock(); 00682 if( !m_pwnc->closeSocket(wnc->socket) ) { 00683 m_errors = NSAPI_ERROR_DEVICE_ERROR; 00684 err = true; 00685 } 00686 _pwnc_mutex.unlock(); 00687 00688 if( !err ) { 00689 wnc->opened = false; //no longer in use 00690 wnc->addr = NULL; //not open 00691 wnc->connected= false; 00692 wnc->proto = 1; //assume TCP for now 00693 m_errors = NSAPI_ERROR_OK; 00694 wnc->_cb_data = NULL; 00695 wnc->_callback= NULL; 00696 } 00697 00698 debugOutput("EXIT socket_close()"); 00699 return err; 00700 } 00701 00702 00703 void WNC14A2AInterface::socket_attach(void *handle, void (*callback)(void *), void *data) 00704 { 00705 WNCSOCKET *wnc = (WNCSOCKET *)handle; 00706 00707 debugOutput("ENTER/EXIT socket_attach()"); 00708 wnc->_callback = callback; 00709 wnc->_cb_data = data; 00710 } 00711 00712 int WNC14A2AInterface::socket_sendto(void *handle, const SocketAddress &address, const void *data, unsigned size) 00713 { 00714 WNCSOCKET *wnc = (WNCSOCKET *)handle; 00715 00716 debugOutput("ENTER socket_sendto()"); 00717 00718 if (!wnc->connected) { 00719 int err = socket_connect(wnc, address); 00720 if (err < 0) 00721 return err; 00722 } 00723 wnc->addr = address; 00724 00725 debugOutput("EXIT socket_sendto()"); 00726 return socket_send(wnc, data, size); 00727 } 00728 00729 int WNC14A2AInterface::socket_recvfrom(void *handle, SocketAddress *address, void *buffer, unsigned size) 00730 { 00731 WNCSOCKET *wnc = (WNCSOCKET *)handle; 00732 debugOutput("ENTER socket_recvfrom()"); 00733 00734 if (!wnc->connected) { 00735 debugOutput("need to open a WNC socket first"); 00736 int err = socket_connect(wnc, *address); 00737 if (err < 0) 00738 return err; 00739 } 00740 00741 int ret = socket_recv(wnc, (char *)buffer, size); 00742 if (ret >= 0 && address) 00743 *address = wnc->addr; 00744 debugOutput("EXIT socket_recvfrom()"); 00745 return ret; 00746 } 00747 00748 00749 int inline WNC14A2AInterface::socket_accept(nsapi_socket_t server, nsapi_socket_t *handle, SocketAddress *address) 00750 { 00751 debugOutput("ENTER/EXIT socket_accept() -- not supported"); 00752 m_errors = NSAPI_ERROR_UNSUPPORTED; 00753 return -1; 00754 } 00755 00756 int inline WNC14A2AInterface::socket_bind(void *handle, const SocketAddress &address) 00757 { 00758 WNCSOCKET *wnc = (WNCSOCKET *)handle; 00759 00760 debugOutput("ENTER/EXIT socket_bind(), use address '%s', port %d", address.get_ip_address(),address.get_port()); 00761 _socRxS[wnc->socket].m_rx_disTO=true; //for us, simply disable the Rx timeout to keep monitoring for data 00762 return (m_errors = NSAPI_ERROR_OK); 00763 } 00764 00765 00766 int inline WNC14A2AInterface::socket_listen(void *handle, int backlog) 00767 { 00768 debugOutput("ENTER/EXIT socket_listen() -- not supported"); 00769 m_errors = NSAPI_ERROR_UNSUPPORTED; 00770 return -1; 00771 } 00772 00773 00774 int WNC14A2AInterface::socket_send(void *handle, const void *data, unsigned size) 00775 { 00776 WNCSOCKET *wnc = (WNCSOCKET *)handle; 00777 TXEVENT *txsock; 00778 00779 debugOutput("ENTER socket_send() send %d bytes",size); 00780 txsock = &_socTxS[wnc->socket]; 00781 00782 if( size < 1 || data == NULL ) // should never happen but have seen it 00783 return 0; 00784 00785 switch( txsock->m_tx_wnc_state ) { 00786 case TX_IDLE: 00787 txsock->m_tx_wnc_state = TX_STARTING; 00788 debugDump_arry((const uint8_t*)data,size); 00789 txsock->m_tx_dptr = (uint8_t*)data; 00790 txsock->m_tx_orig_size = size; 00791 txsock->m_tx_req_size = (uint32_t)size; 00792 txsock->m_tx_total_sent= 0; 00793 txsock->m_tx_callback = wnc->_callback; 00794 txsock->m_tx_cb_data = wnc->_cb_data; 00795 00796 if( txsock->m_tx_req_size > UART_BUFF_SIZE ) 00797 txsock->m_tx_req_size= UART_BUFF_SIZE; 00798 00799 if( !tx_event(txsock) ) { //if we didn't sent all the data at once, continue in background 00800 txsock->m_tx_wnc_state = TX_ACTIVE; 00801 wnc_queue.call_in(EQ_FREQ,mbed::Callback<void()>((WNC14A2AInterface*)this,&WNC14A2AInterface::wnc_eq_event)); 00802 return NSAPI_ERROR_WOULD_BLOCK; 00803 } 00804 // fall through 00805 00806 case TX_COMPLETE: 00807 debugOutput("EXIT socket_send(), sent %d bytes", txsock->m_tx_total_sent); 00808 txsock->m_tx_wnc_state = TX_IDLE; 00809 return txsock->m_tx_total_sent; 00810 00811 case TX_ACTIVE: 00812 case TX_STARTING: 00813 return NSAPI_ERROR_WOULD_BLOCK; 00814 00815 default: 00816 debugOutput("EXIT socket_send(), NSAPI_ERROR_DEVICE_ERROR"); 00817 return (m_errors = NSAPI_ERROR_DEVICE_ERROR); 00818 } 00819 } 00820 00821 int WNC14A2AInterface::tx_event(TXEVENT *ptr) 00822 { 00823 debugOutput("ENTER tx_event(), socket %d",ptr->m_tx_socket); 00824 00825 _pwnc_mutex.lock(); 00826 if( m_pwnc->write(ptr->m_tx_socket, ptr->m_tx_dptr, ptr->m_tx_req_size) ) 00827 ptr->m_tx_total_sent += ptr->m_tx_req_size; 00828 _pwnc_mutex.unlock(); 00829 00830 if( ptr->m_tx_total_sent < ptr->m_tx_orig_size ) { 00831 ptr->m_tx_dptr += ptr->m_tx_req_size; 00832 ptr->m_tx_req_size = ptr->m_tx_orig_size-ptr->m_tx_total_sent; 00833 00834 if( ptr->m_tx_req_size > UART_BUFF_SIZE) 00835 ptr->m_tx_req_size= UART_BUFF_SIZE; 00836 00837 debugOutput("EXIT tx_event(), send %d more bytes.",ptr->m_tx_req_size); 00838 return 0; 00839 } 00840 debugOutput("EXIT tx_event, socket %d, data sent",ptr->m_tx_socket); 00841 ptr->m_tx_wnc_state = TX_COMPLETE; 00842 if( ptr->m_tx_callback != NULL ) 00843 ptr->m_tx_callback( ptr->m_tx_cb_data ); 00844 ptr->m_tx_cb_data = NULL; 00845 ptr->m_tx_callback = NULL; 00846 00847 return 1; 00848 } 00849 00850 int WNC14A2AInterface::socket_recv(void *handle, void *data, unsigned size) 00851 { 00852 WNCSOCKET *wnc = (WNCSOCKET *)handle; 00853 RXEVENT *rxsock; 00854 00855 rxsock = &_socRxS[wnc->socket]; 00856 debugOutput("ENTER socket_recv(), socket %d, request %d bytes",wnc->socket, size); 00857 00858 if( size < 1 || data == NULL ) { // should never happen 00859 return 0; 00860 } 00861 00862 switch( rxsock->m_rx_wnc_state ) { 00863 case READ_START: //need to start a read sequence of events 00864 rxsock->m_rx_wnc_state= READ_INIT; 00865 rxsock->m_rx_dptr = (uint8_t*)data; 00866 rxsock->m_rx_req_size = (uint32_t)size; 00867 rxsock->m_rx_total_cnt= 0; 00868 rxsock->m_rx_timer = 0; 00869 rxsock->m_rx_return_cnt=0; 00870 00871 if( rxsock->m_rx_req_size > WNC_BUFF_SIZE) 00872 rxsock->m_rx_req_size= WNC_BUFF_SIZE; 00873 00874 rxsock->m_rx_callback = wnc->_callback; 00875 rxsock->m_rx_cb_data = wnc->_cb_data; 00876 00877 if( !rx_event(rxsock) ){ 00878 rxsock->m_rx_wnc_state = READ_ACTIVE; 00879 wnc_queue.call_in(EQ_FREQ,mbed::Callback<void()>((WNC14A2AInterface*)this,&WNC14A2AInterface::wnc_eq_event)); 00880 return NSAPI_ERROR_WOULD_BLOCK; 00881 } 00882 // fall through 00883 00884 case DATA_AVAILABLE: 00885 debugOutput("EXIT socket_recv(),socket %d, return %d bytes",wnc->socket, rxsock->m_rx_return_cnt); 00886 debugDump_arry((const uint8_t*)data,rxsock->m_rx_return_cnt); 00887 rxsock->m_rx_wnc_state = READ_START; 00888 return rxsock->m_rx_return_cnt; 00889 00890 case READ_ACTIVE: 00891 case READ_INIT: 00892 rxsock->m_rx_timer = 0; //reset the time-out timer 00893 return NSAPI_ERROR_WOULD_BLOCK; 00894 00895 default: 00896 debugOutput("EXIT socket_recv(), NSAPI_ERROR_DEVICE_ERROR"); 00897 return (m_errors = NSAPI_ERROR_DEVICE_ERROR); 00898 } 00899 } 00900 00901 00902 int WNC14A2AInterface::rx_event(RXEVENT *ptr) 00903 { 00904 debugOutput("ENTER rx_event() for socket %d", ptr->m_rx_socket); 00905 _pwnc_mutex.lock(); 00906 int cnt = m_pwnc->read(ptr->m_rx_socket, ptr->m_rx_dptr, ptr->m_rx_req_size); 00907 _pwnc_mutex.unlock(); 00908 00909 if( cnt ) { //got data, return it to the caller 00910 debugOutput("data received on socket %d, cnt=%d", ptr->m_rx_socket,cnt); 00911 ptr->m_rx_wnc_state = DATA_AVAILABLE; 00912 ptr->m_rx_return_cnt = cnt; 00913 if( ptr->m_rx_callback != NULL ) 00914 ptr->m_rx_callback( ptr->m_rx_cb_data ); 00915 ptr->m_rx_cb_data = NULL; 00916 ptr->m_rx_callback = NULL; 00917 return 1; 00918 } 00919 if( ++ptr->m_rx_timer > (WNC14A2A_READ_TIMEOUTMS/EQ_FREQ) && !ptr->m_rx_disTO ) { //timed out waiting, return 0 to caller 00920 debugOutput("EXIT rx_event(), rx data TIME-OUT!"); 00921 ptr->m_rx_wnc_state = DATA_AVAILABLE; 00922 ptr->m_rx_return_cnt = 0; 00923 if( ptr->m_rx_callback != NULL ) 00924 ptr->m_rx_callback( ptr->m_rx_cb_data ); 00925 ptr->m_rx_cb_data = NULL; 00926 ptr->m_rx_callback = NULL; 00927 return 1; 00928 } 00929 00930 debugOutput("EXIT rx_event(), socket %d, sechedule for more data.",ptr->m_rx_socket); 00931 return 0; 00932 } 00933 00934 void WNC14A2AInterface::wnc_eq_event() 00935 { 00936 int done = 1; 00937 bool goSlow = true; 00938 00939 for( unsigned int i=0; i<WNC14A2A_SOCKET_COUNT; i++ ) { 00940 if( _socRxS[i].m_rx_wnc_state == READ_ACTIVE || _socRxS[i].m_rx_disTO) { 00941 done &= rx_event(&_socRxS[i]); 00942 goSlow &= ( _socRxS[i].m_rx_timer > ((WNC14A2A_READ_TIMEOUTMS/EQ_FREQ)*(EQ_FREQ_SLOW/EQ_FREQ)) ); 00943 00944 if( goSlow ) 00945 _socRxS[i].m_rx_timer = (WNC14A2A_READ_TIMEOUTMS/EQ_FREQ)*(EQ_FREQ_SLOW/EQ_FREQ); 00946 } 00947 00948 if( _socTxS[i].m_tx_wnc_state == TX_ACTIVE ) { 00949 goSlow = false; 00950 debugOutput("CALL TX_event() for socket %d", i); 00951 done &= tx_event(&_socTxS[i]); 00952 } 00953 } 00954 00955 if( !done ) 00956 wnc_queue.call_in((goSlow?EQ_FREQ_SLOW:EQ_FREQ),mbed::Callback<void()>((WNC14A2AInterface*)this,&WNC14A2AInterface::wnc_eq_event)); 00957 }
Generated on Tue Jul 12 2022 16:22:13 by 1.7.2