takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers QUECTEL_BG96_CellularStack.cpp Source File

QUECTEL_BG96_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/BG96/QUECTEL_BG96_CellularStack.h"
00019 #include "CellularLog.h"
00020 
00021 using namespace mbed;
00022 
00023 QUECTEL_BG96_CellularStack::QUECTEL_BG96_CellularStack(ATHandler &atHandler, int cid, nsapi_ip_stack_t stack_type) : AT_CellularStack(atHandler, cid, stack_type)
00024 {
00025     _at.set_urc_handler("+QIURC:", mbed::Callback<void()>(this, &QUECTEL_BG96_CellularStack::urc_qiurc));
00026 }
00027 
00028 QUECTEL_BG96_CellularStack::~QUECTEL_BG96_CellularStack()
00029 {
00030 }
00031 
00032 nsapi_error_t QUECTEL_BG96_CellularStack::socket_listen(nsapi_socket_t handle, int backlog)
00033 {
00034     return NSAPI_ERROR_UNSUPPORTED ;
00035 }
00036 
00037 nsapi_error_t QUECTEL_BG96_CellularStack::socket_accept(void *server, void **socket, SocketAddress *addr)
00038 {
00039     return NSAPI_ERROR_UNSUPPORTED ;
00040 }
00041 
00042 void QUECTEL_BG96_CellularStack::urc_qiurc()
00043 {
00044     int sock_id = 0;
00045 
00046     _at.lock();
00047     (void) _at.skip_param();
00048     sock_id = _at.read_int();
00049     _at.unlock();
00050 
00051     for (int i = 0; i < get_max_socket_count(); i++) {
00052         CellularSocket *sock = _socket[i];
00053         if (sock && sock->id == sock_id) {
00054             if (sock->_cb) {
00055                 sock->_cb(sock->_data);
00056             }
00057             break;
00058         }
00059     }
00060 }
00061 
00062 int QUECTEL_BG96_CellularStack::get_max_socket_count()
00063 {
00064     return BG96_SOCKET_MAX;
00065 }
00066 
00067 bool QUECTEL_BG96_CellularStack::is_protocol_supported(nsapi_protocol_t protocol)
00068 {
00069     return (protocol == NSAPI_UDP );
00070 }
00071 
00072 nsapi_error_t QUECTEL_BG96_CellularStack::socket_close_impl(int sock_id)
00073 {
00074     _at.cmd_start("AT+QICLOSE=");
00075     _at.write_int(sock_id);
00076     _at.cmd_stop();
00077     _at.resp_start();
00078     _at.resp_stop();
00079 
00080     return _at.get_last_error();
00081 }
00082 
00083 void QUECTEL_BG96_CellularStack::handle_open_socket_response(int &modem_connect_id, int &err)
00084 {
00085     // OK
00086     _at.resp_start();
00087     _at.resp_stop();
00088     // QIOPEN -> should be handled as URC?
00089     _at.set_at_timeout(BG96_CREATE_SOCKET_TIMEOUT);
00090     _at.resp_start("+QIOPEN:");
00091     _at.restore_at_timeout();
00092     modem_connect_id = _at.read_int();
00093     err = _at.read_int();
00094 }
00095 nsapi_error_t QUECTEL_BG96_CellularStack::create_socket_impl(CellularSocket *socket)
00096 {
00097     int modem_connect_id = -1;
00098     int request_connect_id = socket->id;
00099     int remote_port = 0;
00100     int err = -1;
00101 
00102     if (socket->proto == NSAPI_UDP  && !socket->connected) {
00103         _at.cmd_start("AT+QIOPEN=");
00104         _at.write_int(_cid);
00105         _at.write_int(request_connect_id);
00106         _at.write_string("UDP SERVICE");
00107         _at.write_string("127.0.0.1");
00108         _at.write_int(remote_port);
00109         _at.write_int(socket->localAddress.get_port());
00110         _at.write_int(0);
00111         _at.cmd_stop();
00112 
00113         handle_open_socket_response(modem_connect_id, err);
00114 
00115         if ((_at.get_last_error() == NSAPI_ERROR_OK ) && err) {
00116             _at.cmd_start("AT+QICLOSE=");
00117             _at.write_int(modem_connect_id);
00118             _at.cmd_stop();
00119             _at.resp_start();
00120             _at.resp_stop();
00121 
00122             _at.cmd_start("AT+QIOPEN=");
00123             _at.write_int(_cid);
00124             _at.write_int(request_connect_id);
00125             _at.write_string("UDP SERVICE");
00126             _at.write_string("127.0.0.1");
00127             _at.write_int(remote_port);
00128             _at.write_int(socket->localAddress.get_port());
00129             _at.write_int(0);
00130             _at.cmd_stop();
00131 
00132             handle_open_socket_response(modem_connect_id, err);
00133         }
00134     } else if (socket->proto == NSAPI_UDP  && socket->connected) {
00135         _at.cmd_start("AT+QIOPEN=");
00136         _at.write_int(_cid);
00137         _at.write_int(request_connect_id);
00138         _at.write_string("UDP");
00139         _at.write_string(socket->remoteAddress.get_ip_address());
00140         _at.write_int(socket->remoteAddress.get_port());
00141         _at.cmd_stop();
00142 
00143         handle_open_socket_response(modem_connect_id, err);
00144 
00145         if ((_at.get_last_error() == NSAPI_ERROR_OK ) && err) {
00146             _at.cmd_start("AT+QICLOSE=");
00147             _at.write_int(modem_connect_id);
00148             _at.cmd_stop();
00149             _at.resp_start();
00150             _at.resp_stop();
00151 
00152             _at.cmd_start("AT+QIOPEN=");
00153             _at.write_int(_cid);
00154             _at.write_int(request_connect_id);
00155             _at.write_string("UDP");
00156             _at.write_string(socket->remoteAddress.get_ip_address());
00157             _at.write_int(socket->remoteAddress.get_port());
00158             _at.cmd_stop();
00159 
00160             handle_open_socket_response(modem_connect_id, err);
00161         }
00162     }
00163 
00164     // If opened successfully BUT not requested one, close it
00165     if (!err && (modem_connect_id != request_connect_id)) {
00166         _at.cmd_start("AT+QICLOSE=");
00167         _at.write_int(modem_connect_id);
00168         _at.cmd_stop();
00169         _at.resp_start();
00170         _at.resp_stop();
00171     }
00172 
00173     nsapi_error_t ret_val = _at.get_last_error();
00174 
00175     socket->created = ((ret_val == NSAPI_ERROR_OK ) && (modem_connect_id == request_connect_id));
00176 
00177     return ret_val;
00178 }
00179 
00180 nsapi_size_or_error_t QUECTEL_BG96_CellularStack::socket_sendto_impl(CellularSocket *socket, const SocketAddress &address,
00181                                                                      const void *data, nsapi_size_t size)
00182 {
00183     int sent_len = 0;
00184     int sent_len_before = 0;
00185     int sent_len_after = 0;
00186 
00187     // Get the sent count before sending
00188     _at.cmd_start("AT+QISEND=");
00189     _at.write_int(socket->id);
00190     _at.write_int(0);
00191     _at.cmd_stop();
00192 
00193     _at.resp_start("+QISEND:");
00194     sent_len_before = _at.read_int();
00195     _at.resp_stop();
00196 
00197     // Send
00198     _at.cmd_start("AT+QISEND=");
00199     _at.write_int(socket->id);
00200     _at.write_int(size);
00201     _at.write_string(address.get_ip_address());
00202     _at.write_int(address.get_port());
00203     _at.cmd_stop();
00204 
00205     _at.resp_start(">");
00206     _at.write_bytes((uint8_t *)data, size);
00207     _at.resp_start();
00208     _at.set_stop_tag("\r\n");
00209     _at.resp_stop();
00210 
00211     // Get the sent count after sending
00212     _at.cmd_start("AT+QISEND=");
00213     _at.write_int(socket->id);
00214     _at.write_int(0);
00215     _at.cmd_stop();
00216 
00217     _at.resp_start("+QISEND:");
00218     sent_len_after = _at.read_int();
00219     _at.resp_stop();
00220 
00221     if (_at.get_last_error() == NSAPI_ERROR_OK ) {
00222         sent_len = sent_len_after - sent_len_before;
00223         return sent_len;
00224     }
00225 
00226     return _at.get_last_error();
00227 }
00228 
00229 nsapi_size_or_error_t QUECTEL_BG96_CellularStack::socket_recvfrom_impl(CellularSocket *socket, SocketAddress *address,
00230                                                                        void *buffer, nsapi_size_t size)
00231 {
00232     nsapi_size_or_error_t recv_len = 0;
00233     int port;
00234     char ip_address[NSAPI_IP_SIZE + 1];
00235 
00236     _at.cmd_start("AT+QIRD=");
00237     _at.write_int(socket->id);
00238     _at.cmd_stop();
00239 
00240     _at.resp_start("+QIRD:");
00241     recv_len = _at.read_int();
00242     _at.read_string(ip_address, sizeof(ip_address));
00243     port = _at.read_int();
00244     if (recv_len > 0) {
00245         _at.read_bytes((uint8_t *)buffer, recv_len);
00246     }
00247     _at.resp_stop();
00248 
00249     if (!recv_len || (_at.get_last_error() != NSAPI_ERROR_OK )) {
00250         return NSAPI_ERROR_WOULD_BLOCK ;
00251     }
00252 
00253     if (address) {
00254         address->set_ip_address(ip_address);
00255         address->set_port(port);
00256     }
00257 
00258     return recv_len;
00259 }