nuttx-apps/lte/alt1250/usock_handlers/alt1250_sms.c
SPRESENSE 3650251c5e lte/alt1250: Fix bug that caused stack when executing the socket API
Fix a bug that caused the application to get stuck when executing
the socket API after waking up from hibernation and before executing
lte_hibernation_resume().
2024-02-09 14:52:05 +02:00

1051 lines
34 KiB
C

/****************************************************************************
* apps/lte/alt1250/usock_handlers/alt1250_sms.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you 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.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <nuttx/net/usrsock.h>
#include <nuttx/net/sms.h>
#include <assert.h>
#include "alt1250_dbg.h"
#include "alt1250_container.h"
#include "alt1250_socket.h"
#include "alt1250_devif.h"
#include "alt1250_usockevent.h"
#include "alt1250_postproc.h"
#include "alt1250_usrsock_hdlr.h"
#include "alt1250_sms.h"
#include "alt1250_evt.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#if defined(CONFIG_LTE_ALT1250_SMS_TOA)
# if defined(CONFIG_LTE_ALT1250_SMS_NAI_UNKNOWN)
# define ALT1250_SMS_NAI SMS_NAI_UNKNOWN
# elif defined(CONFIG_LTE_ALT1250_SMS_NAI_INTERNATIONAL)
# define ALT1250_SMS_NAI SMS_NAI_INTERNATIONAL
# elif defined(CONFIG_LTE_ALT1250_SMS_NAI_NATIONAL)
# define ALT1250_SMS_NAI SMS_NAI_NATIONAL
# elif defined(CONFIG_LTE_ALT1250_SMS_NAI_NETWORK_SPEC)
# define ALT1250_SMS_NAI SMS_NAI_NETWORK_SPEC
# elif defined(CONFIG_LTE_ALT1250_SMS_NAI_SUBSCRIBER)
# define ALT1250_SMS_NAI SMS_NAI_SUBSCRIBER
# elif defined(CONFIG_LTE_ALT1250_SMS_NAI_ALPANUMERIC)
# define ALT1250_SMS_NAI SMS_NAI_ALPANUMERIC
# elif defined(CONFIG_LTE_ALT1250_SMS_NAI_ABBREVIATED)
# define ALT1250_SMS_NAI SMS_NAI_ABBREVIATED
# elif defined(CONFIG_LTE_ALT1250_SMS_NAI_RESERVED)
# define ALT1250_SMS_NAI SMS_NAI_RESERVED
# endif
# if defined(CONFIG_LTE_ALT1250_SMS_NPI_UNKNOWN)
# define ALT1250_SMS_NPI SMS_NPI_UNKNOWN
# elif defined(CONFIG_LTE_ALT1250_SMS_NPI_ISDN)
# define ALT1250_SMS_NPI SMS_NPI_ISDN
# elif defined(CONFIG_LTE_ALT1250_SMS_NPI_DATA)
# define ALT1250_SMS_NPI SMS_NPI_DATA
# elif defined(CONFIG_LTE_ALT1250_SMS_NPI_TELEX)
# define ALT1250_SMS_NPI SMS_NPI_TELEX
# elif defined(CONFIG_LTE_ALT1250_SMS_NPI_SERVICE_CENTRE_SPEC)
# define ALT1250_SMS_NPI SMS_NPI_SERVICE_CENTRE_SPEC
# elif defined(CONFIG_LTE_ALT1250_SMS_NPI_SERVICE_CENTRE_SPEC2)
# define ALT1250_SMS_NPI SMS_NPI_SERVICE_CENTRE_SPEC2
# elif defined(CONFIG_LTE_ALT1250_SMS_NPI_NATIONAL)
# define ALT1250_SMS_NPI SMS_NPI_NATIONAL
# elif defined(CONFIG_LTE_ALT1250_SMS_NPI_PRIVATE)
# define ALT1250_SMS_NPI SMS_NPI_PRIVATE
# elif defined(CONFIG_LTE_ALT1250_SMS_NPI_ERMES)
# define ALT1250_SMS_NPI SMS_NPI_ERMES
# elif defined(CONFIG_LTE_ALT1250_SMS_NPI_RESERVED)
# define ALT1250_SMS_NPI SMS_NPI_RESERVED
# endif
#endif /* CONFIG_LTE_ALT1250_SMS_TOA */
/* RK_02_01_01_10xxx FW version that does not support SMS feature */
#define IS_SMS_UNAVAIL_FWVERSION(d) (!strncmp(MODEM_FWVERSION(d), \
"RK_02_01_01", 11))
/****************************************************************************
* Private Data
****************************************************************************/
static struct alt_container_s g_sms_container;
static struct postproc_s g_sms_postproc;
/****************************************************************************
* Private Functions Prototypes
****************************************************************************/
static int postproc_smsinit(FAR struct alt1250_s *dev,
FAR struct alt_container_s *reply,
FAR struct usock_s *usock,
FAR int32_t *usock_result,
FAR uint32_t *usock_xid,
FAR struct usock_ackinfo_s *ackinfo,
unsigned long arg);
static int postproc_smsinit_reopen(FAR struct alt1250_s *dev,
FAR struct alt_container_s *reply,
FAR struct usock_s *usock,
FAR int32_t *usock_result,
FAR uint32_t *usock_xid,
FAR struct usock_ackinfo_s *ackinfo,
unsigned long arg);
static int postproc_smsfin(FAR struct alt1250_s *dev,
FAR struct alt_container_s *reply,
FAR struct usock_s *usock,
FAR int32_t *usock_result,
FAR uint32_t *usock_xid,
FAR struct usock_ackinfo_s *ackinfo,
unsigned long arg);
static int postproc_smsfin_reopen(FAR struct alt1250_s *dev,
FAR struct alt_container_s *reply,
FAR struct usock_s *usock,
FAR int32_t *usock_result,
FAR uint32_t *usock_xid,
FAR struct usock_ackinfo_s *ackinfo,
unsigned long arg);
static int postproc_smssend(FAR struct alt1250_s *dev,
FAR struct alt_container_s *reply,
FAR struct usock_s *usock,
FAR int32_t *usock_result,
FAR uint32_t *usock_xid,
FAR struct usock_ackinfo_s *ackinfo,
unsigned long arg);
static int postproc_smsdelete(FAR struct alt1250_s *dev,
FAR struct alt_container_s *reply,
FAR struct usock_s *usock,
FAR int32_t *usock_result,
FAR uint32_t *usock_xid,
FAR struct usock_ackinfo_s *ackinfo,
unsigned long arg);
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* name: send_smsinit_command
****************************************************************************/
static int send_smsinit_command(FAR struct alt1250_s *dev,
FAR struct alt_container_s *container,
int usockid,
FAR postproc_hdlr_t func,
FAR int32_t *usock_result)
{
/* Dummy variable to receive replies by the container.
* No one refers to this address.
*/
FAR void *dummy_output = NULL;
clear_container(container);
set_container_ids(container, usockid, LTE_CMDID_SMS_INIT);
set_container_argument(container, NULL, 0);
set_container_response(container, &dummy_output, 1);
set_container_postproc(container, func, 0);
return altdevice_send_command(dev, dev->altfd, container, usock_result);
}
/****************************************************************************
* name: send_smsfin_command
****************************************************************************/
static int send_smsfin_command(FAR struct alt1250_s *dev,
FAR struct alt_container_s *container,
int usockid,
FAR postproc_hdlr_t func,
FAR int32_t *usock_result)
{
/* Dummy variable to receive replies by the container.
* No one refers to this address.
*/
FAR void *dummy_output = NULL;
clear_container(container);
set_container_ids(container, usockid, LTE_CMDID_SMS_FIN);
set_container_argument(container, NULL, 0);
set_container_response(container, &dummy_output, 1);
set_container_postproc(container, func, 0);
return altdevice_send_command(dev, dev->altfd, container, usock_result);
}
/****************************************************************************
* name: send_smssend_command
****************************************************************************/
static int send_smssend_command(FAR struct alt1250_s *dev,
FAR struct alt_container_s *container,
FAR struct usock_s *usock,
FAR struct sms_send_msg_s *msg,
FAR uint16_t msg_len,
FAR int32_t *usock_result)
{
int idx = 0;
FAR void *inparam[6];
uint8_t chset = SMS_CHSET_UCS2;
/* Thease members are referenced only when sending a command and
* not when receiving a response, so local variables are used.
*/
inparam[0] = msg;
inparam[1] = &msg_len;
inparam[2] = &dev->sms_info.en_status_report;
inparam[3] = &dev->sms_info.dest_scaddr;
inparam[4] = &chset;
#if defined(CONFIG_LTE_ALT1250_SMS_TOA)
inparam[5] = &dev->sms_info.dest_toa;
#else
inparam[5] = NULL;
#endif
USOCKET_SET_RESPONSE(usock, idx++, USOCKET_REFID(usock));
USOCKET_SET_RESPONSE(usock, idx++, &USOCKET_REQBUFLEN(usock));
set_container_ids(container, USOCKET_USOCKID(usock), LTE_CMDID_SMS_SEND);
set_container_argument(container, inparam, nitems(inparam));
set_container_response(container, USOCKET_REP_RESPONSE(usock), idx);
set_container_postproc(container, postproc_smssend, 0);
return altdevice_send_command(dev, dev->altfd, container, usock_result);
}
/****************************************************************************
* name: send_smsdelete_command
****************************************************************************/
static int send_smsdelete_command(FAR struct alt1250_s *dev,
FAR struct alt_container_s *container,
FAR struct usock_s *usock,
uint16_t msg_index,
FAR int32_t *usock_result)
{
/* Dummy variable to receive replies by the container.
* No one refers to this address.
*/
FAR void *dummy_output = NULL;
FAR void *inparam[1];
/* This member is referenced only when sending a command and
* not when receiving a response, so local variables is used.
*/
inparam[0] = &msg_index;
set_container_ids(container, USOCKET_USOCKID(usock), LTE_CMDID_SMS_DELETE);
set_container_argument(container, inparam, nitems(inparam));
set_container_response(container, &dummy_output, 1);
set_container_postproc(container, postproc_smsdelete, 0);
return altdevice_send_command(dev, dev->altfd, container, usock_result);
}
/****************************************************************************
* name: send_smsreportrecv_command
****************************************************************************/
static int send_smsreportrecv_command(FAR struct alt1250_s *dev,
FAR int32_t *usock_result)
{
struct alt_container_s container = {
0
};
set_container_ids(&container, 0, LTE_CMDID_SMS_REPORT_RECV);
return altdevice_send_command(dev, dev->altfd, &container, usock_result);
}
/****************************************************************************
* name: reset_sms_info
****************************************************************************/
void reset_sms_info(FAR struct alt1250_s *dev)
{
SMS_SET_STATE(&dev->sms_info, SMS_STATE_UNINIT);
dev->sms_info.msg_index = 0;
dev->sms_info.read_msglen = 0;
dev->sms_info.total_msglen = 0;
dev->sms_info.is_first_msg = false;
#if defined(CONFIG_LTE_ALT1250_SMS_TOA)
dev->sms_info.dest_toa = SMS_SET_TOA(ALT1250_SMS_NAI, ALT1250_SMS_NPI);
#endif
}
/****************************************************************************
* name: fill_recv_ackinfo
****************************************************************************/
static bool fill_recv_ackinfo(FAR struct alt1250_s *dev,
FAR struct usock_s *usock,
FAR int32_t *usock_result,
FAR struct usock_ackinfo_s *ackinfo)
{
FAR void **arg;
FAR uint8_t *msg_head;
uint16_t remain_msglen;
/* arg[0]: sms msg index
* arg[1]: sms msg length
* arg[2]: Maximum number of msg for concatenate sms.
* arg[3]: Current number of msg for concatenate sms.
* arg[4]: sms msg
*/
arg = alt1250_getevtarg(LTE_CMDID_SMS_REPORT_RECV);
assert(arg && arg[4]);
msg_head = (FAR uint8_t *)arg[4];
remain_msglen = dev->sms_info.msglen - dev->sms_info.read_msglen;
if (!dev->sms_info.is_first_msg)
{
/* In the case of a concatenated SMS, the header information is only
* given to the first SMS. Therefore, if the SMS is not the first
* one, the header information is shifted and read.
*/
msg_head += sizeof(struct sms_recv_msg_header_s);
remain_msglen -= sizeof(struct sms_recv_msg_header_s);
}
*usock_result = MIN(USOCKET_REQBUFLEN(usock), remain_msglen);
ackinfo->valuelen = 0;
ackinfo->valuelen_nontrunc = 0;
ackinfo->value_ptr = NULL;
ackinfo->buf_ptr = msg_head + dev->sms_info.read_msglen;
/* return is empty */
return (USOCKET_REQBUFLEN(usock) < remain_msglen) ? false : true;
}
/****************************************************************************
* name: notify_read_ready
****************************************************************************/
static void notify_read_ready(FAR struct alt1250_s *dev, uint16_t msg_index,
uint16_t msg_len)
{
dev->sms_info.msg_index = msg_index;
dev->sms_info.msglen = msg_len;
dev->sms_info.read_msglen = 0;
usocket_smssock_readready(dev);
}
/****************************************************************************
* name: notify_abort
****************************************************************************/
static void notify_abort(FAR struct alt1250_s *dev)
{
reset_sms_info(dev);
usocket_smssock_abort(dev);
}
/****************************************************************************
* name: update_concat_size
****************************************************************************/
static void update_concat_size(FAR struct alt1250_s *dev, uint16_t msg_index,
uint16_t msg_len, uint8_t max_num,
uint8_t seq_num,
FAR struct sms_recv_msg_header_s *sms_msg)
{
int32_t usock_result = OK;
dev->sms_info.total_msglen += sms_msg->datalen;
if (max_num == seq_num)
{
/* In case of last of concatenated sms */
/* Send only SMS FIN command to avoid receiving the next SMS REPORT
* command. If SMS REPORT response is sent before SMS FIN command
* is sent, unexpected SMS REPORT command may be received.
*/
send_smsfin_command(dev, &g_sms_container, 0,
postproc_smsfin_reopen, &usock_result);
if (usock_result < 0)
{
notify_abort(dev);
}
else
{
SMS_SET_STATE(&dev->sms_info, SMS_STATE_REOPEN);
dev->sms_info.is_first_msg = true;
}
}
else
{
send_smsreportrecv_command(dev, &usock_result);
if (usock_result < 0)
{
notify_abort(dev);
}
}
}
/****************************************************************************
* name: handle_recvmsg
****************************************************************************/
static void handle_recvmsg(FAR struct alt1250_s *dev, uint16_t msg_index,
uint16_t msg_len, uint8_t max_num,
uint8_t seq_num,
FAR struct sms_recv_msg_header_s *sms_msg)
{
if (max_num == 0)
{
/* In case of not concatenated sms */
dev->sms_info.total_msglen = sms_msg->datalen;
dev->sms_info.is_first_msg = true;
SMS_SET_STATE(&dev->sms_info, SMS_STATE_READ_READY);
/* Notify usrsock of the read ready event. */
notify_read_ready(dev, msg_index, msg_len);
}
else
{
/* In case of concatenated sms */
SMS_SET_STATE(&dev->sms_info, SMS_STATE_CALC_SIZE);
dev->sms_info.msg_index = msg_index;
update_concat_size(dev, msg_index, msg_len, max_num, seq_num, sms_msg);
}
}
/****************************************************************************
* name: postproc_smsinit
****************************************************************************/
static int postproc_smsinit(FAR struct alt1250_s *dev,
FAR struct alt_container_s *reply,
FAR struct usock_s *usock,
FAR int32_t *usock_result,
FAR uint32_t *usock_xid,
FAR struct usock_ackinfo_s *ackinfo,
unsigned long arg)
{
int ret = REP_SEND_ACK_TXREADY;
dbg_alt1250("%s start\n", __func__);
*usock_result = CONTAINER_RESPRES(reply);
if (*usock_result < 0)
{
ret = REP_SEND_ACK;
}
else
{
*usock_result = USOCKET_USOCKID(usock);
ackinfo->usockid = USOCKET_USOCKID(usock);
SMS_SET_STATE(&dev->sms_info, SMS_STATE_WAITMSG);
}
return ret;
}
/****************************************************************************
* name: postproc_smsinit_reopen
****************************************************************************/
static int postproc_smsinit_reopen(FAR struct alt1250_s *dev,
FAR struct alt_container_s *reply,
FAR struct usock_s *usock,
FAR int32_t *usock_result,
FAR uint32_t *usock_xid,
FAR struct usock_ackinfo_s *ackinfo,
unsigned long arg)
{
dbg_alt1250("%s start\n", __func__);
*usock_result = CONTAINER_RESPRES(reply);
if (*usock_result >= 0)
{
SMS_SET_STATE(&dev->sms_info, SMS_STATE_WAITMSG_CONCAT);
}
else
{
notify_abort(dev);
}
return REP_NO_ACK_WOFREE;
}
/****************************************************************************
* name: postproc_smsfin
****************************************************************************/
static int postproc_smsfin(FAR struct alt1250_s *dev,
FAR struct alt_container_s *reply,
FAR struct usock_s *usock,
FAR int32_t *usock_result,
FAR uint32_t *usock_xid,
FAR struct usock_ackinfo_s *ackinfo,
unsigned long arg)
{
dbg_alt1250("%s start\n", __func__);
*usock_xid = USOCKET_XID(usock);
*usock_result = CONTAINER_RESPRES(reply);
usocket_free(usock);
return REP_SEND_ACK;
}
/****************************************************************************
* name: postproc_smsfin_reopen
****************************************************************************/
static int postproc_smsfin_reopen(FAR struct alt1250_s *dev,
FAR struct alt_container_s *reply,
FAR struct usock_s *usock,
FAR int32_t *usock_result,
FAR uint32_t *usock_xid,
FAR struct usock_ackinfo_s *ackinfo,
unsigned long arg)
{
dbg_alt1250("%s start\n", __func__);
if (SMS_STATE(&dev->sms_info) == SMS_STATE_UNINIT)
{
dbg_alt1250("All sms sockets are closed\n");
}
else
{
send_smsinit_command(dev, reply, 0, postproc_smsinit_reopen,
usock_result);
if (*usock_result < 0)
{
notify_abort(dev);
}
}
return REP_NO_ACK_WOFREE;
}
/****************************************************************************
* name: postproc_smssend
****************************************************************************/
static int postproc_smssend(FAR struct alt1250_s *dev,
FAR struct alt_container_s *reply,
FAR struct usock_s *usock,
FAR int32_t *usock_result,
FAR uint32_t *usock_xid,
FAR struct usock_ackinfo_s *ackinfo,
unsigned long arg)
{
int ret = REP_SEND_ACK_TXREADY;
dbg_alt1250("%s start\n", __func__);
/* resp[0]: referese ID list */
*usock_xid = USOCKET_XID(usock);
*usock_result = CONTAINER_RESPRES(reply);
if (*usock_result == -EPROTO)
{
lte_errinfo_t errinfo;
alt1250_geterrinfo(&errinfo);
*usock_result = (errinfo.err_indicator & LTE_ERR_INDICATOR_ERRCODE) ?
-errinfo.err_result_code : *usock_result;
}
ackinfo->usockid = USOCKET_USOCKID(usock);
return ret;
}
/****************************************************************************
* name: postproc_smsdelete
****************************************************************************/
static int postproc_smsdelete(FAR struct alt1250_s *dev,
FAR struct alt_container_s *reply,
FAR struct usock_s *usock,
FAR int32_t *usock_result,
FAR uint32_t *usock_xid,
FAR struct usock_ackinfo_s *ackinfo,
unsigned long arg)
{
int ret = REP_SEND_ACK;
dbg_alt1250("%s start\n", __func__);
*usock_xid = USOCKET_XID(usock);
*usock_result = CONTAINER_RESPRES(reply);
if (*usock_result >= 0)
{
ret = send_smsreportrecv_command(dev, usock_result);
if (*usock_result >= 0)
{
/* In case of success */
ret = REP_SEND_DACK;
fill_recv_ackinfo(dev, usock, usock_result, ackinfo);
dev->sms_info.is_first_msg = false;
}
}
return ret;
}
/****************************************************************************
* name: sms_report_event
****************************************************************************/
static void sms_report_event(FAR struct alt1250_s *dev, uint16_t msg_index,
uint16_t msg_len, uint8_t max_num,
uint8_t seq_num,
FAR struct sms_recv_msg_header_s *sms_msg)
{
dbg_alt1250("%s start\n", __func__);
assert(msg_len >= sizeof(struct sms_recv_msg_header_s));
switch (SMS_STATE(&dev->sms_info))
{
case SMS_STATE_UNINIT:
dbg_alt1250("All sms sockets are closed\n");
break;
case SMS_STATE_REOPEN:
dbg_alt1250("Receive report msg in REOPEN state\n");
break;
case SMS_STATE_READ_READY:
/* Notify usrsock of the read ready event. */
notify_read_ready(dev, msg_index, msg_len);
break;
case SMS_STATE_WAITMSG:
handle_recvmsg(dev, msg_index, msg_len, max_num, seq_num, sms_msg);
break;
case SMS_STATE_WAITMSG_CONCAT:
if (dev->sms_info.msg_index != msg_index)
{
/* In case of unexpected SMS received.
* Therefore, start over from the beginning.
*/
handle_recvmsg(dev, msg_index, msg_len, max_num, seq_num,
sms_msg);
}
else
{
/* In case of expected concatenated SMS received. */
sms_msg->datalen = dev->sms_info.total_msglen;
SMS_SET_STATE(&dev->sms_info, SMS_STATE_READ_READY);
/* Notify usrsock of the read ready event. */
notify_read_ready(dev, msg_index, msg_len);
}
break;
case SMS_STATE_CALC_SIZE:
update_concat_size(dev, msg_index, msg_len, max_num, seq_num,
sms_msg);
break;
default:
dbg_alt1250("Receive report msg in unexpected state: %d\n",
SMS_STATE(&dev->sms_info));
break;
}
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* name: alt1250_sms_init
****************************************************************************/
int alt1250_sms_init(FAR struct alt1250_s *dev, FAR struct usock_s *usock,
FAR int32_t *usock_result,
FAR struct usock_ackinfo_s *ackinfo)
{
int ret = REP_SEND_ACK_WOFREE;
FAR struct alt_container_s *container;
dbg_alt1250("%s start\n", __func__);
if (IS_SMS_UNAVAIL_FWVERSION(dev))
{
dbg_alt1250("This ALT1250 FW version does not support SMS.\n");
*usock_result = -EAFNOSUPPORT;
return REP_SEND_ACK_WOFREE;
}
if (SMS_STATE(&dev->sms_info) == SMS_STATE_UNINIT)
{
container = container_alloc();
if (container == NULL)
{
dbg_alt1250("no container\n");
return REP_NO_CONTAINER;
}
ret = send_smsinit_command(dev, container, USOCKET_USOCKID(usock),
postproc_smsinit, usock_result);
if (IS_NEED_CONTAINER_FREE(ret))
{
container_free(container);
}
}
else
{
ret = REP_SEND_ACK_TXREADY;
ackinfo->usockid = USOCKET_USOCKID(usock);
}
return ret;
}
/****************************************************************************
* name: alt1250_sms_fin
****************************************************************************/
int alt1250_sms_fin(FAR struct alt1250_s *dev, FAR struct usock_s *usock,
FAR int32_t *usock_result)
{
int ret = REP_SEND_ACK_WOFREE;
FAR struct alt_container_s *container;
dbg_alt1250("%s start\n", __func__);
*usock_result = OK;
if (usocket_smssock_num(dev) == 1)
{
if (SMS_STATE(&dev->sms_info) == SMS_STATE_REOPEN)
{
return REP_NO_CONTAINER;
}
container = container_alloc();
if (container == NULL)
{
dbg_alt1250("no container\n");
return REP_NO_CONTAINER;
}
ret = send_smsfin_command(dev, container, USOCKET_USOCKID(usock),
postproc_smsfin, usock_result);
if (IS_NEED_CONTAINER_FREE(ret))
{
container_free(container);
}
alt1250_reset_sms_info(dev);
if (*usock_result < 0)
{
usocket_free(usock);
}
}
else
{
usocket_free(usock);
}
return ret;
}
/****************************************************************************
* name: alt1250_sms_send
****************************************************************************/
int alt1250_sms_send(FAR struct alt1250_s *dev,
FAR struct usrsock_request_sendto_s *req,
FAR struct usock_s *usock,
FAR int32_t *usock_result)
{
int ret = REP_SEND_ACK_WOFREE;
FAR struct alt_container_s *container;
dbg_alt1250("%s start\n", __func__);
if (SMS_STATE(&dev->sms_info) == SMS_STATE_REOPEN)
{
/* Sending the SMS send command now will fail because the
* SMS fin command has already been sent.
* Therefore, return REP_NO_CONTAINER and wait for the status to
* become ready to send.
*/
return REP_NO_CONTAINER;
}
container = container_alloc();
if (container == NULL)
{
dbg_alt1250("no container\n");
return REP_NO_CONTAINER;
}
if (req->addrlen > 0)
{
/* Ignore destination address. */
usockif_discard(dev->usockfd, req->addrlen);
}
if (req->buflen > 0 &&
req->buflen <= sizeof(struct sms_send_msg_s) + (SMS_MAX_DATALEN * 2))
{
ret = usockif_readreqsendbuf(dev->usockfd, dev->tx_buff, req->buflen);
if (ret < 0)
{
*usock_result = ret;
container_free(container);
return REP_SEND_ACK_WOFREE;
}
ret = send_smssend_command(dev, container, usock,
(FAR struct sms_send_msg_s *)dev->tx_buff,
req->buflen,
usock_result);
if (IS_NEED_CONTAINER_FREE(ret))
{
container_free(container);
}
}
else
{
/* In case of invalid buffer length */
*usock_result = -EINVAL;
container_free(container);
ret = REP_SEND_ACK_WOFREE;
}
return ret;
}
/****************************************************************************
* name: alt1250_sms_recv
****************************************************************************/
int alt1250_sms_recv(FAR struct alt1250_s *dev,
FAR struct usrsock_request_recvfrom_s *req,
FAR struct usock_s *usock,
FAR int32_t *usock_result,
FAR struct usock_ackinfo_s *ackinfo)
{
int ret = REP_SEND_ACK_WOFREE;
FAR struct alt_container_s *container;
dbg_alt1250("%s start\n", __func__);
if (SMS_STATE(&dev->sms_info) == SMS_STATE_REOPEN)
{
return REP_NO_CONTAINER;
}
if (fill_recv_ackinfo(dev, usock, usock_result, ackinfo))
{
/* In case of buffer is empty */
container = container_alloc();
if (container == NULL)
{
dbg_alt1250("no container\n");
return REP_NO_CONTAINER;
}
/* If the application has read all data,
* change the status to SMS_STATE_WAITMSG.
*/
dev->sms_info.total_msglen -= (dev->sms_info.msglen -
sizeof(struct sms_recv_msg_header_s));
if (dev->sms_info.total_msglen == 0)
{
SMS_SET_STATE(&dev->sms_info, SMS_STATE_WAITMSG);
}
/* Delete the SMS in the ALT1250 because one SMS was read. */
ret = send_smsdelete_command(dev, container, usock,
dev->sms_info.msg_index, usock_result);
if (IS_NEED_CONTAINER_FREE(ret))
{
container_free(container);
}
}
else
{
/* In case of buffer is not empty */
ret = REP_SEND_DACK_RXREADY;
dev->sms_info.read_msglen += req->max_buflen;
ackinfo->usockid = USOCKET_USOCKID(usock);
}
return ret;
}
/****************************************************************************
* name: usockreq_ioctl_sms
****************************************************************************/
int usockreq_ioctl_sms(FAR struct alt1250_s *dev,
FAR struct usrsock_request_buff_s *req,
FAR int32_t *usock_result,
FAR uint32_t *usock_xid,
FAR struct usock_ackinfo_s *ackinfo)
{
FAR struct usrsock_request_ioctl_s *request = &req->request.ioctl_req;
FAR struct lte_smsreq_s *smsreq = &req->req_ioctl.smsreq;
FAR struct usock_s *usock;
int ret = REP_SEND_ACK_WOFREE;
dbg_alt1250("%s start\n", __func__);
*usock_result = -EBADFD;
usock = usocket_search(dev, request->usockid);
if (usock)
{
switch (request->cmd)
{
case SIOCSMSENSTREP:
*usock_result = OK;
dev->sms_info.en_status_report = smsreq->smsru.enable;
break;
case SIOCSMSGREFID:
*usock_result = OK;
ret = REP_SEND_DACK;
ackinfo->valuelen = sizeof(struct lte_smsreq_s);
ackinfo->valuelen_nontrunc = sizeof(struct lte_smsreq_s);
ackinfo->value_ptr = (FAR uint8_t *)USOCKET_REFID(usock);
ackinfo->buf_ptr = NULL;
break;
case SIOCSMSSSCA:
*usock_result = OK;
memcpy(&dev->sms_info.dest_scaddr, &smsreq->smsru.scaddr,
sizeof(struct sms_sc_addr_s));
break;
default:
*usock_result = -EINVAL;
break;
}
}
return ret;
}
/****************************************************************************
* name: perform_sms_report_event
****************************************************************************/
uint64_t perform_sms_report_event(FAR struct alt1250_s *dev, uint64_t bitmap)
{
uint64_t bit = 0ULL;
FAR void **arg;
if (alt1250_checkcmdid(LTE_CMDID_SMS_REPORT_RECV, bitmap, &bit))
{
arg = alt1250_getevtarg(LTE_CMDID_SMS_REPORT_RECV);
if (arg && arg[0] && arg[1] && arg[2] && arg[3] && arg[4])
{
/* arg[0]: sms msg index
* arg[1]: sms msg length
* arg[2]: Maximum number of msg for concatenate sms.
* arg[3]: Current number of msg for concatenate sms.
* arg[4]: sms msg
*/
sms_report_event(dev, *((FAR uint16_t *)arg[0]),
*((FAR uint16_t *)arg[1]),
*((FAR uint8_t *)arg[2]),
*((FAR uint8_t *)arg[3]),
(FAR struct sms_recv_msg_header_s *)arg[4]);
}
alt1250_setevtarg_writable(LTE_CMDID_SMS_REPORT_RECV);
}
return bit;
}
/****************************************************************************
* name: alt1250_sms_initcontainer
****************************************************************************/
void alt1250_sms_initcontainer(FAR struct alt1250_s *dev)
{
g_sms_container.priv = (unsigned long)&g_sms_postproc;
clear_container(&g_sms_container);
}
/****************************************************************************
* name: alt1250_reset_sms_info
****************************************************************************/
void alt1250_reset_sms_info(FAR struct alt1250_s *dev)
{
notify_abort(dev);
}