Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers CellularNonIPSocket.cpp Source File

CellularNonIPSocket.cpp

00001 /* CellularNonIPSocket
00002 #include <CellularNonIPSocket.h>
00003  * Copyright (c) 2015 ARM Limited
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License");
00006  * you may not use this file except in compliance with the License.
00007  * You may obtain a copy of the License at
00008  *
00009  *     http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 
00018 #include "platform/Callback.h"
00019 #include "CellularNonIPSocket.h"
00020 #include <stdio.h>
00021 
00022 using namespace mbed;
00023 
00024 CellularNonIPSocket::CellularNonIPSocket()
00025     : _timeout(osWaitForever),
00026       _readers(0), _writers(0), _pending(0),
00027       _cp_netif(NULL),
00028       _opened(false)
00029 {}
00030 
00031 nsapi_error_t CellularNonIPSocket::open(CellularContext *cellular_context)
00032 {
00033     if (cellular_context == NULL) {
00034         return NSAPI_ERROR_PARAMETER ;
00035     }
00036 
00037     return open(cellular_context->get_cp_netif());
00038 }
00039 
00040 CellularNonIPSocket::~CellularNonIPSocket()
00041 {
00042     close();
00043 }
00044 
00045 nsapi_error_t CellularNonIPSocket::open(ControlPlane_netif *cp_netif)
00046 {
00047     _lock.lock();
00048 
00049     if (_cp_netif != NULL || cp_netif == NULL) {
00050         _lock.unlock();
00051         return NSAPI_ERROR_PARAMETER ;
00052     }
00053     _cp_netif = cp_netif;
00054 
00055     _event = callback(this, &CellularNonIPSocket::event);
00056     _cp_netif->attach(Callback<void()>::thunk, &_event);
00057     _opened = true;
00058 
00059     _lock.unlock();
00060     return NSAPI_ERROR_OK ;
00061 }
00062 
00063 nsapi_error_t CellularNonIPSocket::close()
00064 {
00065     _lock.lock();
00066 
00067     nsapi_error_t ret = NSAPI_ERROR_OK ;
00068     if (!_opened)  {
00069         return NSAPI_ERROR_NO_SOCKET ;
00070     }
00071 
00072     // Just in case - tell the stack not to callback any more, then remove this socket.
00073     _cp_netif->attach(0, 0);
00074     _opened = false;
00075     _cp_netif = 0; // Invalidate the cp_netif pointer - otherwise open() fails.
00076 
00077     // Wakeup anything in a blocking operation
00078     // on this socket
00079     event();
00080 
00081     // Wait until all readers and writers are gone
00082     while (_readers || _writers) {
00083         _lock.unlock();
00084         _event_flag.wait_any(FINISHED_FLAG, osWaitForever);
00085         _lock.lock();
00086     }
00087 
00088     _lock.unlock();
00089 
00090     return ret;
00091 }
00092 
00093 nsapi_size_or_error_t CellularNonIPSocket::send(const void *data, nsapi_size_t size)
00094 {
00095     _lock.lock();
00096     nsapi_size_or_error_t ret;
00097 
00098     _writers++;
00099 
00100     while (true) {
00101         if (!_opened) {
00102             ret = NSAPI_ERROR_NO_SOCKET ;
00103             break;
00104         }
00105 
00106         _pending = 0;
00107         nsapi_size_or_error_t sent = _cp_netif->send(data, size);
00108         if ((0 == _timeout) || (NSAPI_ERROR_WOULD_BLOCK  != sent)) {
00109             ret = sent;
00110             break;
00111         } else {
00112             uint32_t flag;
00113 
00114             // Release lock before blocking so other threads
00115             // accessing this object aren't blocked
00116             _lock.unlock();
00117             flag = _event_flag.wait_any(WRITE_FLAG, _timeout);
00118             _lock.lock();
00119 
00120             if (flag & osFlagsError) {
00121                 // Timeout break
00122                 ret = NSAPI_ERROR_WOULD_BLOCK ;
00123                 break;
00124             }
00125         }
00126     }
00127 
00128     _writers--;
00129     if (!_opened || !_writers) {
00130         _event_flag.set(FINISHED_FLAG);
00131     }
00132     _lock.unlock();
00133     return ret;
00134 }
00135 
00136 nsapi_size_or_error_t CellularNonIPSocket::recv(void *buffer, nsapi_size_t size)
00137 {
00138     _lock.lock();
00139     nsapi_size_or_error_t ret;
00140 
00141     _readers++;
00142 
00143     while (true) {
00144         if (!_opened) {
00145             ret = NSAPI_ERROR_NO_SOCKET ;
00146             break;
00147         }
00148 
00149         _pending = 0;
00150         nsapi_size_or_error_t recv = _cp_netif->recv(buffer, size);
00151 
00152         // Non-blocking sockets always return. Blocking only returns when success or errors other than WOULD_BLOCK
00153         if ((0 == _timeout) || (NSAPI_ERROR_WOULD_BLOCK  != recv)) {
00154             ret = recv;
00155             break;
00156         } else {
00157             uint32_t flag;
00158 
00159             // Release lock before blocking so other threads
00160             // accessing this object aren't blocked
00161             _lock.unlock();
00162             flag = _event_flag.wait_any(READ_FLAG, _timeout);
00163             _lock.lock();
00164 
00165             if (flag & osFlagsError) {
00166                 // Timeout break
00167                 ret = NSAPI_ERROR_WOULD_BLOCK ;
00168                 break;
00169             }
00170         }
00171     }
00172 
00173     _readers--;
00174     if (!_opened || !_readers) {
00175         _event_flag.set(FINISHED_FLAG);
00176     }
00177 
00178     _lock.unlock();
00179     return ret;
00180 }
00181 
00182 void CellularNonIPSocket::set_blocking (bool blocking)
00183 {
00184     set_timeout (blocking ? -1 : 0);
00185 }
00186 
00187 void CellularNonIPSocket::set_timeout (int timeout)
00188 {
00189     _lock.lock();
00190 
00191     if (timeout >= 0) {
00192         _timeout = (uint32_t)timeout;
00193     } else {
00194         _timeout = osWaitForever;
00195     }
00196 
00197     _lock.unlock();
00198 }
00199 
00200 void CellularNonIPSocket::event()
00201 {
00202     _event_flag.set(READ_FLAG | WRITE_FLAG);
00203 
00204     _pending += 1;
00205     if (_callback && _pending == 1) {
00206         _callback();
00207     }
00208 }
00209 
00210 void CellularNonIPSocket::sigio (Callback<void()> callback)
00211 {
00212     _lock.lock();
00213     _callback = callback;
00214     _lock.unlock();
00215 }
00216 
00217 nsapi_error_t CellularNonIPSocket::connect(const SocketAddress &address)
00218 {
00219     return NSAPI_ERROR_UNSUPPORTED ;
00220 }
00221 
00222 Socket *CellularNonIPSocket::accept(nsapi_error_t *error)
00223 {
00224     if (error) {
00225         *error = NSAPI_ERROR_UNSUPPORTED ;
00226     }
00227     return NULL;
00228 }
00229 
00230 nsapi_error_t CellularNonIPSocket::listen(int backlog)
00231 {
00232     return NSAPI_ERROR_UNSUPPORTED ;
00233 }
00234 
00235 nsapi_size_or_error_t CellularNonIPSocket::sendto(const SocketAddress &address,
00236                                                   const void *data, nsapi_size_t size)
00237 {
00238     return NSAPI_ERROR_UNSUPPORTED ;
00239 }
00240 nsapi_size_or_error_t CellularNonIPSocket::recvfrom(SocketAddress *address,
00241                                                     void *data, nsapi_size_t size)
00242 {
00243     return NSAPI_ERROR_UNSUPPORTED ;
00244 }
00245 
00246 nsapi_error_t CellularNonIPSocket::setsockopt(int level, int optname, const void *optval, unsigned optlen)
00247 {
00248     return NSAPI_ERROR_UNSUPPORTED ;
00249 }
00250 
00251 nsapi_error_t CellularNonIPSocket::getsockopt(int level, int optname, void *optval, unsigned *optlen)
00252 {
00253     return NSAPI_ERROR_UNSUPPORTED ;
00254 }
00255 
00256 nsapi_error_t  CellularNonIPSocket::getpeername(SocketAddress *address)
00257 {
00258     return NSAPI_ERROR_UNSUPPORTED ;
00259 }
00260 
00261 nsapi_error_t CellularNonIPSocket::bind(const SocketAddress &address)
00262 {
00263     return NSAPI_ERROR_UNSUPPORTED ;
00264 }