NMT / SMS: Short Message Service support

This commit is contained in:
Andreas Eversberg
2016-07-04 19:52:00 +02:00
parent 64c829909b
commit e7fa08b6df
11 changed files with 1017 additions and 10 deletions

View File

@@ -22,6 +22,7 @@
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include "../common/debug.h"
#include "../common/timer.h"
#include "../common/call.h"
@@ -30,6 +31,8 @@
#include "dsp.h"
#include "frame.h"
static int sms_ref = 0;
/* Call reference for calls from mobile station to network
This offset of 0x400000000 is required for MNCC interface. */
static int new_callref = 0x40000000;
@@ -283,7 +286,7 @@ static void nmt_timeout(struct timer *timer);
static void nmt_go_idle(nmt_t *nmt);
/* Create transceiver instance and link to a list. */
int nmt_create(int channel, enum nmt_chan_type chan_type, const char *sounddev, int samplerate, int cross_channels, double rx_gain, int pre_emphasis, int de_emphasis, const char *write_wave, const char *read_wave, uint8_t ms_power, uint8_t traffic_area, uint8_t area_no, int compandor, int supervisory, int loopback)
int nmt_create(int channel, enum nmt_chan_type chan_type, const char *sounddev, int samplerate, int cross_channels, double rx_gain, int pre_emphasis, int de_emphasis, const char *write_wave, const char *read_wave, uint8_t ms_power, uint8_t traffic_area, uint8_t area_no, int compandor, int supervisory, const char *smsc_number, int loopback)
{
nmt_t *nmt;
int rc;
@@ -337,13 +340,20 @@ int nmt_create(int channel, enum nmt_chan_type chan_type, const char *sounddev,
goto error;
}
/* init audio processing */
/* init DMS processing */
rc = dms_init_sender(nmt);
if (rc < 0) {
PDEBUG(DNMT, DEBUG_ERROR, "Failed to init DMS processing!\n");
goto error;
}
/* init SMS processing */
rc = sms_init_sender(nmt);
if (rc < 0) {
PDEBUG(DNMT, DEBUG_ERROR, "Failed to init SMS processing!\n");
goto error;
}
timer_init(&nmt->timer, nmt_timeout, nmt);
nmt->sysinfo.chan_type = chan_type;
nmt->sysinfo.ms_power = ms_power;
@@ -351,6 +361,7 @@ int nmt_create(int channel, enum nmt_chan_type chan_type, const char *sounddev,
nmt->sysinfo.area_no = area_no;
nmt->compandor = compandor;
nmt->supervisory = supervisory;
strncpy(nmt->smsc_number, smsc_number, sizeof(nmt->smsc_number) - 1);
/* go into idle state */
nmt_go_idle(nmt);
@@ -371,6 +382,7 @@ void nmt_destroy(sender_t *sender)
PDEBUG(DNMT, DEBUG_DEBUG, "Destroying 'NMT' instance for channel = %d.\n", sender->kanal);
dsp_cleanup_sender(nmt);
dms_cleanup_sender(nmt);
sms_cleanup_sender(nmt);
timer_exit(&nmt->timer);
sender_destroy(&nmt->sender);
free(nmt);
@@ -382,6 +394,8 @@ static void nmt_go_idle(nmt_t *nmt)
timer_stop(&nmt->timer);
nmt->page_for_nmt = NULL;
nmt->dms_call = 0;
dms_reset(nmt);
sms_reset(nmt);
PDEBUG(DNMT, DEBUG_INFO, "Entering IDLE state, sending idle frames on %s.\n", chan_type_long_name(nmt->sysinfo.chan_type));
nmt_new_state(nmt, STATE_IDLE);
@@ -760,9 +774,9 @@ static void rx_mo_dialing(nmt_t *nmt, frame_t *frame)
break;
PDEBUG(DNMT, DEBUG_INFO, "Dialing complete %s->%s, call established.\n", &nmt->subscriber.country, nmt->dialing);
/* setup call */
if (!strcmp(nmt->dialing, "767")) {
if (!strcmp(nmt->dialing, nmt->smsc_number)) {
/* SMS */
dms_reset(nmt);
PDEBUG(DNMT, DEBUG_INFO, "Setup call to SMSC.\n");
nmt->dms_call = 1;
} else {
int callref = ++new_callref;
@@ -980,6 +994,10 @@ static void tx_mt_complete(nmt_t *nmt, frame_t *frame)
super_reset(nmt);
timer_start(&nmt->timer, SUPERVISORY_TO1);
}
if (nmt->dms_call) {
time_t ti = time(NULL);
sms_deliver(nmt, sms_ref, "", SMS_TYPE_UKNOWN, SMS_PLAN_ISDN_TEL, ti, nmt->sms_string);
}
}
}
@@ -1365,7 +1383,7 @@ const char *nmt_get_frame(nmt_t *nmt)
*/
/* Call control starts call towards mobile station. */
int call_out_setup(int callref, char *dialing)
int _out_setup(int callref, char *dialing, const char *sms)
{
sender_t *sender;
nmt_t *nmt;
@@ -1413,10 +1431,22 @@ inval:
/* 4. trying to page mobile station */
sender->callref = callref;
if (sms) {
strncpy(nmt->sms_string, sms, sizeof(nmt->sms_string) - 1);
nmt->dms_call = 1;
}
nmt_page(nmt, ms_country, ms_number, 1);
return 0;
}
int call_out_setup(int callref, char *dialing)
{
return _out_setup(callref, dialing, NULL);
}
int sms_out_setup(char *dialing, const char *sms)
{
return _out_setup(0, dialing, sms);
}
/* Call control sends disconnect (with tones).
* An active call stays active, so tones and annoucements can be received
@@ -1519,3 +1549,61 @@ void call_rx_audio(int callref, int16_t *samples, int count)
}
}
/*
* SMS layer messages
*/
/* SMS layer releases */
void sms_release(nmt_t *nmt)
{
PDEBUG(DNMT, DEBUG_NOTICE, "Outgoing release, by SMS layer!\n");
nmt_release(nmt);
}
void sms_submit(nmt_t *nmt, uint8_t ref, const char *orig_address, uint8_t orig_type, uint8_t orig_plan, int msg_ref, const char *dest_address, uint8_t dest_type, uint8_t dest_plan, const char *message)
{
PDEBUG(DNMT, DEBUG_NOTICE, "Received SMS from '%s' to '%s'\n", orig_address, dest_address);
printf("SMS received '%s' -> '%s': %s\n", orig_address, dest_address, message);
}
void sms_deliver_report(nmt_t *nmt, uint8_t ref, int error, uint8_t cause)
{
PDEBUG(DNMT, DEBUG_NOTICE, "Got SMS deliver report\n");
if (error)
printf("SMS failed! (cause=%d)\n", cause);
else {
sms_ref++;
printf("SMS sent!\n");
}
}
/* application sends ud a message, we need to deliver */
void deliver_sms(const char *sms)
{
int i, rc;
char number[8];
/* check for number digits */
for (i = 0; i < 7; i++) {
if (sms[i] < '0' || sms[i] > '9')
break;
}
if (i < 7 || sms[7] != ',') {
PDEBUG(DNMT, DEBUG_NOTICE, "Given SMS MUST start with the 7 digits phone number, followed by a comma (no spaces)\n");
return;
}
strncpy(number, sms, 7);
number[7] = '\0';
sms += 8;
PDEBUG(DNMT, DEBUG_INFO, "SMS for subscriber '%s'\n", number);
printf("SMS sending SMSC -> '%s': %s\n", number, sms);
rc = sms_out_setup(number, sms);
if (rc < 0) {
PDEBUG(DNMT, DEBUG_INFO, "SMS delivery failed with cause '%d'\n", -rc);
return;
}
}