Knight KE / Mbed OS Game_Master
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 int QUECTEL_BC95_CellularStack::get_max_packet_size()
00065 {
00066     return BC95_MAX_PACKET_SIZE;
00067 }
00068 
00069 bool QUECTEL_BC95_CellularStack::is_protocol_supported(nsapi_protocol_t protocol)
00070 {
00071     return (protocol == NSAPI_UDP );
00072 }
00073 
00074 nsapi_error_t QUECTEL_BC95_CellularStack::socket_close_impl(int sock_id)
00075 {
00076     _at.cmd_start("AT+NSOCL=");
00077     _at.write_int(sock_id);
00078     _at.cmd_stop();
00079     _at.resp_start();
00080     _at.resp_stop();
00081 
00082     tr_info("Close socket: %d error: %d", sock_id, _at.get_last_error());
00083 
00084     return _at.get_last_error();
00085 }
00086 
00087 nsapi_error_t QUECTEL_BC95_CellularStack::create_socket_impl(CellularSocket *socket)
00088 {
00089     int sock_id = -1;
00090     bool socketOpenWorking = false;
00091 
00092     if (socket->proto == NSAPI_UDP ) {
00093 
00094         _at.cmd_start("AT+NSOCR=DGRAM,17,");
00095         _at.write_int(socket->localAddress.get_port());
00096         _at.write_int(1);
00097         _at.cmd_stop();
00098         _at.resp_start();
00099         sock_id = _at.read_int();
00100         _at.resp_stop();
00101 
00102         socketOpenWorking = (_at.get_last_error() == NSAPI_ERROR_OK );
00103 
00104         if (!socketOpenWorking) {
00105             _at.cmd_start("AT+NSOCL=0");
00106             _at.cmd_stop();
00107             _at.resp_start();
00108             _at.resp_stop();
00109 
00110             _at.cmd_start("AT+NSOCR=DGRAM,17,");
00111             _at.write_int(socket->localAddress.get_port());
00112             _at.write_int(1);
00113             _at.cmd_stop();
00114             _at.resp_start();
00115             sock_id = _at.read_int();
00116             _at.resp_stop();
00117 
00118             socketOpenWorking = (_at.get_last_error() == NSAPI_ERROR_OK );
00119         }
00120     }
00121 
00122     if (!socketOpenWorking || (sock_id == -1)) {
00123         tr_error("Socket create failed!");
00124         return NSAPI_ERROR_NO_SOCKET ;
00125     }
00126 
00127     // Check for duplicate socket id delivered by modem
00128     for (int i = 0; i < BC95_SOCKET_MAX; i++) {
00129         CellularSocket *sock = _socket[i];
00130         if (sock && sock->created && sock->id == sock_id) {
00131             tr_error("Duplicate socket index: %d created:%d, sock_id: %d", i, sock->created, sock_id);
00132             return NSAPI_ERROR_NO_SOCKET ;
00133         }
00134     }
00135 
00136     tr_info("Socket create id: %d", sock_id);
00137 
00138     socket->id = sock_id;
00139     socket->created = true;
00140 
00141     return NSAPI_ERROR_OK ;
00142 }
00143 
00144 nsapi_size_or_error_t QUECTEL_BC95_CellularStack::socket_sendto_impl(CellularSocket *socket, const SocketAddress &address,
00145         const void *data, nsapi_size_t size)
00146 {
00147     int sent_len = 0;
00148 
00149     char *hexstr = new char[BC95_MAX_PACKET_SIZE*2+1];
00150     int hexlen = char_str_to_hex_str((const char*)data, size, hexstr);
00151     // NULL terminated for write_string
00152     hexstr[hexlen] = 0;
00153     _at.cmd_start("AT+NSOST=");
00154     _at.write_int(socket->id);
00155     _at.write_string(address.get_ip_address(), false);
00156     _at.write_int(address.get_port());
00157     _at.write_int(size <= BC95_MAX_PACKET_SIZE ? size : BC95_MAX_PACKET_SIZE);
00158     _at.write_string(hexstr, false);
00159     _at.cmd_stop();
00160     _at.resp_start();
00161     // skip socket id
00162     _at.skip_param();
00163     sent_len = _at.read_int();
00164     _at.resp_stop();
00165 
00166     delete hexstr;
00167 
00168     if (_at.get_last_error() == NSAPI_ERROR_OK ) {
00169         return sent_len;
00170     }
00171 
00172     return _at.get_last_error();
00173 }
00174 
00175 nsapi_size_or_error_t QUECTEL_BC95_CellularStack::socket_recvfrom_impl(CellularSocket *socket, SocketAddress *address,
00176         void *buffer, nsapi_size_t size)
00177 {
00178     nsapi_size_or_error_t recv_len=0;
00179     int port;
00180     char ip_address[NSAPI_IP_SIZE];
00181 
00182     _at.cmd_start("AT+NSORF=");
00183     _at.write_int(socket->id);
00184     _at.write_int(size <= BC95_MAX_PACKET_SIZE ? size : BC95_MAX_PACKET_SIZE);
00185     _at.cmd_stop();
00186     _at.resp_start();
00187     // receiving socket id
00188     _at.skip_param();
00189     _at.read_string(ip_address, sizeof(ip_address));
00190     port = _at.read_int();
00191     recv_len = _at.read_int();
00192     int hexlen = _at.read_hex_string((char*)buffer, size);
00193     // remaining length
00194     _at.skip_param();
00195     _at.resp_stop();
00196 
00197     if (!recv_len || (recv_len == -1) || (_at.get_last_error() != NSAPI_ERROR_OK )) {
00198         return NSAPI_ERROR_WOULD_BLOCK ;
00199     }
00200 
00201     if (address) {
00202         address->set_ip_address(ip_address);
00203         address->set_port(port);
00204     }
00205 
00206     if (recv_len != hexlen) {
00207         tr_error("Not received as much data as expected. Should receive: %d bytes, received: %d bytes", recv_len, hexlen);
00208     }
00209     return recv_len;
00210 }