nuttx/drivers/modem/alt1250/altcom_hdlr_sms.c

315 lines
10 KiB
C
Raw Normal View History

/****************************************************************************
* drivers/modem/alt1250/altcom_hdlr_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 <stdint.h>
#include <stddef.h>
#include <string.h>
#include <errno.h>
#include <arpa/inet.h>
#include "altcom_cmd_sms.h"
#include "altcom_errno.h"
/****************************************************************************
* Public Functions
****************************************************************************/
int32_t altcom_smsinit_pkt_compose(FAR void **arg, size_t arglen,
uint8_t altver, FAR uint8_t *pktbuf,
const size_t pktsz, FAR uint16_t *altcid)
{
FAR struct apicmd_sms_init_req_s *out =
(FAR struct apicmd_sms_init_req_s *)pktbuf;
*altcid = APICMDID_SMS_INIT;
out->types = ALTCOM_SMS_MSG_TYPE_SEND | ALTCOM_SMS_MSG_TYPE_RECV |
ALTCOM_SMS_MSG_TYPE_DELIVER_REPORT;
out->storage_use = 1; /* always use storage */
return sizeof(struct apicmd_sms_init_req_s);
}
int32_t altcom_smsfin_pkt_compose(FAR void **arg, size_t arglen,
uint8_t altver, FAR uint8_t *pktbuf,
const size_t pktsz, FAR uint16_t *altcid)
{
*altcid = APICMDID_SMS_FIN;
return 0;
}
int32_t altcom_smssend_pkt_compose(FAR void **arg, size_t arglen,
uint8_t altver, FAR uint8_t *pktbuf,
const size_t pktsz, FAR uint16_t *altcid)
{
int32_t size = 0;
int i;
FAR struct apicmd_sms_send_req_s *out =
(FAR struct apicmd_sms_send_req_s *)pktbuf;
FAR struct sms_send_msg_s *msg = (FAR struct sms_send_msg_s *)arg[0];
uint16_t msglen = *((FAR uint16_t *)arg[1]);
bool en_status_report = *((FAR bool *)arg[2]);
FAR struct sms_sc_addr_s *scaddr = (FAR struct sms_sc_addr_s *)arg[3];
uint8_t chset = *((FAR uint8_t *)arg[4]);
FAR uint8_t *dest_toa = (FAR uint8_t *)arg[5];
if (msglen > pktsz)
{
return -ENOBUFS;
}
if ((msg->header.destaddrlen % 2) || (msg->header.datalen % 2) ||
(msg->header.destaddrlen > (SMS_MAX_ADDRLEN * 2)) ||
(msg->header.datalen > (SMS_MAX_DATALEN * 2)) ||
(scaddr->addrlen % 2) || (scaddr->addrlen > (SMS_MAX_ADDRLEN * 2)))
{
/* destaddrlen and datalen must be even numbers */
return -EINVAL;
}
out->sc_addr.toa = scaddr->toa;
out->sc_addr.length = scaddr->addrlen;
/* Swap sc address */
for (i = 0; i < (scaddr->addrlen / 2); i++)
{
out->sc_addr.address[i] = htons(scaddr->addr[i]);
}
out->valid_indicator = ALTCOM_SMS_MSG_VALID_UD;
out->valid_indicator |= en_status_report ? ALTCOM_SMS_MSG_VALID_SRR : 0;
out->dest_addr.toa = (dest_toa == NULL) ? 0 : *dest_toa;
out->dest_addr.length = msg->header.destaddrlen;
/* Swap destination address */
for (i = 0; i < (msg->header.destaddrlen / 2); i++)
{
out->dest_addr.address[i] = htons(msg->header.destaddr[i]);
}
switch (chset)
{
case SMS_CHSET_UCS2:
chset = ALTCOM_SMS_CHSET_UCS2;
break;
case SMS_CHSET_GSM7:
chset = ALTCOM_SMS_CHSET_GSM7;
break;
case SMS_CHSET_BINARY:
chset = ALTCOM_SMS_CHSET_BINARY;
break;
default:
return -EINVAL;
}
out->userdata.chset = ALTCOM_SMS_CHSET_UCS2;
out->userdata.data_len = htons(msg->header.datalen);
/* Swap data */
for (i = 0; i < (msg->header.datalen / 2); i++)
{
out->user_data[i] = htons(msg->data[i]);
}
*altcid = APICMDID_SMS_SEND;
size = sizeof(struct apicmd_sms_send_req_s) + msg->header.datalen;
return size;
}
int32_t altcom_smsdelete_pkt_compose(FAR void **arg, size_t arglen,
uint8_t altver, FAR uint8_t *pktbuf,
const size_t pktsz,
FAR uint16_t *altcid)
{
FAR struct apicmd_sms_delete_s *out =
(FAR struct apicmd_sms_delete_s *)pktbuf;
uint16_t msg_index = *(FAR uint16_t *)arg[0];
*altcid = APICMDID_SMS_DELETE;
out->index = htons(msg_index);
out->types = 0;
return sizeof(struct apicmd_sms_delete_s);
}
int32_t altcom_smsreportrecv_pkt_compose(FAR void **arg, size_t arglen,
uint8_t altver, FAR uint8_t *pktbuf,
const size_t pktsz,
FAR uint16_t *altcid)
{
FAR struct apicmd_sms_res_s *out =
(FAR struct apicmd_sms_res_s *)pktbuf;
*altcid = APICMDID_SMS_REPORT_RECV | ALTCOM_CMDID_REPLY_BIT;
out->result = htonl(0); /* always success */
return sizeof(struct apicmd_sms_res_s);
}
int32_t altcom_smscommon_pkt_parse(FAR struct alt1250_dev_s *dev,
FAR uint8_t *pktbuf, size_t pktsz,
uint8_t altver, FAR void **arg,
size_t arglen, FAR uint64_t *bitmap)
{
FAR struct apicmd_sms_res_s *in =
(FAR struct apicmd_sms_res_s *)pktbuf;
return altcom_geterrcode(in->result);
}
int32_t altcom_smssend_pkt_parse(FAR struct alt1250_dev_s *dev,
FAR uint8_t *pktbuf, size_t pktsz,
uint8_t altver, FAR void **arg,
size_t arglen, FAR uint64_t *bitmap)
{
FAR struct apicmd_sms_sendres_s *in =
(FAR struct apicmd_sms_sendres_s *)pktbuf;
FAR struct sms_refids_s *refid = (FAR struct sms_refids_s *)arg[0];
uint16_t msglen = *((FAR uint16_t *)arg[1]);
int32_t sendresult = altcom_geterrcode(in->result);
if (sendresult >= 0)
{
refid->nrefid = in->mr_num;
memcpy(refid->refid, in->mr_list, sizeof(refid->refid));
}
return (sendresult < 0) ? sendresult : msglen;
}
int32_t altcom_smsreportrecv_pkt_parse(FAR struct alt1250_dev_s *dev,
FAR uint8_t *pktbuf, size_t pktsz,
uint8_t altver, FAR void **arg,
size_t arglen, FAR uint64_t *bitmap)
{
int i;
FAR struct apicmd_sms_reprecv_s *in =
(FAR struct apicmd_sms_reprecv_s *)pktbuf;
FAR uint16_t *msg_index = (FAR uint16_t *)arg[0];
FAR uint16_t *msg_sz = (FAR uint16_t *)arg[1];
FAR uint8_t *maxnum = (FAR uint8_t *)arg[2];
FAR uint8_t *seqnum = (FAR uint8_t *)arg[3];
FAR struct sms_recv_msg_header_s *msgheader =
(FAR struct sms_recv_msg_header_s *)arg[4];
*msg_index = ntohs(in->index);
*maxnum = 0;
*seqnum = 0;
if (in->msg.type == ALTCOM_SMS_MSG_TYPE_RECV)
{
FAR struct sms_deliver_msg_s *deliver =
(FAR struct sms_deliver_msg_s *)arg[4];
*msg_sz = sizeof(struct sms_deliver_msg_s) +
ntohs(in->msg.u.recv.userdata.data_len);
if (in->msg.u.recv.valid_indicator & ALTCOM_SMS_MSG_VALID_CONCAT_HDR)
{
*maxnum = in->msg.u.recv.concat_hdr.max_num;
*seqnum = in->msg.u.recv.concat_hdr.seq_num;
}
msgheader->msgtype = SMS_MSG_TYPE_DELIVER;
memcpy(&msgheader->send_time, &in->msg.u.recv.sc_time,
sizeof(msgheader->send_time));
msgheader->srcaddrlen = in->msg.u.recv.src_addr.length;
if (msgheader->srcaddrlen > SMS_MAX_ADDRLEN * 2)
{
m_err("Unexpected src addrlen: %u\n", msgheader->srcaddrlen);
return -EINVAL;
}
/* Swap source address */
for (i = 0; i < (msgheader->srcaddrlen / 2); i++)
{
msgheader->srcaddr[i] = ntohs(in->msg.u.recv.src_addr.address[i]);
}
msgheader->datalen = ntohs(in->msg.u.recv.userdata.data_len);
if (msgheader->datalen > (SMS_MAX_DATALEN * 2))
{
m_err("Unexpected datalen: %u\n", msgheader->datalen);
return -EINVAL;
}
/* Swap data */
for (i = 0; i < (msgheader->datalen / 2); i++)
{
deliver->data[i] = ntohs(in->msg.u.recv.user_data[i]);
}
m_info("[recv msg] msg size: %u\n", *msg_sz);
m_info(" maxnum: %u, seqnum: %u\n", *maxnum, *seqnum);
m_info(" msgtype: %u\n", msgheader->msgtype);
m_info(" srcaddrlen: %u\n", msgheader->srcaddrlen);
m_info(" datalen: %u\n", msgheader->datalen);
}
else if (in->msg.type == ALTCOM_SMS_MSG_TYPE_DELIVER_REPORT)
{
FAR struct sms_status_report_msg_s *report =
(FAR struct sms_status_report_msg_s *)arg[4];
*msg_sz = sizeof(struct sms_status_report_msg_s);
msgheader->msgtype = SMS_MSG_TYPE_STATUS_REPORT;
memcpy(&msgheader->send_time, &in->msg.u.delivery_report.sc_time,
sizeof(msgheader->send_time));
msgheader->srcaddrlen = 0;
memset(msgheader->srcaddr, 0, sizeof(msgheader->srcaddr));
msgheader->datalen = sizeof(struct sms_status_report_s);
report->status_report.refid = in->msg.u.delivery_report.ref_id;
report->status_report.status = in->msg.u.delivery_report.status;
memcpy(&report->status_report.discharge_time,
&in->msg.u.delivery_report.discharge_time,
sizeof(report->status_report.discharge_time));
m_info("[staus report] msg size: %u\n", *msg_sz);
m_info(" msgtype: %u\n", msgheader->msgtype);
m_info(" datalen: %u\n", msgheader->datalen);
m_info(" refid: %u\n", report->status_report.refid);
m_info(" status: %u\n", report->status_report.status);
}
else
{
return -EINVAL;
}
return 0;
}