#include "main.h"
#include "mncc.h"
-struct lcr_gsm *gsm_bs = NULL;
+struct lcr_gsm *gsm_bs_first = NULL;
#define PAYLOAD_TYPE_GSM 3
*/
Pgsm_bs::Pgsm_bs(int type, char *portname, struct port_settings *settings, struct interface *interface) : Pgsm(type, portname, settings, interface)
{
- p_g_lcr_gsm = gsm_bs;
+ struct lcr_gsm *gsm_bs = gsm_bs_first;
+
+ p_g_lcr_gsm = NULL;
+ SCPY(p_g_bs_name, interface->gsm_bs_name);
+
+ while (gsm_bs) {
+ if (gsm_bs->type == LCR_GSM_TYPE_NETWORK && !strcmp(gsm_bs->name, p_g_bs_name)) {
+ p_g_lcr_gsm = gsm_bs;
+ break;
+ }
+ gsm_bs = gsm_bs->gsm_next;
+ }
+
p_g_dtmf = NULL;
p_g_dtmf_index = 0;
- PDEBUG(DEBUG_GSM, "Created new GSMBSPort(%s).\n", portname);
+ PDEBUG(DEBUG_GSM, "Created new GSMBSPort(%s %s).\n", portname, p_g_bs_name);
}
/*
modify_lchan(media_types[0]);
p_g_payload_type = payload_types[0];
}
+
+ if (p_g_earlyb && !p_g_tch_connected) { /* only if ... */
+ struct gsm_mncc *frame;
+ gsm_trace_header(p_interface_name, this, MNCC_FRAME_RECV, DIRECTION_OUT);
+ end_trace();
+ frame = create_mncc(MNCC_FRAME_RECV, p_g_callref);
+ send_and_free_mncc(p_g_lcr_gsm, frame->msg_type, frame);
+ p_g_tch_connected = 1;
+ }
}
/* DTMF INDICATION */
decoder = p_g_amr_decoder;
half = 1;
break;
+ case 0x80:
+ add_trace("speech", "version", "Analog 8000Hz given");
+ media_type = MEDIA_TYPE_ANALOG;
+ payload_type = dynamic_type++;
+ encoder = (void *)1;
+ decoder = (void *)1;
+ break;
default:
add_trace("speech", "version", "%d given", mncc->bearer_cap.speech_ver[i]);
media_type = 0;
if (p_g_callref) {
/* release in case the ID is already in use */
add_trace("error", NULL, "callref already in use");
+reject:
end_trace();
mncc = create_mncc(MNCC_REJ_REQ, callref);
gsm_trace_header(p_interface_name, this, MNCC_REJ_REQ, DIRECTION_OUT);
trigger_work(&p_g_delete);
return;
}
+ if (callref < 0x40000000) {
+ /* release in case the ID is invalid */
+ add_trace("error", NULL, "callref invalid, not of BSC type");
+ goto reject;
+ }
p_g_callref = callref;
end_trace();
p_callerinfo.present = INFO_PRESENT_NOTAVAIL;
SCPY(p_callerinfo.imsi, mncc->imsi);
p_callerinfo.screen = INFO_SCREEN_NETWORK;
- p_callerinfo.ntype = INFO_NTYPE_UNKNOWN;
+ switch (mncc->calling.type) {
+ case 0x1:
+ p_callerinfo.ntype = INFO_NTYPE_INTERNATIONAL;
+ break;
+ case 0x2:
+ p_callerinfo.ntype = INFO_NTYPE_NATIONAL;
+ break;
+ case 0x4:
+ p_callerinfo.ntype = INFO_NTYPE_SUBSCRIBER;
+ break;
+ default:
+ p_callerinfo.ntype = INFO_NTYPE_UNKNOWN;
+ break;
+ }
SCPY(p_callerinfo.interface, p_interface_name);
/* dialing information */
gsm_trace_header(p_interface_name, this, msg_type, DIRECTION_IN);
if (p_callerinfo.id[0])
add_trace("calling", "number", "%s", p_callerinfo.id);
- else
+ else if (p_callerinfo.imsi[0])
SPRINT(p_callerinfo.id, "imsi-%s", p_callerinfo.imsi);
add_trace("calling", "imsi", "%s", p_callerinfo.imsi);
add_trace("dialing", "number", "%s", p_dialinginfo.id);
/*
* BSC sends message to port
*/
-int message_bsc(struct lcr_gsm *lcr_gsm, int msg_type, void *arg)
+int message_bsc(class Pgsm_bs *pgsm_bs, struct lcr_gsm *lcr_gsm, int msg_type, void *arg)
{
struct gsm_mncc *mncc = (struct gsm_mncc *)arg;
unsigned int callref = mncc->callref;
- class Port *port;
- class Pgsm_bs *pgsm_bs = NULL;
char name[64];
-// struct mISDNport *mISDNport;
/* Special messages */
switch(msg_type) {
}
- /* find callref */
- callref = mncc->callref;
- port = port_first;
- while(port) {
- if ((port->p_type & PORT_CLASS_GSM_MASK) == PORT_CLASS_GSM_BS) {
- pgsm_bs = (class Pgsm_bs *)port;
- if (pgsm_bs->p_g_callref == callref) {
- break;
- }
- }
- port = port->next;
- }
-
if (msg_type == GSM_TCHF_FRAME
|| msg_type == GSM_TCHF_FRAME_EFR
|| msg_type == GSM_TCHH_FRAME
|| msg_type == GSM_TCH_FRAME_AMR
+ || msg_type == ANALOG_8000HZ
|| msg_type == GSM_BAD_FRAME) {
- if (port) {
+ if (pgsm_bs) {
/* inject DTMF, if enabled */
if (pgsm_bs->p_g_dtmf) {
unsigned char data[160];
return 0;
}
- if (!port) {
+ if (!pgsm_bs) {
struct interface *interface;
if (msg_type != MNCC_SETUP_IND)
struct lcr_msg *message;
struct epoint_list *epointlist;
struct gsm_mncc *mncc;
+ struct interface *interface;
+
+ interface = getinterfacebyname(p_interface_name);
+ if (!interface) {
+ PERROR("Cannot find interface %s.\n", p_interface_name);
+ return;
+ }
/* copy setup infos to port */
memcpy(&p_callerinfo, ¶m->setup.callerinfo, sizeof(p_callerinfo));
add_trace("redir", "number", "%s", mncc->redirecting.number);
}
+ if (interface->gsm_bs_hr) {
+ add_trace("lchan", "type", "TCH/H or TCH/F");
+ mncc->lchan_type = GSM_LCHAN_TCH_H;
+ } else {
+ add_trace("lchan", "type", "TCH/F");
+ mncc->lchan_type = GSM_LCHAN_TCH_F;
+ }
+
end_trace();
send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
int gsm_bs_exit(int rc)
{
- /* free gsm instance */
- if (gsm_bs) {
- if (gsm_bs->mncc_lfd.fd > -1) {
- close(gsm_bs->mncc_lfd.fd);
- unregister_fd(&gsm_bs->mncc_lfd);
- }
-
- del_timer(&gsm_bs->socket_retry);
- free(gsm_bs);
- gsm_bs = NULL;
- }
+ /* destroy all instances */
+ while (gsm_bs_first)
+ gsm_bs_delete(gsm_bs_first->name);
+ return rc;
+}
- return(rc);
+int gsm_bs_init(void)
+{
+ return 0;
}
-int gsm_bs_init(struct interface *interface)
+/* add a new GSM base station instance */
+int gsm_bs_new(struct interface *interface)
{
+ struct lcr_gsm *gsm_bs = gsm_bs_first, **gsm_bs_p = &gsm_bs_first;
+
+ while (gsm_bs) {
+ gsm_bs_p = &gsm_bs->gsm_next;
+ gsm_bs = gsm_bs->gsm_next;
+ }
+
+ PDEBUG(DEBUG_GSM, "GSM: interface for BS '%s' is created\n", interface->gsm_bs_name);
+
/* create gsm instance */
gsm_bs = (struct lcr_gsm *)MALLOC(sizeof(struct lcr_gsm));
SCPY(gsm_bs->interface_name, interface->name);
gsm_bs->type = LCR_GSM_TYPE_NETWORK;
+ SCPY(gsm_bs->name, interface->gsm_bs_name);
gsm_bs->sun.sun_family = AF_UNIX;
- SCPY(gsm_bs->sun.sun_path, "/tmp/bsc_mncc");
+ if (gsm_bs->name[0])
+ SPRINT(gsm_bs->sun.sun_path, "/tmp/bsc_mncc_%s", gsm_bs->name);
+ else
+ SCPY(gsm_bs->sun.sun_path, "/tmp/bsc_mncc");
memset(&gsm_bs->socket_retry, 0, sizeof(gsm_bs->socket_retry));
add_timer(&gsm_bs->socket_retry, mncc_socket_retry_cb, gsm_bs, 0);
generate_dtmf();
+ *gsm_bs_p = gsm_bs;
+
return 0;
}
+
+int gsm_bs_delete(const char *name)
+{
+ struct lcr_gsm *gsm_bs = gsm_bs_first, **gsm_bs_p = &gsm_bs_first;
+
+ PDEBUG(DEBUG_GSM, "GSM: interface for BS '%s' is deleted\n", name);
+
+ while (gsm_bs) {
+ if (gsm_bs->type == LCR_GSM_TYPE_NETWORK && !strcmp(gsm_bs->name, name))
+ break;
+ gsm_bs_p = &gsm_bs->gsm_next;
+ gsm_bs = gsm_bs->gsm_next;
+ }
+
+ if (!gsm_bs)
+ return 0;
+
+ if (gsm_bs->mncc_lfd.fd > -1) {
+ close(gsm_bs->mncc_lfd.fd);
+ unregister_fd(&gsm_bs->mncc_lfd);
+ }
+ del_timer(&gsm_bs->socket_retry);
+
+ /* remove instance from list */
+ *gsm_bs_p = gsm_bs->gsm_next;
+ FREE(gsm_bs, sizeof(struct lcr_gsm));
+
+ return 0;
+}
+