X-Git-Url: http://git.eversberg.eu/gitweb.cgi?p=lcr.git;a=blobdiff_plain;f=gsm_bs.cpp;h=6d1a122661f36def6c30b97132c6e4506583a2a0;hp=4855a5c5edcbe577f37eb971c93529e9d47ddbbf;hb=d67fcefab05e9aa89e6e72a5f2aae10a5404c5e5;hpb=7f0d14c706328e1ff74fe8b8c16ae54407cc8055 diff --git a/gsm_bs.cpp b/gsm_bs.cpp index 4855a5c..6d1a122 100644 --- a/gsm_bs.cpp +++ b/gsm_bs.cpp @@ -103,11 +103,36 @@ void Pgsm_bs::call_conf_ind(unsigned int msg_type, unsigned int callref, struct /* get list of offered payload types * if list ist empty, the FR V1 is selected */ select_payload_type(mncc, payload_types, media_types, &payloads, sizeof(payload_types)); - /* if no given payload type is supported, we assume */ + /* if no given payload type is supported, we select from channel type */ if (!payloads) { - media_types[0] = MEDIA_TYPE_GSM; - payload_types[0] = PAYLOAD_TYPE_GSM; - payloads = 1; + switch (mncc->lchan_type) { + case GSM_LCHAN_TCH_F: + media_types[0] = MEDIA_TYPE_GSM; + payload_types[0] = PAYLOAD_TYPE_GSM; + payloads = 1; + break; + case GSM_LCHAN_TCH_H: + media_types[0] = MEDIA_TYPE_GSM_HR; + payload_types[0] = 96; /* dynamic */ + payloads = 1; + break; + default: + mncc = create_mncc(MNCC_REL_REQ, callref); + gsm_trace_header(p_interface_name, this, MNCC_REL_REQ, DIRECTION_OUT); + mncc->fields |= MNCC_F_CAUSE; + mncc->cause.coding = 3; + mncc->cause.location = 1; + mncc->cause.value = 65; + add_trace("cause", "coding", "%d", mncc->cause.coding); + add_trace("cause", "location", "%d", mncc->cause.location); + add_trace("cause", "value", "%d", mncc->cause.value); + add_trace("reason", NULL, "Given lchan not supported"); + end_trace(); + send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc); + new_state(PORT_STATE_RELEASE); + trigger_work(&p_g_delete); + return; + } } /* select first payload type that matches the rtp list */ @@ -317,6 +342,8 @@ void Pgsm_bs::select_payload_type(struct gsm_mncc *mncc, unsigned char *payload_ { int media_type; unsigned char payload_type; + int half; + void *encoder, *decoder; *payloads = 0; @@ -328,32 +355,52 @@ void Pgsm_bs::select_payload_type(struct gsm_mncc *mncc, unsigned char *payload_ add_trace("bearer", "capa", "given by MS"); for (i = 0; mncc->bearer_cap.speech_ver[i] >= 0; i++) { + half = 0; /* select payload type we support */ switch (mncc->bearer_cap.speech_ver[i]) { case 0: add_trace("speech", "version", "Full Rate given"); media_type = MEDIA_TYPE_GSM; payload_type = PAYLOAD_TYPE_GSM; + encoder = p_g_fr_encoder; + decoder = p_g_fr_decoder; break; case 2: add_trace("speech", "version", "EFR given"); media_type = MEDIA_TYPE_GSM_EFR; payload_type = dynamic_type++; + encoder = p_g_amr_encoder; + decoder = p_g_amr_decoder; break; case 4: add_trace("speech", "version", "AMR given"); media_type = MEDIA_TYPE_AMR; payload_type = dynamic_type++; + encoder = p_g_amr_encoder; + decoder = p_g_amr_decoder; break; case 1: add_trace("speech", "version", "Half Rate given"); media_type = MEDIA_TYPE_GSM_HR; payload_type = dynamic_type++; + encoder = p_g_hr_encoder; + decoder = p_g_hr_decoder; + half = 1; break; case 5: add_trace("speech", "version", "AMR Half Rate given"); media_type = MEDIA_TYPE_AMR; payload_type = dynamic_type++; + encoder = p_g_amr_encoder; + 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]); @@ -365,9 +412,17 @@ void Pgsm_bs::select_payload_type(struct gsm_mncc *mncc, unsigned char *payload_ add_trace("speech", "ignored", "Not supported by LCR"); continue; } + if (!half && mncc->lchan_type != GSM_LCHAN_TCH_F) { + add_trace("speech", "ignored", "Not TCH/F"); + continue; + } + if (half && mncc->lchan_type != GSM_LCHAN_TCH_H) { + add_trace("speech", "ignored", "Not TCH/H"); + continue; + } if (!p_g_rtp_bridge) { - if (media_type != MEDIA_TYPE_GSM) { - add_trace("speech", "ignored", "Not suitable for LCR"); + if (!encoder || !decoder) { + add_trace("speech", "ignored", "Codec not supported"); continue; } } @@ -415,6 +470,7 @@ void Pgsm_bs::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_ 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); @@ -432,6 +488,11 @@ void Pgsm_bs::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_ 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(); @@ -480,30 +541,40 @@ void Pgsm_bs::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_ /* get list of offered payload types * if list ist empty, the FR V1 is selected */ select_payload_type(mncc, payload_types, media_types, &payloads, sizeof(payload_types)); - /* if no given payload type is supported, we assume */ + /* if no given payload type is supported, we select from channel type */ if (!payloads) { - media_types[0] = MEDIA_TYPE_GSM; - payload_types[0] = PAYLOAD_TYPE_GSM; - payloads = 1; + switch (mncc->lchan_type) { + case GSM_LCHAN_TCH_F: + media_types[0] = MEDIA_TYPE_GSM; + payload_types[0] = PAYLOAD_TYPE_GSM; + payloads = 1; + break; + case GSM_LCHAN_TCH_H: + media_types[0] = MEDIA_TYPE_GSM_HR; + payload_types[0] = 96; /* dynamic */ + payloads = 1; + break; + default: + mncc = create_mncc(MNCC_REJ_REQ, callref); + gsm_trace_header(p_interface_name, this, MNCC_REJ_REQ, DIRECTION_OUT); + mncc->fields |= MNCC_F_CAUSE; + mncc->cause.coding = 3; + mncc->cause.location = 1; + mncc->cause.value = 65; + add_trace("cause", "coding", "%d", mncc->cause.coding); + add_trace("cause", "location", "%d", mncc->cause.location); + add_trace("cause", "value", "%d", mncc->cause.value); + add_trace("reason", NULL, "Given lchan not supported"); + end_trace(); + send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc); + new_state(PORT_STATE_RELEASE); + trigger_work(&p_g_delete); + return; + } } #if 0 /* if no given payload type is supported, we reject the call */ if (!payloads) { - mncc = create_mncc(MNCC_REJ_REQ, callref); - gsm_trace_header(p_interface_name, this, MNCC_REJ_REQ, DIRECTION_OUT); - mncc->fields |= MNCC_F_CAUSE; - mncc->cause.coding = 3; - mncc->cause.location = 1; - mncc->cause.value = 65; - add_trace("cause", "coding", "%d", mncc->cause.coding); - add_trace("cause", "location", "%d", mncc->cause.location); - add_trace("cause", "value", "%d", mncc->cause.value); - add_trace("reason", NULL, "Given speech codec(s) not supported"); - end_trace(); - send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc); - new_state(PORT_STATE_RELEASE); - trigger_work(&p_g_delete); - return; } #endif @@ -513,7 +584,7 @@ void Pgsm_bs::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_ 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); @@ -616,6 +687,10 @@ int message_bsc(struct lcr_gsm *lcr_gsm, int msg_type, void *arg) } 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) { /* inject DTMF, if enabled */ @@ -746,6 +821,13 @@ void Pgsm_bs::message_setup(unsigned int epoint_id, int message_id, union parame 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)); @@ -949,6 +1031,14 @@ void Pgsm_bs::message_setup(unsigned int epoint_id, int message_id, union parame 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);