mirror of https://github.com/ARMmbed/mbed-os.git
Cellular: Gemalto Cinterion support for ELS61
parent
9e012c3de6
commit
761e01f55c
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright (c) 2018, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "GEMALTO_CINTERION_CellularNetwork.h"
|
||||
#include "GEMALTO_CINTERION_Module.h"
|
||||
#include "AT_CellularInformation.h"
|
||||
#include "GEMALTO_CINTERION.h"
|
||||
#include "CellularLog.h"
|
||||
|
||||
using namespace mbed;
|
||||
using namespace events;
|
||||
|
||||
GEMALTO_CINTERION::GEMALTO_CINTERION(EventQueue &queue) : AT_CellularDevice(queue)
|
||||
{
|
||||
}
|
||||
|
||||
GEMALTO_CINTERION::~GEMALTO_CINTERION()
|
||||
{
|
||||
}
|
||||
|
||||
CellularNetwork *GEMALTO_CINTERION::open_network(FileHandle *fh)
|
||||
{
|
||||
if (!_network) {
|
||||
ATHandler *atHandler = get_at_handler(fh);
|
||||
if (atHandler) {
|
||||
_network = new GEMALTO_CINTERION_CellularNetwork(*get_at_handler(fh));
|
||||
if (!_network) {
|
||||
release_at_handler(atHandler);
|
||||
}
|
||||
}
|
||||
}
|
||||
return _network;
|
||||
}
|
||||
|
||||
nsapi_error_t GEMALTO_CINTERION::init_module(FileHandle *fh)
|
||||
{
|
||||
CellularInformation *information = open_information(fh);
|
||||
if (!information) {
|
||||
return NSAPI_ERROR_NO_MEMORY;
|
||||
}
|
||||
char model[sizeof("ELS61") + 1]; // sizeof need to be long enough to hold just the model text
|
||||
nsapi_error_t ret = information->get_model(model, sizeof(model));
|
||||
close_information();
|
||||
if (ret != NSAPI_ERROR_OK) {
|
||||
tr_error("Cellular model not found!");
|
||||
return NSAPI_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
return GEMALTO_CINTERION_Module::detect_model(model);
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2018, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef GEMALTO_CINTERION_H_
|
||||
#define GEMALTO_CINTERION_H_
|
||||
|
||||
#include "AT_CellularDevice.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
class GEMALTO_CINTERION : public AT_CellularDevice {
|
||||
public:
|
||||
|
||||
GEMALTO_CINTERION(events::EventQueue &queue);
|
||||
virtual ~GEMALTO_CINTERION();
|
||||
|
||||
public: // CellularDevice
|
||||
virtual CellularNetwork *open_network(FileHandle *fh);
|
||||
virtual nsapi_error_t init_module(FileHandle *fh);
|
||||
};
|
||||
|
||||
} // namespace mbed
|
||||
|
||||
#endif // GEMALTO_CINTERION_H_
|
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright (c) 2018, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "GEMALTO_CINTERION_CellularNetwork.h"
|
||||
#include "GEMALTO_CINTERION_CellularStack.h"
|
||||
|
||||
using namespace mbed;
|
||||
|
||||
GEMALTO_CINTERION_CellularNetwork::GEMALTO_CINTERION_CellularNetwork(ATHandler &atHandler) : AT_CellularNetwork(atHandler)
|
||||
{
|
||||
}
|
||||
|
||||
GEMALTO_CINTERION_CellularNetwork::~GEMALTO_CINTERION_CellularNetwork()
|
||||
{
|
||||
}
|
||||
|
||||
NetworkStack *GEMALTO_CINTERION_CellularNetwork::get_stack()
|
||||
{
|
||||
if (!_stack) {
|
||||
_stack = new GEMALTO_CINTERION_CellularStack(_at, _apn, _cid, _ip_stack_type);
|
||||
}
|
||||
return _stack;
|
||||
}
|
||||
|
||||
bool GEMALTO_CINTERION_CellularNetwork::get_modem_stack_type(nsapi_ip_stack_t requested_stack)
|
||||
{
|
||||
return (requested_stack == IPV4_STACK || requested_stack == IPV6_STACK);
|
||||
}
|
||||
|
||||
bool GEMALTO_CINTERION_CellularNetwork::has_registration(RegistrationType reg_type)
|
||||
{
|
||||
return (reg_type == C_REG || reg_type == C_GREG || reg_type == C_EREG);
|
||||
}
|
||||
|
||||
nsapi_error_t GEMALTO_CINTERION_CellularNetwork::set_access_technology_impl(RadioAccessTechnology opsAct)
|
||||
{
|
||||
_op_act = RAT_UNKNOWN;
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright (c) 2018, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef GEMALTO_CINTERION_CELLULAR_NETWORK_H_
|
||||
#define GEMALTO_CINTERION_CELLULAR_NETWORK_H_
|
||||
|
||||
#include "AT_CellularNetwork.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
class GEMALTO_CINTERION_CellularNetwork : public AT_CellularNetwork {
|
||||
public:
|
||||
GEMALTO_CINTERION_CellularNetwork(ATHandler &atHandler);
|
||||
virtual ~GEMALTO_CINTERION_CellularNetwork();
|
||||
|
||||
protected:
|
||||
virtual NetworkStack *get_stack();
|
||||
|
||||
virtual bool has_registration(RegistrationType reg_type);
|
||||
|
||||
virtual bool get_modem_stack_type(nsapi_ip_stack_t requested_stack);
|
||||
|
||||
virtual nsapi_error_t set_access_technology_impl(RadioAccessTechnology opsAct);
|
||||
};
|
||||
|
||||
} // namespace mbed
|
||||
|
||||
#endif // GEMALTO_CINTERION_CELLULAR_NETWORK_H_
|
|
@ -0,0 +1,491 @@
|
|||
/*
|
||||
* Copyright (c) 2018, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "GEMALTO_CINTERION_CellularStack.h"
|
||||
#include "CellularLog.h"
|
||||
|
||||
// defines as per ELS61-E2_ATC_V01.000
|
||||
#define SOCKET_MAX 10
|
||||
#define UDP_PACKET_SIZE 1460
|
||||
#define FAILURE_TIMEOUT (30*1000) // failure timeout in milliseconds on modem side
|
||||
|
||||
/*
|
||||
* Use connection profile 0 and Internet service profiles starting from 0 for sockets.
|
||||
*/
|
||||
#define CONNECTION_PROFILE_ID 0
|
||||
|
||||
using namespace mbed;
|
||||
|
||||
GEMALTO_CINTERION_CellularStack::GEMALTO_CINTERION_CellularStack(ATHandler &atHandler, const char *apn,
|
||||
int cid, nsapi_ip_stack_t stack_type) : AT_CellularStack(atHandler, cid, stack_type), _apn(apn)
|
||||
{
|
||||
}
|
||||
|
||||
GEMALTO_CINTERION_CellularStack::~GEMALTO_CINTERION_CellularStack()
|
||||
{
|
||||
}
|
||||
|
||||
GEMALTO_CINTERION_CellularStack::CellularSocket *GEMALTO_CINTERION_CellularStack::find_socket(int sock_id)
|
||||
{
|
||||
CellularSocket *sock = NULL;
|
||||
for (int i = 0; i < SOCKET_MAX; i++) {
|
||||
if (_socket[i] && _socket[i]->id == sock_id) {
|
||||
sock = _socket[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!sock) {
|
||||
tr_error("Socket not found %d", sock_id);
|
||||
}
|
||||
return sock;
|
||||
}
|
||||
|
||||
void GEMALTO_CINTERION_CellularStack::urc_sis()
|
||||
{
|
||||
int sock_id = _at.read_int();
|
||||
int urc_code = _at.read_int();
|
||||
//tr_debug("Socket ready: id=%d, urc=%d", sock_id, urc_code);
|
||||
CellularSocket *sock = find_socket(sock_id);
|
||||
if (sock) {
|
||||
if (urc_code == 5) { // data available
|
||||
if (sock->_cb) {
|
||||
sock->started = true;
|
||||
sock->tx_ready = true;
|
||||
sock->_cb(sock->_data);
|
||||
}
|
||||
} else if (urc_code == 2) { // socket closed
|
||||
sock->created = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GEMALTO_CINTERION_CellularStack::urc_sisw()
|
||||
{
|
||||
int sock_id = _at.read_int();
|
||||
int urc_code = _at.read_int();
|
||||
//tr_debug("TX event: socket=%d, urc=%d", sock_id, urc_code);
|
||||
CellularSocket *sock = find_socket(sock_id);
|
||||
if (sock) {
|
||||
if (urc_code == 1) { // ready
|
||||
if (sock->_cb) {
|
||||
sock->tx_ready = true;
|
||||
sock->_cb(sock->_data);
|
||||
}
|
||||
} else if (urc_code == 2) { // socket closed
|
||||
sock->created = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GEMALTO_CINTERION_CellularStack::urc_sisr()
|
||||
{
|
||||
int sock_id = _at.read_int();
|
||||
int urc_code = _at.read_int();
|
||||
//tr_debug("RX event: socket=%d, urc=%d", sock_id, urc_code);
|
||||
CellularSocket *sock = find_socket(sock_id);
|
||||
if (sock) {
|
||||
if (urc_code == 1) { // data available
|
||||
if (sock->_cb) {
|
||||
sock->rx_avail = true;
|
||||
sock->_cb(sock->_data);
|
||||
}
|
||||
} else if (urc_code == 2) { // socket closed
|
||||
sock->created = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsapi_error_t GEMALTO_CINTERION_CellularStack::socket_stack_init()
|
||||
{
|
||||
_at.lock();
|
||||
if (create_connection_profile()) {
|
||||
_at.set_urc_handler("^SIS:", mbed::Callback<void()>(this, &GEMALTO_CINTERION_CellularStack::urc_sis));
|
||||
_at.set_urc_handler("^SISW:", mbed::Callback<void()>(this, &GEMALTO_CINTERION_CellularStack::urc_sisw));
|
||||
_at.set_urc_handler("^SISR:", mbed::Callback<void()>(this, &GEMALTO_CINTERION_CellularStack::urc_sisr));
|
||||
}
|
||||
return _at.unlock_return_error();
|
||||
}
|
||||
|
||||
int GEMALTO_CINTERION_CellularStack::get_max_socket_count()
|
||||
{
|
||||
return SOCKET_MAX;
|
||||
}
|
||||
|
||||
bool GEMALTO_CINTERION_CellularStack::is_protocol_supported(nsapi_protocol_t protocol)
|
||||
{
|
||||
return (protocol == NSAPI_UDP);
|
||||
}
|
||||
|
||||
nsapi_error_t GEMALTO_CINTERION_CellularStack::socket_close_impl(int sock_id)
|
||||
{
|
||||
_at.set_at_timeout(FAILURE_TIMEOUT);
|
||||
_at.cmd_start("AT^SISC=");
|
||||
_at.write_int(sock_id);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
_at.restore_at_timeout();
|
||||
tr_debug("Closed socket %d (err %d)", sock_id, _at.get_last_error());
|
||||
return _at.get_last_error();
|
||||
}
|
||||
|
||||
// To open socket:
|
||||
// 1. Select URC mode or polling mode with AT^SCFG
|
||||
// 2. create a GPRS connection profile with AT^SICS (must have PDP)
|
||||
// 3. create service profile with AT^SISS and map connectionID to serviceID
|
||||
// 4. open internet session with AT^SISO (ELS61 tries to attach to a packet domain)
|
||||
nsapi_error_t GEMALTO_CINTERION_CellularStack::create_socket_impl(CellularSocket *socket)
|
||||
{
|
||||
int connection_profile_id = CONNECTION_PROFILE_ID;
|
||||
|
||||
// setup internet session profile
|
||||
int internet_service_id = socket->id;
|
||||
bool foundSrvType = false;
|
||||
bool foundConIdType = false;
|
||||
_at.cmd_start("AT^SISS?");
|
||||
_at.cmd_stop();
|
||||
_at.resp_start("^SISS:");
|
||||
/*
|
||||
* Profile is a list of tag-value map:
|
||||
* ^SISS: <srvProfileId>, <srvParmTag>, <srvParmValue>
|
||||
* [^SISS: ...]
|
||||
*/
|
||||
while (_at.info_resp()) {
|
||||
int id = _at.read_int();
|
||||
if (id == internet_service_id) {
|
||||
char paramTag[16];
|
||||
int paramTagLen = _at.read_string(paramTag, sizeof(paramTag));
|
||||
if (paramTagLen > 0) {
|
||||
//tr_debug("paramTag %s", paramTag);
|
||||
char paramValue[100 + 1]; // APN may be up to 100 chars
|
||||
int paramValueLen = _at.read_string(paramValue, sizeof(paramValue));
|
||||
if (paramValueLen >= 0) {
|
||||
//tr_debug("paramValue %s", paramValue);
|
||||
if (strcmp(paramTag, "srvType") == 0) {
|
||||
if (strcmp(paramValue, "Socket") == 0) {
|
||||
tr_debug("srvType %s", paramValue);
|
||||
foundSrvType = true;
|
||||
}
|
||||
}
|
||||
if (strcmp(paramTag, "address") == 0) {
|
||||
if (strncmp(paramValue, "sock", sizeof("sock")) == 0) {
|
||||
tr_debug("address %s", paramValue);
|
||||
foundSrvType = true;
|
||||
}
|
||||
}
|
||||
if (strcmp(paramTag, "conId") == 0) {
|
||||
char buf[10];
|
||||
std::sprintf(buf, "%d", connection_profile_id);
|
||||
tr_debug("conId %s", paramValue);
|
||||
if (strcmp(paramValue, buf) == 0) {
|
||||
foundConIdType = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_at.resp_stop();
|
||||
|
||||
if (!foundSrvType) {
|
||||
_at.cmd_start("AT^SISS=");
|
||||
_at.write_int(internet_service_id);
|
||||
_at.write_string("srvType");
|
||||
_at.write_string("Socket");
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
}
|
||||
|
||||
if (!foundConIdType) {
|
||||
_at.cmd_start("AT^SISS=");
|
||||
_at.write_int(internet_service_id);
|
||||
_at.write_string("conId");
|
||||
_at.write_int(connection_profile_id);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
}
|
||||
|
||||
tr_debug("Internet service %d created (err %d)", internet_service_id, _at.get_last_error());
|
||||
|
||||
char sock_addr[sizeof("sockudp://") + sizeof(":") + sizeof("65535") + 1];
|
||||
std::sprintf(sock_addr, "sockudp://:%u", socket->localAddress.get_port());
|
||||
_at.cmd_start("AT^SISS=");
|
||||
_at.write_int(socket->id);
|
||||
_at.write_string("address", false);
|
||||
_at.write_string(sock_addr);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
|
||||
|
||||
_at.cmd_start("AT^SISO=");
|
||||
_at.write_int(socket->id);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
if (_at.get_last_error()) {
|
||||
tr_error("Socket %d open failed!", socket->id);
|
||||
_at.clear_error();
|
||||
socket_close_impl(socket->id);
|
||||
return NSAPI_ERROR_NO_SOCKET;
|
||||
}
|
||||
|
||||
socket->created = true;
|
||||
tr_debug("Socket %d created (err %d)", socket->id, _at.get_last_error());
|
||||
|
||||
return _at.get_last_error();
|
||||
}
|
||||
|
||||
nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_sendto_impl(CellularSocket *socket,
|
||||
const SocketAddress &address, const void *data, nsapi_size_t size)
|
||||
{
|
||||
tr_debug("Socket %d, sendto %s, len %d", socket->id, address.get_ip_address(), size);
|
||||
|
||||
int ip_version = address.get_ip_version();
|
||||
if ((ip_version == NSAPI_IPv4 && _stack_type != IPV4_STACK) ||
|
||||
(ip_version == NSAPI_IPv6 && _stack_type != IPV6_STACK)) {
|
||||
tr_warn("No IP route for %s", address.get_ip_address());
|
||||
return NSAPI_ERROR_NO_SOCKET;
|
||||
}
|
||||
|
||||
if (!socket->started || !socket->tx_ready) {
|
||||
tr_debug("Socket %d would block", socket->id);
|
||||
return NSAPI_ERROR_WOULD_BLOCK;
|
||||
}
|
||||
|
||||
if (size > UDP_PACKET_SIZE) {
|
||||
tr_warn("Sending UDP packet size %d (max %d)", size, UDP_PACKET_SIZE);
|
||||
size = UDP_PACKET_SIZE;
|
||||
}
|
||||
|
||||
_at.set_at_timeout(FAILURE_TIMEOUT);
|
||||
_at.cmd_start("AT^SISW=");
|
||||
_at.write_int(socket->id);
|
||||
_at.write_int(size);
|
||||
_at.write_int(0);
|
||||
char ip_address[sizeof("[1111:2222:3333:4444:5555:6666:7777:8888]:12345") + 1];
|
||||
if (address.get_ip_version() == NSAPI_IPv4) {
|
||||
std::sprintf(ip_address, "%s", address.get_ip_address());
|
||||
} else {
|
||||
std::sprintf(ip_address, "[%s]", address.get_ip_address());
|
||||
}
|
||||
char socket_address[sizeof(ip_address) + sizeof(":") + sizeof("65535") + 1];
|
||||
std::sprintf(socket_address, "%s:%u", ip_address, address.get_port());
|
||||
_at.write_string(socket_address);
|
||||
_at.cmd_stop();
|
||||
|
||||
_at.resp_start("^SISW:");
|
||||
if (!_at.info_resp()) {
|
||||
tr_error("Socket %d send failure", socket->id);
|
||||
_at.restore_at_timeout();
|
||||
return NSAPI_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
_at.restore_at_timeout();
|
||||
int socket_id = _at.read_int();
|
||||
if (socket_id != socket->id) {
|
||||
tr_error("Socket id %d != %d", socket_id, socket->id);
|
||||
return NSAPI_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
int accept_len = _at.read_int();
|
||||
if (accept_len == -1) {
|
||||
tr_error("Socket %d send failed", socket->id);
|
||||
return NSAPI_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
int unack_len = _at.read_int();
|
||||
if (unack_len != 0) {
|
||||
tr_warn("Socket %d unack_len %d", socket->id, unack_len);
|
||||
}
|
||||
|
||||
_at.write_bytes((uint8_t *)data, accept_len);
|
||||
_at.resp_stop();
|
||||
|
||||
tr_debug("Socket %d sendto %s, %d bytes (err %d)", socket->id, address.get_ip_address(), accept_len, _at.get_last_error());
|
||||
|
||||
if (_at.get_last_error() == NSAPI_ERROR_OK) {
|
||||
socket->tx_ready = false;
|
||||
}
|
||||
|
||||
return (_at.get_last_error() == NSAPI_ERROR_OK) ? accept_len : NSAPI_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
nsapi_size_or_error_t GEMALTO_CINTERION_CellularStack::socket_recvfrom_impl(CellularSocket *socket, SocketAddress *address,
|
||||
void *buffer, nsapi_size_t size)
|
||||
{
|
||||
tr_debug("Socket %d recvfrom %d bytes", socket->id, size);
|
||||
|
||||
if (size > UDP_PACKET_SIZE) {
|
||||
tr_debug("Socket recvfrom size %d > %d", size, UDP_PACKET_SIZE);
|
||||
size = UDP_PACKET_SIZE;
|
||||
}
|
||||
|
||||
if (!socket->rx_avail) {
|
||||
_at.process_oob(); // check for ^SISR URC
|
||||
if (!socket->rx_avail) {
|
||||
tr_debug("Socket %d would block", socket->id);
|
||||
return NSAPI_ERROR_WOULD_BLOCK;
|
||||
}
|
||||
}
|
||||
|
||||
_at.cmd_start("AT^SISR=");
|
||||
_at.write_int(socket->id);
|
||||
_at.write_int(size);
|
||||
_at.cmd_stop();
|
||||
|
||||
_at.resp_start("^SISR:");
|
||||
if (!_at.info_resp()) {
|
||||
tr_error("Socket %d not responding", socket->id);
|
||||
return NSAPI_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
int socket_id = _at.read_int();
|
||||
if (socket_id != socket->id) {
|
||||
tr_error("Socket recvfrom id %d != %d", socket_id, socket->id);
|
||||
return NSAPI_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
nsapi_size_or_error_t len = _at.read_int();
|
||||
if (len == 0) {
|
||||
tr_warn("Socket %d no data", socket->id);
|
||||
_at.resp_stop();
|
||||
return NSAPI_ERROR_WOULD_BLOCK;
|
||||
}
|
||||
if (len == -1) {
|
||||
tr_error("Socket %d recvfrom failed!", socket->id);
|
||||
return NSAPI_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
socket->rx_avail = false;
|
||||
if (len >= (nsapi_size_or_error_t)size) {
|
||||
int remain_len = _at.read_int();
|
||||
if (remain_len > 0) {
|
||||
socket->rx_avail = true;
|
||||
}
|
||||
}
|
||||
char ip_address[sizeof("[1111:2222:3333:4444:5555:6666:7777:8888]:12345") + 1];
|
||||
int ip_len = _at.read_string(ip_address, sizeof(ip_address));
|
||||
tr_error("ip %s", ip_address);
|
||||
if (ip_len <= 0) {
|
||||
tr_error("Socket %d recvfrom addr!", socket->id);
|
||||
return NSAPI_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
if (address) {
|
||||
char *ip_start = ip_address;
|
||||
char *ip_stop;
|
||||
char *port_start;
|
||||
if (_stack_type == IPV6_STACK) {
|
||||
ip_start++; // skip '['
|
||||
ip_stop = strchr(ip_address, ']');
|
||||
if (ip_stop) {
|
||||
port_start = strchr(ip_stop, ':');
|
||||
}
|
||||
} else {
|
||||
ip_stop = strchr(ip_address, ':');
|
||||
port_start = ip_stop;
|
||||
}
|
||||
if (ip_stop && port_start) {
|
||||
char tmp_ch = *ip_stop;
|
||||
*ip_stop = '\0'; // split IP and port
|
||||
address->set_ip_address(ip_start);
|
||||
port_start++; // skip ':'
|
||||
int port = std::strtol(port_start, NULL, 10);
|
||||
address->set_port(port);
|
||||
tr_debug("IP address %s:%d", address->get_ip_address(), address->get_port());
|
||||
*ip_stop = tmp_ch; // restore original IP string
|
||||
}
|
||||
}
|
||||
|
||||
nsapi_size_or_error_t recv_len = _at.read_bytes((uint8_t *)buffer, len);
|
||||
|
||||
_at.resp_stop();
|
||||
|
||||
tr_debug("Socket %d, recvfrom %s, %d bytes (err %d)", socket->id, ip_address, len, _at.get_last_error());
|
||||
|
||||
return (_at.get_last_error() == NSAPI_ERROR_OK) ? recv_len : NSAPI_ERROR_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
// setup internet connection profile for sockets
|
||||
bool GEMALTO_CINTERION_CellularStack::create_connection_profile()
|
||||
{
|
||||
char conParamType[12];
|
||||
std::sprintf(conParamType, "GPRS%d", (_stack_type == IPV4_STACK) ? 0 : 6);
|
||||
_at.cmd_start("AT^SICS?");
|
||||
_at.cmd_stop();
|
||||
bool foundConnection = false;
|
||||
bool foundAPN = false;
|
||||
int connection_profile_id = CONNECTION_PROFILE_ID;
|
||||
_at.resp_start("^SICS:");
|
||||
while (_at.info_resp()) {
|
||||
int id = _at.read_int();
|
||||
tr_debug("SICS %d", id);
|
||||
if (id == connection_profile_id) {
|
||||
char paramTag[16];
|
||||
int paramTagLen = _at.read_string(paramTag, sizeof(paramTag));
|
||||
if (paramTagLen > 0) {
|
||||
tr_debug("paramTag %s", paramTag);
|
||||
char paramValue[100 + 1]; // APN may be up to 100 chars
|
||||
int paramValueLen = _at.read_string(paramValue, sizeof(paramValue));
|
||||
if (paramValueLen >= 0) {
|
||||
tr_debug("paramValue %s", paramValue);
|
||||
if (strcmp(paramTag, "conType") == 0) {
|
||||
tr_debug("conType %s", paramValue);
|
||||
if (strcmp(paramValue, conParamType) == 0) {
|
||||
foundConnection = true;
|
||||
}
|
||||
}
|
||||
if (strcmp(paramTag, "apn") == 0) {
|
||||
tr_debug("apn %s", paramValue);
|
||||
if (strcmp(paramValue, _apn ? _apn : "") == 0) {
|
||||
foundAPN = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_at.resp_stop();
|
||||
|
||||
if (!foundConnection) {
|
||||
tr_debug("Socket conType %s", conParamType);
|
||||
_at.cmd_start("AT^SICS=");
|
||||
_at.write_int(connection_profile_id);
|
||||
_at.write_string("conType");
|
||||
_at.write_string(conParamType);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
}
|
||||
|
||||
if (!foundAPN && _apn) {
|
||||
tr_debug("Socket APN %s", _apn ? _apn : "");
|
||||
_at.cmd_start("AT^SICS=");
|
||||
_at.write_int(connection_profile_id);
|
||||
_at.write_string("apn");
|
||||
_at.write_string(_apn);
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
}
|
||||
|
||||
// use URC mode
|
||||
_at.cmd_start("AT^SCFG=\"Tcp/withURCs\",\"on\"");
|
||||
_at.cmd_stop();
|
||||
_at.resp_start();
|
||||
_at.resp_stop();
|
||||
|
||||
tr_debug("Connection profile %d created, stack_type %d (err %d)", connection_profile_id, _stack_type, _at.get_last_error());
|
||||
return _at.get_last_error() == NSAPI_ERROR_OK;
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Copyright (c) 2018, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef GEMALTO_CINTERION_CELLULAR_STACK_H_
|
||||
#define GEMALTO_CINTERION_CELLULAR_STACK_H_
|
||||
|
||||
#include "AT_CellularStack.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
class GEMALTO_CINTERION_CellularStack : public AT_CellularStack {
|
||||
public:
|
||||
GEMALTO_CINTERION_CellularStack(ATHandler &atHandler, const char *apn, int cid, nsapi_ip_stack_t stack_type);
|
||||
virtual ~GEMALTO_CINTERION_CellularStack();
|
||||
|
||||
protected:
|
||||
|
||||
virtual nsapi_error_t socket_stack_init();
|
||||
|
||||
virtual int get_max_socket_count();
|
||||
|
||||
virtual bool is_protocol_supported(nsapi_protocol_t protocol);
|
||||
|
||||
virtual nsapi_error_t socket_close_impl(int sock_id);
|
||||
|
||||
virtual nsapi_error_t create_socket_impl(CellularSocket *socket);
|
||||
|
||||
virtual nsapi_size_or_error_t socket_sendto_impl(CellularSocket *socket, const SocketAddress &address,
|
||||
const void *data, nsapi_size_t size);
|
||||
|
||||
virtual nsapi_size_or_error_t socket_recvfrom_impl(CellularSocket *socket, SocketAddress *address,
|
||||
void *buffer, nsapi_size_t size);
|
||||
|
||||
private:
|
||||
CellularSocket *find_socket(int sock_id);
|
||||
void urc_sis();
|
||||
void urc_sisw();
|
||||
void urc_sisr();
|
||||
bool create_connection_profile();
|
||||
|
||||
const char *_apn;
|
||||
};
|
||||
|
||||
} // namespace mbed
|
||||
|
||||
#endif /* GEMALTO_CINTERION_CELLULAR_STACK_H_ */
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright (c) 2018, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "AT_CellularBase.h"
|
||||
#include "GEMALTO_CINTERION_Module.h"
|
||||
#include "CellularLog.h"
|
||||
|
||||
using namespace mbed;
|
||||
|
||||
// supported features as per ELS61-E2_ATC_V01.000
|
||||
static const AT_CellularBase::SupportedFeature unsupported_features_els61[] = {
|
||||
AT_CellularBase::AT_CGSN_WITH_TYPE,
|
||||
AT_CellularBase::SUPPORTED_FEATURE_END_MARK
|
||||
};
|
||||
|
||||
GEMALTO_CINTERION_Module::Model GEMALTO_CINTERION_Module::_model;
|
||||
|
||||
nsapi_error_t GEMALTO_CINTERION_Module::detect_model(const char *model)
|
||||
{
|
||||
static const AT_CellularBase::SupportedFeature *unsupported_features;
|
||||
if (strcmp(model, "ELS61") == 0) {
|
||||
_model = ModelELS61;
|
||||
unsupported_features = unsupported_features_els61;
|
||||
} else {
|
||||
tr_error("Cinterion model unsupported %s", model);
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
}
|
||||
tr_info("Cinterion model %s (%d)", model, _model);
|
||||
AT_CellularBase::set_unsupported_features(unsupported_features);
|
||||
return NSAPI_ERROR_OK;
|
||||
}
|
||||
|
||||
GEMALTO_CINTERION_Module::Model GEMALTO_CINTERION_Module::get_model()
|
||||
{
|
||||
return _model;
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright (c) 2018, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef GEMALTO_CINTERION_MODULE_H_
|
||||
#define GEMALTO_CINTERION_MODULE_H_
|
||||
|
||||
#include "nsapi_types.h"
|
||||
|
||||
namespace mbed {
|
||||
|
||||
class FileHandle;
|
||||
|
||||
class GEMALTO_CINTERION_Module {
|
||||
public:
|
||||
/** Actual model of cellular module is needed to make AT command adaptation at runtime
|
||||
* to support many different models in one cellular driver.
|
||||
*/
|
||||
enum Model {
|
||||
ModelUnknown = 0,
|
||||
ModelELS61
|
||||
};
|
||||
static nsapi_error_t detect_model(const char *model);
|
||||
static Model get_model();
|
||||
|
||||
private:
|
||||
static Model _model;
|
||||
};
|
||||
|
||||
} // namespace mbed
|
||||
|
||||
#endif // GEMALTO_CINTERION_MODULE_H_
|
Loading…
Reference in New Issue