takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers QUECTEL_BC95_CellularStack.cpp Source File

QUECTEL_BC95_CellularStack.cpp

00001 /*
00002  * Copyright (c) 2017, Arm Limited and affiliates.
00003  * SPDX-License-Identifier: Apache-2.0
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 "QUECTEL_BC95_CellularStack.h"
00019 #include "CellularUtil.h"
00020 #include "CellularLog.h"
00021 
00022 using namespace mbed;
00023 using namespace mbed_cellular_util;
00024 
00025 QUECTEL_BC95_CellularStack::QUECTEL_BC95_CellularStack(ATHandler &atHandler, int cid, nsapi_ip_stack_t stack_type) : AT_CellularStack(atHandler, cid, stack_type)
00026 {
00027     _at.set_urc_handler("+NSONMI:", mbed::Callback<void()>(this, &QUECTEL_BC95_CellularStack::urc_nsonmi));
00028 }
00029 
00030 QUECTEL_BC95_CellularStack::~QUECTEL_BC95_CellularStack()
00031 {
00032 }
00033 
00034 nsapi_error_t QUECTEL_BC95_CellularStack::socket_listen(nsapi_socket_t handle, int backlog)
00035 {
00036     return NSAPI_ERROR_UNSUPPORTED ;
00037 }
00038 
00039 nsapi_error_t QUECTEL_BC95_CellularStack::socket_accept(void *server, void **socket, SocketAddress *addr)
00040 {
00041     return NSAPI_ERROR_UNSUPPORTED ;
00042 }
00043 
00044 void QUECTEL_BC95_CellularStack::urc_nsonmi()
00045 {
00046     int sock_id = _at.read_int();
00047 
00048     for (int i = 0; i < get_max_socket_count(); i++) {
00049         CellularSocket *sock = _socket[i];
00050         if (sock && sock->id == sock_id) {
00051             if (sock->_cb) {
00052                 sock->_cb(sock->_data);
00053             }
00054             break;
00055         }
00056     }
00057 }
00058 
00059 int QUECTEL_BC95_CellularStack::get_max_socket_count()
00060 {
00061     return BC95_SOCKET_MAX;
00062 }
00063 
00064 bool QUECTEL_BC95_CellularStack::is_protocol_supported(nsapi_protocol_t protocol)
00065 {
00066     return (protocol == NSAPI_UDP );
00067 }
00068 
00069 nsapi_error_t QUECTEL_BC95_CellularStack::socket_close_impl(int sock_id)
00070 {
00071     _at.cmd_start("AT+NSOCL=");
00072     _at.write_int(sock_id);
00073     _at.cmd_stop();
00074     _at.resp_start();
00075     _at.resp_stop();
00076 
00077     tr_info("Close socket: %d error: %d", sock_id, _at.get_last_error());
00078 
00079     return _at.get_last_error();
00080 }
00081 
00082 nsapi_error_t QUECTEL_BC95_CellularStack::create_socket_impl(CellularSocket *socket)
00083 {
00084     int sock_id = -1;
00085     bool socketOpenWorking = false;
00086 
00087     if (socket->proto == NSAPI_UDP ) {
00088 
00089         _at.cmd_start("AT+NSOCR=DGRAM,17,");
00090         _at.write_int(socket->localAddress.get_port());
00091         _at.write_int(1);
00092         _at.cmd_stop();
00093         _at.resp_start();
00094         sock_id = _at.read_int();
00095         _at.resp_stop();
00096 
00097         socketOpenWorking = (_at.get_last_error() == NSAPI_ERROR_OK );
00098 
00099         if (!socketOpenWorking) {
00100             _at.cmd_start("AT+NSOCL=0");
00101             _at.cmd_stop();
00102             _at.resp_start();
00103             _at.resp_stop();
00104 
00105             _at.cmd_start("AT+NSOCR=DGRAM,17,");
00106             _at.write_int(socket->localAddress.get_port());
00107             _at.write_int(1);
00108             _at.cmd_stop();
00109             _at.resp_start();
00110             sock_id = _at.read_int();
00111             _at.resp_stop();
00112 
00113             socketOpenWorking = (_at.get_last_error() == NSAPI_ERROR_OK );
00114         }
00115     }
00116 
00117     if (!socketOpenWorking || (sock_id == -1)) {
00118         tr_error("Socket create failed!");
00119         return NSAPI_ERROR_NO_SOCKET ;
00120     }
00121 
00122     // Check for duplicate socket id delivered by modem
00123     for (int i = 0; i < BC95_SOCKET_MAX; i++) {
00124         CellularSocket *sock = _socket[i];
00125         if (sock && sock->created && sock->id == sock_id) {
00126             tr_error("Duplicate socket index: %d created:%d, sock_id: %d", i, sock->created, sock_id);
00127             return NSAPI_ERROR_NO_SOCKET ;
00128         }
00129     }
00130 
00131     tr_info("Socket create id: %d", sock_id);
00132 
00133     socket->id = sock_id;
00134     socket->created = true;
00135 
00136     return NSAPI_ERROR_OK ;
00137 }
00138 
00139 nsapi_size_or_error_t QUECTEL_BC95_CellularStack::socket_sendto_impl(CellularSocket *socket, const SocketAddress &address,
00140                                                                      const void *data, nsapi_size_t size)
00141 {
00142     int sent_len = 0;
00143 
00144     char *hexstr = new char[size * 2 + 1];
00145     int hexlen = char_str_to_hex_str((const char *)data, size, hexstr);
00146     // NULL terminated for write_string
00147     hexstr[hexlen] = 0;
00148     _at.cmd_start("AT+NSOST=");
00149     _at.write_int(socket->id);
00150     _at.write_string(address.get_ip_address(), false);
00151     _at.write_int(address.get_port());
00152     _at.write_int(size);
00153     _at.write_string(hexstr, false);
00154     _at.cmd_stop();
00155     _at.resp_start();
00156     // skip socket id
00157     _at.skip_param();
00158     sent_len = _at.read_int();
00159     _at.resp_stop();
00160 
00161     delete hexstr;
00162 
00163     if (_at.get_last_error() == NSAPI_ERROR_OK ) {
00164         return sent_len;
00165     }
00166 
00167     return _at.get_last_error();
00168 }
00169 
00170 nsapi_size_or_error_t QUECTEL_BC95_CellularStack::socket_recvfrom_impl(CellularSocket *socket, SocketAddress *address,
00171                                                                        void *buffer, nsapi_size_t size)
00172 {
00173     nsapi_size_or_error_t recv_len = 0;
00174     int port;
00175     char ip_address[NSAPI_IP_SIZE];
00176 
00177     _at.cmd_start("AT+NSORF=");
00178     _at.write_int(socket->id);
00179     _at.write_int(size);
00180     _at.cmd_stop();
00181     _at.resp_start();
00182     // receiving socket id
00183     _at.skip_param();
00184     _at.read_string(ip_address, sizeof(ip_address));
00185     port = _at.read_int();
00186     recv_len = _at.read_int();
00187     int hexlen = _at.read_hex_string((char *)buffer, size);
00188     // remaining length
00189     _at.skip_param();
00190     _at.resp_stop();
00191 
00192     if (!recv_len || (recv_len == -1) || (_at.get_last_error() != NSAPI_ERROR_OK )) {
00193         return NSAPI_ERROR_WOULD_BLOCK ;
00194     }
00195 
00196     if (address) {
00197         address->set_ip_address(ip_address);
00198         address->set_port(port);
00199     }
00200 
00201     if (recv_len != hexlen) {
00202         tr_error("Not received as much data as expected. Should receive: %d bytes, received: %d bytes", recv_len, hexlen);
00203     }
00204     return recv_len;
00205 }