Steve Sims / X_NUCLEO_IDW01M1_AP

Dependents:   X_NUCLEO_IDW01M1_AP_Test

Fork of X_NUCLEO_IDW01M1 by ST

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SPWFInterface.cpp Source File

SPWFInterface.cpp

00001 /* mbed Microcontroller Library
00002 * Copyright (c) 20015 ARM Limited
00003 *
00004 * Licensed under the Apache License, Version 2.0 (the "License");
00005 * you may not use this file except in compliance with the License.
00006 * You may obtain a copy of the License at
00007 *
00008 *     http://www.apache.org/licenses/LICENSE-2.0
00009 *
00010 * Unless required by applicable law or agreed to in writing, software
00011 * distributed under the License is distributed on an "AS IS" BASIS,
00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013 * See the License for the specific language governing permissions and
00014 * limitations under the License.
00015 */
00016 
00017 /**
00018   ******************************************************************************
00019   * @file    SpwfInterface.cpp 
00020   * @author  STMicroelectronics
00021   * @brief   Implementation of the NetworkStack for the SPWF Device
00022   ******************************************************************************
00023   * @copy
00024   *
00025   * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
00026   * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
00027   * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
00028   * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
00029   * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
00030   * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
00031   *
00032   * <h2><center>&copy; COPYRIGHT 2016 STMicroelectronics</center></h2>
00033   ******************************************************************************
00034   */
00035   
00036 #include "SPWFInterface.h"
00037  
00038 // Various timeouts for different SPWF operations
00039 #define SPWF_CONNECT_TIMEOUT 20000
00040 #define SPWF_SEND_TIMEOUT    500
00041 #define SPWF_RECV_TIMEOUT    1000
00042 #define SPWF_MISC_TIMEOUT    15000
00043 
00044 /** spwf_socket class
00045  *  Implementation of SPWF socket structure
00046  */
00047 struct spwf_socket {
00048     int id;
00049     int server_port;
00050     nsapi_protocol_t proto;
00051     bool connected;
00052 };
00053 
00054 
00055 /**
00056 * @brief  SpwfSAInterface constructor         
00057 * @param  tx: Pin USART TX  
00058 *         rx: Pin USART RX
00059 *         rst: reset pin for Spwf module
00060 *         wkup: reset pin for Spwf module
00061 *         rts: Pin USART RTS
00062 *         debug : not used
00063 * @retval none
00064 */
00065 SpwfSAInterface::SpwfSAInterface(PinName tx, PinName rx, PinName rst, PinName wkup, PinName rts, bool debug)
00066     : _spwf(tx, rx, rst, wkup, rts)
00067 {
00068     memset(_ids, 0, sizeof(_ids));
00069     isInitialized = false;
00070     isListening = false;
00071 }
00072 
00073 /**
00074 * @brief  SpwfSAInterface destructor         
00075 * @param  none
00076 * @retval none
00077 */
00078 SpwfSAInterface::~SpwfSAInterface()
00079 {
00080 }
00081 
00082 /**
00083 * @brief  init function
00084           initializes SPWF FW and module         
00085 * @param  none
00086 * @retval error value
00087 */
00088 int SpwfSAInterface::init(void) 
00089 {
00090     _spwf.setTimeout(SPWF_MISC_TIMEOUT);
00091     int result = _spwf.init();
00092     return result;
00093 }
00094 
00095 /** 
00096 * @brief Setup as an access point
00097 * @param ap:  SSID to set the access point up with (1-32 characters)
00098 * @param pass_phrase:  Password/key of the access point to set up (currently only Open AP is supported, this param is ignored)
00099 * @param security: type of NSAPI security supported (currently only Open AP is supported)
00100 * @param channelNum: Channel for the AP to operate on 1-14 (depending on region)
00101 * @retval NSAPI Error Type
00102 */
00103 int SpwfSAInterface::start_access_point(
00104                             const char *ap,
00105                             const char *pass_phrase,
00106                             nsapi_security_t security,
00107                             int channel_num,
00108                             unsigned int data_rates)
00109 {
00110     WiFi_Priv_Mode mode = convert_security(security);
00111 
00112     // Check for valid channel_num
00113     if (channel_num < 1 || channel_num > 14) 
00114     {
00115         #if DEBUG_PRINT
00116         printf("channel_num must be between 1 and 14\n");
00117         #endif
00118         return NSAPI_ERROR_PARAMETER;
00119     }
00120     
00121     // Verify that the access point is between 1-32
00122     if ((NULL == ap && mode != None) || strlen(ap) < 1 || strlen(ap) > 32)
00123     {
00124         #if DEBUG_PRINT
00125         printf("ap length must be between 1 and 32\n");
00126         #endif
00127         return NSAPI_ERROR_PARAMETER;
00128     }
00129     
00130     //initialize the device before starting the AP
00131     if(!isInitialized)
00132     {
00133         if(init()==0)
00134             isInitialized=true;
00135         else return NSAPI_ERROR_DEVICE_ERROR;
00136     }
00137     
00138     _spwf.setTimeout(SPWF_CONNECT_TIMEOUT);   
00139 
00140     switch (mode)
00141     {
00142 //        case WEP:
00143 //        {
00144 //            break;
00145 //        }
00146 //        case WPA_Personal:
00147 //        {
00148 //            break;
00149 //        }
00150         default:
00151         {
00152             #if DEBUG_PRINT
00153             printf("Assuming open wifi access point\n");
00154             #endif
00155             mode = None;
00156             pass_phrase = NULL;
00157         }
00158     }
00159     return (_spwf.start_access_point((char*)ap, (char*)pass_phrase, mode, channel_num, data_rates));
00160 }
00161 
00162 WiFi_Priv_Mode SpwfSAInterface::convert_security(int security)
00163 {
00164     switch(security)
00165     {
00166         case NSAPI_SECURITY_NONE:
00167             return (WiFi_Priv_Mode) None;
00168         case NSAPI_SECURITY_WEP:
00169             return (WiFi_Priv_Mode) WEP;
00170         case NSAPI_SECURITY_WPA:
00171         case NSAPI_SECURITY_WPA2:
00172             return (WiFi_Priv_Mode) WPA_Personal;
00173         default:
00174             return (WiFi_Priv_Mode) WPA_Personal;
00175     }
00176 }
00177 
00178 /**
00179 * @brief  network connect
00180           connects to Access Point
00181 * @param  ap: Access Point (AP) Name String  
00182 *         pass_phrase: Password String for AP
00183 *         security: type of NSAPI security supported
00184 * @retval NSAPI Error Type
00185 */
00186 int SpwfSAInterface::connect(
00187     const char *ap, 
00188     const char *pass_phrase, 
00189     nsapi_security_t security)
00190 {
00191     WiFi_Priv_Mode mode;
00192     
00193     //initialize the device before connecting
00194     if(!isInitialized)
00195     {
00196         if(init()==0)
00197             isInitialized=true;
00198         else return NSAPI_ERROR_DEVICE_ERROR;
00199     }
00200     
00201     _spwf.setTimeout(SPWF_CONNECT_TIMEOUT);   
00202         
00203     mode = convert_security(security);
00204     if ((WiFi_Priv_Mode) None == mode) 
00205     {
00206         pass_phrase = NULL;
00207     }
00208   
00209     return (_spwf.connect((char*)ap, (char*)pass_phrase, mode));
00210 }
00211 
00212 /**
00213 * @brief  network disconnect
00214           disconnects from Access Point
00215 * @param  none
00216 * @retval NSAPI Error Type
00217 */
00218 int SpwfSAInterface::disconnect()
00219 {    
00220     return (_spwf.disconnect());
00221 }
00222 
00223 /** 
00224 * @brief  Get the local IP address
00225 * @param  none
00226 * @retval Null-terminated representation of the local IP address
00227 *         or null if not yet connected
00228 */
00229 const char *SpwfSAInterface::get_ip_address()
00230 {
00231     return _spwf.getIPAddress();
00232 }
00233 
00234 /** 
00235 * @brief  Get the MAC address
00236 * @param  none
00237 * @retval Null-terminated representation of the MAC address
00238 *         or null if not yet connected
00239 */
00240 const char *SpwfSAInterface::get_mac_address()
00241 {
00242     return _spwf.getMACAddress();
00243 }
00244 
00245 /**
00246 * @brief  open a socket handle
00247 * @param  handle: Pointer to handle
00248 *         proto: TCP/UDP protocol
00249 * @retval NSAPI Error Type
00250 */
00251 int SpwfSAInterface::socket_open(void **handle, nsapi_protocol_t proto)
00252 {
00253     int id = -1;    
00254 
00255     struct spwf_socket *socket = new struct spwf_socket;
00256     if (!socket) {
00257         return NSAPI_ERROR_NO_SOCKET;
00258     }
00259 
00260     socket->id = id;
00261     socket->server_port = id;
00262     socket->proto = proto;
00263     socket->connected = false;
00264     *handle = socket;
00265     return 0;
00266 }
00267 
00268 /**
00269 * @brief  connect to a remote socket
00270 * @param  handle: Pointer to socket handle
00271 *         addr: Address to connect to
00272 * @retval NSAPI Error Type
00273 */
00274 int SpwfSAInterface::socket_connect(void *handle, const SocketAddress &addr)
00275 {
00276     uint8_t sock_id = 99;
00277     struct spwf_socket *socket = (struct spwf_socket *)handle;
00278     
00279     const char *proto = (socket->proto == NSAPI_UDP) ? "u" : "t";//"s" for secure socket?
00280  
00281     _spwf.socket_client_open((uint8_t*)addr.get_ip_address(), (uint32_t)addr.get_port(), (uint8_t *)proto, &sock_id);//sock ID is allocated NOW
00282     
00283     //TODO: Maintain a socket table to map socket ID to host & port
00284     //TODO: lookup on client table to see if already socket is allocated to same host/port
00285     //multimap <char *, vector <uint16_t> > ::iterator i = c_table.find((char*)ip);
00286       
00287     if(sock_id <= SPWFSA_SOCKET_COUNT)
00288     {
00289         socket->id = sock_id;//the socket ID of this Socket instance
00290         _ids[socket->id] = true;
00291         socket->connected = true;
00292     }
00293     else 
00294         return NSAPI_ERROR_NO_SOCKET;
00295     
00296     return 0;
00297 }
00298 
00299 /**
00300 * @brief  bind to a port number and address
00301 * @param  handle: Pointer to socket handle
00302 *         proto: address to bind to
00303 * @retval NSAPI Error Type
00304 */
00305 int SpwfSAInterface::socket_bind(void *handle, const SocketAddress &address)
00306 {
00307     struct spwf_socket *socket = (struct spwf_socket *)handle;    
00308     socket->server_port = address.get_port();
00309     return 0;
00310 }
00311 
00312 /**
00313 * @brief  start listening on a port and address
00314 * @param  handle: Pointer to handle
00315 *         backlog: not used (always value is 1)
00316 * @retval NSAPI Error Type
00317 */
00318 int SpwfSAInterface::socket_listen(void *handle, int backlog)
00319 {
00320     struct spwf_socket *socket = (struct spwf_socket *)handle;
00321     int err;
00322     
00323     if(socket->server_port==-1 || isListening) 
00324         return NSAPI_ERROR_NO_SOCKET; //server socket not bound or already listening
00325     
00326     const char *proto = (socket->proto == NSAPI_UDP) ? "u" : "t";
00327     
00328     err = _spwf.socket_server_open((uint32_t)socket->server_port, (uint8_t *)proto);
00329     if(err==0)
00330     {
00331         socket->id = SERVER_SOCKET_NO;//Special socket ID number for Server Socket
00332         isListening = true;
00333     }
00334     else 
00335         return NSAPI_ERROR_DEVICE_ERROR;
00336         
00337     return err;
00338 }
00339 
00340 /**
00341 * @brief  accept connections from remote sockets
00342 * @param  handle: Pointer to handle of client socket (connecting)
00343 *         proto: handle of server socket which will accept connections
00344 * @retval NSAPI Error Type
00345 */
00346 int SpwfSAInterface::socket_accept(void **handle, void *server)
00347 {
00348     struct spwf_socket *server_socket = (struct spwf_socket *)server;
00349     
00350     if(server_socket->server_port==-1 || !isListening) 
00351         return NSAPI_ERROR_NO_SOCKET; //server socket not bound or not listening
00352     
00353     if(_spwf.get_wait_for_incoming_client())
00354     {
00355         server_socket->connected = true;
00356         struct spwf_socket *socket = new struct spwf_socket;//create new network socket
00357         if (!socket) {
00358             return NSAPI_ERROR_NO_SOCKET;
00359         }
00360         
00361         memset(socket, 0, sizeof (struct spwf_socket));
00362                 
00363         socket->id = server_socket->id;
00364         socket->server_port = server_socket->server_port;
00365         socket->proto = server_socket->proto;
00366         socket->connected = true;
00367         
00368         *handle = socket; 
00369         socket = 0;
00370         _spwf.set_wait_for_incoming_client(false);
00371         wait_ms(50);//CHECK:TODO:Why do we need this?
00372         return 0;
00373     }    
00374     return NSAPI_ERROR_WOULD_BLOCK;
00375 }
00376 
00377 /**
00378 * @brief  close a socket
00379 * @param  handle: Pointer to handle
00380 * @retval NSAPI Error Type
00381 */
00382 int SpwfSAInterface::socket_close(void *handle)
00383 {
00384     struct spwf_socket *socket = (struct spwf_socket *)handle;
00385     int err = 0;
00386     _spwf.setTimeout(SPWF_MISC_TIMEOUT);
00387     
00388     if(socket->id!=-1)
00389     {
00390         if(socket->id==SERVER_SOCKET_NO)
00391         {
00392             if (_spwf.socket_server_close()==-1) {
00393                 err = NSAPI_ERROR_DEVICE_ERROR;
00394             }
00395             isListening = false;
00396         }
00397         else
00398         {
00399             if (_spwf.socket_client_close(socket->id)==-1) {
00400                 err = NSAPI_ERROR_DEVICE_ERROR;
00401             }
00402             _ids[socket->id] = false;
00403         }
00404     }
00405 
00406     delete socket;
00407     return err;
00408 }
00409 
00410 /**
00411 * @brief  write to a socket
00412 * @param  handle: Pointer to handle
00413 *         data: pointer to data
00414 *         size: size of data
00415 * @retval no of bytes sent
00416 */
00417 int SpwfSAInterface::socket_send(void *handle, const void *data, unsigned size)
00418 {    
00419     struct spwf_socket *socket = (struct spwf_socket *)handle;
00420     int err;
00421     
00422     if(socket->id==SERVER_SOCKET_NO)
00423         {
00424             if(socket->server_port==-1 || !isListening) 
00425                 return NSAPI_ERROR_NO_SOCKET; //server socket not bound or not listening        
00426 
00427             err = _spwf.socket_server_write((uint16_t)size, (char*)data);
00428         }
00429     else
00430         {
00431             err = _spwf.socket_client_write((uint8_t)socket->id, (uint16_t)size, (char*)data);
00432         }
00433     
00434     return err;
00435 }
00436 
00437 /**
00438 * @brief  receive data on a socket
00439 * @param  handle: Pointer to handle
00440 *         data: pointer to data
00441 *         size: size of data
00442 * @retval no of bytes read
00443 */
00444 int SpwfSAInterface::socket_recv(void *handle, void *data, unsigned size)
00445 {
00446     struct spwf_socket *socket = (struct spwf_socket *)handle;
00447     int32_t recv;
00448     
00449     _spwf.setTimeout(SPWF_RECV_TIMEOUT);
00450     
00451     //CHECK:Receive for both Client and Server Sockets same?
00452     recv = _spwf.socket_client_recv((uint8_t)socket->id, (uint16_t)size, (char*)data);    
00453     if (recv < 0) {
00454         return NSAPI_ERROR_WOULD_BLOCK;
00455     }
00456     return recv;
00457     
00458 }
00459 
00460 /**
00461 * @brief  send data to a udp socket
00462 * @param  handle: Pointer to handle
00463 *         addr: address of udp socket
00464 *         data: pointer to data
00465 *         size: size of data
00466 * @retval no of bytes sent
00467 */
00468 int SpwfSAInterface::socket_sendto(void *handle, const SocketAddress &addr, const void *data, unsigned size)
00469 {
00470     struct spwf_socket *socket = (struct spwf_socket *)handle;
00471     if (!socket->connected) {
00472         int err = socket_connect(socket, addr);
00473         if (err < 0) {
00474             return err;
00475         }
00476     }
00477     
00478     return socket_send(socket, data, size);
00479 }
00480 
00481 /**
00482 * @brief  receive data on a udp socket
00483 * @param  handle: Pointer to handle
00484 *         addr: address of udp socket
00485 *         data: pointer to data
00486 *         size: size of data
00487 * @retval no of bytes read
00488 */
00489 int SpwfSAInterface::socket_recvfrom(void *handle, SocketAddress *addr, void *data, unsigned size)
00490 {
00491     struct spwf_socket *socket = (struct spwf_socket *)handle;    
00492     return socket_recv(socket, data, size);
00493 }
00494 
00495 /**
00496 * @brief  attach function/callback to the socket
00497 *         Not used
00498 * @param  handle: Pointer to handle
00499 *         callback: callback function pointer
00500 *         data: pointer to data
00501 * @retval none
00502 */
00503 void SpwfSAInterface::socket_attach(void *handle, void (*callback)(void *), void *data)
00504 {
00505     //No implementation yet
00506 }
00507 
00508 /**
00509 * @brief  utility debug function for printing to serial terminal
00510 * @param  string: Pointer to data
00511 * @retval none
00512 */
00513 void SpwfSAInterface::debug(const char * string)
00514 {
00515     _spwf.debug_print(string);
00516 }