\*****************************************************************************/
#include "main.h"
+#include "config.h"
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#include <osmocore/talloc.h>
#include <openbsc/mncc.h>
#include <openbsc/trau_frame.h>
+#include <openbsc/osmo_msc.h>
+//#include <osmocom/vty/command.h>
struct gsm_network *bsc_gsmnet = 0;
extern int ipacc_rtp_direct;
extern int bsc_bootstrap_network(int (*mmc_rev)(struct gsm_network *, int, void *),
int bts_model_bs11_init(void);
int bts_model_nanobts_init(void);
static struct log_target *stderr_target;
+extern const char *openbsc_copyright;
/* timer to store statistics */
#define DB_SYNC_INTERVAL 60, 0
static struct timer_list db_sync_timer;
+
+/* FIXME: copied from the include file, because it will con compile with C++ */
+struct vty_app_info {
+ const char *name;
+ const char *version;
+ const char *copyright;
+ void *tall_ctx;
+ int (*go_parent_cb)(struct vty *vty);
+ int (*is_config_node)(struct vty *vty, int node);
+};
+
+extern int bsc_vty_go_parent(struct vty *vty);
+extern int bsc_vty_is_config_node(struct vty *vty, int node);
+static struct vty_app_info vty_info = {
+ "OpenBSC",
+ PACKAGE_VERSION,
+ NULL,
+ NULL,
+ bsc_vty_go_parent,
+ bsc_vty_is_config_node,
+};
+
+void vty_init(struct vty_app_info *app_info);
+int bsc_vty_init(void);
+
}
/* timer handling */
}
/*
+ * DTMF stuff
+ */
+unsigned char dtmf_samples[16][8000];
+static int dtmf_x[4] = { 1209, 1336, 1477, 1633 };
+static int dtmf_y[4] = { 697, 770, 852, 941 };
+
+void generate_dtmf(void)
+{
+ double fx, fy, sample;
+ int i, x, y;
+ unsigned char *law;
+
+ for (y = 0; y < 4; y++) {
+ fy = 2 * 3.1415927 * ((double)dtmf_y[y]) / 8000.0;
+ for (x = 0; x < 4; x++) {
+ fx = 2 * 3.1415927 * ((double)dtmf_x[x]) / 8000.0;
+ law = dtmf_samples[y << 2 | x];
+ for (i = 0; i < 8000; i++) {
+ sample = sin(fy * ((double)i)) * 0.251 * 32767.0; /* -6 dB */
+ sample += sin(fx * ((double)i)) * 0.158 * 32767.0; /* -8 dB */
+ *law++ = audio_s16_to_law[(int)sample & 0xffff];
+ }
+ }
+ }
+}
+
+
+/*
* constructor
*/
Pgsm_bs::Pgsm_bs(int type, struct mISDNport *mISDNport, char *portname, struct port_settings *settings, int channel, int exclusive, int mode) : Pgsm(type, mISDNport, portname, settings, channel, exclusive, mode)
{
p_m_g_instance = gsm->network;
+ p_m_g_dtmf = NULL;
+ p_m_g_dtmf_index = 0;
+
PDEBUG(DEBUG_GSM, "Created new GSMBSPort(%s).\n", portname);
}
/* DTMF INDICATION */
void Pgsm_bs::start_dtmf_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
{
- struct lcr_msg *message;
+// struct lcr_msg *message;
struct gsm_mncc *resp;
gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
resp->keypad = mncc->keypad;
send_and_free_mncc(p_m_g_instance, resp->msg_type, resp);
+#if 0
/* send dialing information */
message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_INFORMATION);
memcpy(&message->param.information, &p_dialinginfo, sizeof(struct dialing_info));
message_put(message);
+#endif
+
+ /* generate DTMF tones */
+ switch (mncc->keypad) {
+ case '1': p_m_g_dtmf = dtmf_samples[0]; break;
+ case '2': p_m_g_dtmf = dtmf_samples[1]; break;
+ case '3': p_m_g_dtmf = dtmf_samples[2]; break;
+ case 'a':
+ case 'A': p_m_g_dtmf = dtmf_samples[3]; break;
+ case '4': p_m_g_dtmf = dtmf_samples[4]; break;
+ case '5': p_m_g_dtmf = dtmf_samples[5]; break;
+ case '6': p_m_g_dtmf = dtmf_samples[6]; break;
+ case 'b':
+ case 'B': p_m_g_dtmf = dtmf_samples[7]; break;
+ case '7': p_m_g_dtmf = dtmf_samples[8]; break;
+ case '8': p_m_g_dtmf = dtmf_samples[9]; break;
+ case '9': p_m_g_dtmf = dtmf_samples[10]; break;
+ case 'c':
+ case 'C': p_m_g_dtmf = dtmf_samples[11]; break;
+ case '*': p_m_g_dtmf = dtmf_samples[12]; break;
+ case '0': p_m_g_dtmf = dtmf_samples[13]; break;
+ case '#': p_m_g_dtmf = dtmf_samples[14]; break;
+ case 'd':
+ case 'D': p_m_g_dtmf = dtmf_samples[15]; break;
+ }
+ p_m_g_dtmf_index = 0;
}
void Pgsm_bs::stop_dtmf_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
{
resp = create_mncc(MNCC_STOP_DTMF_RSP, p_m_g_callref);
resp->keypad = mncc->keypad;
send_and_free_mncc(p_m_g_instance, resp->msg_type, resp);
+
+ /* stop DTMF */
+ p_m_g_dtmf = NULL;
}
/* HOLD INDICATION */
}
if (msg_type == GSM_TCHF_FRAME) {
- if (port)
- pgsm_bs->frame_receive((struct gsm_trau_frame *)arg);
+ if (port) {
+ /* inject DTMF, if enabled */
+ if (pgsm_bs->p_m_g_dtmf) {
+ unsigned char data[160];
+ int i;
+
+ for (i = 0; i < 160; i++) {
+ data[i] = pgsm_bs->p_m_g_dtmf[pgsm_bs->p_m_g_dtmf_index++];
+ if (pgsm_bs->p_m_g_dtmf_index == 8000)
+ pgsm_bs->p_m_g_dtmf_index = 0;
+ }
+ /* send */
+ pgsm_bs->bchannel_send(PH_DATA_REQ, 0, data, 160);
+ } else
+ pgsm_bs->frame_receive(arg);
+ }
return 0;
}
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
int pcapfd, rc;
+ vty_info.copyright = openbsc_copyright;
+
log_init(&log_info);
tall_bsc_ctx = talloc_named_const(NULL, 1, "openbsc");
talloc_ctx_init();
/* enable filters */
log_set_all_filter(stderr_target, 1);
+ /* Init VTY (need to preceed options) */
+ vty_init(&vty_info);
+ bsc_vty_init();
+
/* set debug */
if (gsm->conf.debug[0])
log_parse_category_mask(stderr_target, gsm->conf.debug);
/* use RTP proxy for audio streaming */
ipacc_rtp_direct = 0;
+ /* bootstrap network */
+ if (gsm->conf.openbsc_cfg[0] == '/')
+ SCPY(cfg, gsm->conf.openbsc_cfg);
+ else
+ SPRINT(cfg, "%s/%s", CONFIG_DATA, gsm->conf.openbsc_cfg);
+ rc = bsc_bootstrap_network(&message_bsc, cfg);
+ if (rc < 0) {
+ PERROR("Failed to bootstrap GSM network.\n");
+ return gsm_exit(-1);
+ }
+ bsc_api_init(bsc_gsmnet, msc_bsc_api());
+ gsm->network = bsc_gsmnet;
+
/* init database */
if (gsm->conf.hlr[0] == '/')
SCPY(hlr, gsm->conf.hlr);
db_sync_timer.data = NULL;
bsc_schedule_timer(&db_sync_timer, DB_SYNC_INTERVAL);
- /* bootstrap network */
- if (gsm->conf.openbsc_cfg[0] == '/')
- SCPY(cfg, gsm->conf.openbsc_cfg);
- else
- SPRINT(cfg, "%s/%s", CONFIG_DATA, gsm->conf.openbsc_cfg);
- rc = bsc_bootstrap_network(&message_bsc, cfg);
- if (rc < 0) {
- PERROR("Failed to bootstrap GSM network.\n");
- return gsm_exit(-1);
- }
- gsm->network = bsc_gsmnet;
+ generate_dtmf();
return 0;
}