1 /*****************************************************************************\
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg **
8 ** mISDN gsm (BS mode) **
10 \*****************************************************************************/
15 struct lcr_gsm *gsm_bs = NULL;
17 #define PAYLOAD_TYPE_GSM 3
22 unsigned char dtmf_samples[16][8000];
23 static int dtmf_x[4] = { 1209, 1336, 1477, 1633 };
24 static int dtmf_y[4] = { 697, 770, 852, 941 };
26 void generate_dtmf(void)
28 double fx, fy, sample;
32 for (y = 0; y < 4; y++) {
33 fy = 2 * 3.1415927 * ((double)dtmf_y[y]) / 8000.0;
34 for (x = 0; x < 4; x++) {
35 fx = 2 * 3.1415927 * ((double)dtmf_x[x]) / 8000.0;
36 law = dtmf_samples[y << 2 | x];
37 for (i = 0; i < 8000; i++) {
38 sample = sin(fy * ((double)i)) * 0.251 * 32767.0; /* -6 dB */
39 sample += sin(fx * ((double)i)) * 0.158 * 32767.0; /* -8 dB */
40 *law++ = audio_s16_to_law[(int)sample & 0xffff];
50 Pgsm_bs::Pgsm_bs(int type, char *portname, struct port_settings *settings, struct interface *interface) : Pgsm(type, portname, settings, interface)
56 PDEBUG(DEBUG_GSM, "Created new GSMBSPort(%s).\n", portname);
64 PDEBUG(DEBUG_GSM, "Destroyed GSM BS process(%s).\n", p_name);
67 static const char *media_type2name(unsigned char media_type) {
75 case MEDIA_TYPE_GSM_HR:
77 case MEDIA_TYPE_GSM_EFR:
86 /* PROCEEDING INDICATION (from MS) */
87 void Pgsm_bs::call_conf_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
90 unsigned char payload_types[8];
93 gsm_trace_header(p_interface_name, this, msg_type, DIRECTION_IN);
94 if (mncc->fields & MNCC_F_CAUSE) {
95 add_trace("cause", "coding", "%d", mncc->cause.coding);
96 add_trace("cause", "location", "%", mncc->cause.location);
97 add_trace("cause", "value", "%", mncc->cause.value);
101 new_state(PORT_STATE_OUT_PROCEEDING);
103 /* get list of offered payload types */
104 select_payload_type(mncc, payload_types, media_types, &payloads, sizeof(payload_types));
105 /* if no given payload type is supported, we must release */
107 mncc = create_mncc(MNCC_REL_REQ, callref);
108 gsm_trace_header(p_interface_name, this, MNCC_REL_REQ, DIRECTION_OUT);
109 mncc->fields |= MNCC_F_CAUSE;
110 mncc->cause.coding = 3;
111 mncc->cause.location = 1;
112 mncc->cause.value = 65;
113 add_trace("cause", "coding", "%d", mncc->cause.coding);
114 add_trace("cause", "location", "%d", mncc->cause.location);
115 add_trace("cause", "value", "%d", mncc->cause.value);
116 add_trace("reason", NULL, "Given lchan not supported");
118 send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
119 new_state(PORT_STATE_RELEASE);
120 trigger_work(&p_g_delete);
124 /* select first payload type that matches the rtp list */
125 if (p_g_rtp_bridge) {
128 for (i = 0; i < p_g_rtp_payloads; i++) {
129 for (j = 0; j < payloads; j++) {
130 if (p_g_rtp_media_types[i] == media_types[j])
136 if (i == p_g_rtp_payloads) {
137 struct lcr_msg *message;
139 /* payload offered by remote RTP is not supported */
140 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_RELEASE);
141 message->param.disconnectinfo.cause = 65;
142 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
143 message_put(message);
145 mncc = create_mncc(MNCC_REL_REQ, p_g_callref);
146 gsm_trace_header(p_interface_name, this, MNCC_REL_REQ, DIRECTION_OUT);
147 mncc->fields |= MNCC_F_CAUSE;
148 mncc->cause.coding = 3;
149 mncc->cause.location = LOCATION_PRIVATE_LOCAL;
150 mncc->cause.value = 65;
151 add_trace("cause", "coding", "%d", mncc->cause.coding);
152 add_trace("cause", "location", "%d", mncc->cause.location);
153 add_trace("cause", "value", "%d", mncc->cause.value);
154 add_trace("reason", NULL, "None of the payload types are supported by MS");
156 send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
157 new_state(PORT_STATE_RELEASE);
158 trigger_work(&p_g_delete);
162 modify_lchan(p_g_rtp_media_types[i]);
163 /* use the payload type from received rtp list, not from locally generated payload types */
164 p_g_payload_type = p_g_rtp_payload_types[i];
166 /* modify to first given payload */
167 modify_lchan(media_types[0]);
168 p_g_payload_type = payload_types[0];
172 /* DTMF INDICATION */
173 void Pgsm_bs::start_dtmf_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
175 struct gsm_mncc *resp;
177 gsm_trace_header(p_interface_name, this, msg_type, DIRECTION_IN);
178 add_trace("keypad", NULL, "%c", mncc->keypad);
180 SPRINT(p_dialinginfo.id, "%c", mncc->keypad);
181 p_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
184 gsm_trace_header(p_interface_name, this, MNCC_START_DTMF_RSP, DIRECTION_OUT);
185 add_trace("keypad", NULL, "%c", mncc->keypad);
187 resp = create_mncc(MNCC_START_DTMF_RSP, p_g_callref);
188 resp->fields |= MNCC_F_KEYPAD;
189 resp->keypad = mncc->keypad;
190 send_and_free_mncc(p_g_lcr_gsm, resp->msg_type, resp);
192 if (p_g_rtp_bridge) {
193 /* if two members are bridged */
194 if (p_bridge && p_bridge->first && p_bridge->first->next && !p_bridge->first->next->next) {
195 class Port *remote = NULL;
197 /* select other member */
198 if (p_bridge->first->port == this)
199 remote = p_bridge->first->next->port;
200 if (p_bridge->first->next->port == this)
201 remote = p_bridge->first->port;
204 struct lcr_msg *message;
206 /* send dtmf information, because we bridge RTP directly */
207 message = message_create(0, remote->p_serial, EPOINT_TO_PORT, MESSAGE_DTMF);
208 message->param.dtmf = mncc->keypad;
209 message_put(message);
213 /* generate DTMF tones, since we do audio forwarding inside LCR */
214 switch (mncc->keypad) {
215 case '1': p_g_dtmf = dtmf_samples[0]; break;
216 case '2': p_g_dtmf = dtmf_samples[1]; break;
217 case '3': p_g_dtmf = dtmf_samples[2]; break;
219 case 'A': p_g_dtmf = dtmf_samples[3]; break;
220 case '4': p_g_dtmf = dtmf_samples[4]; break;
221 case '5': p_g_dtmf = dtmf_samples[5]; break;
222 case '6': p_g_dtmf = dtmf_samples[6]; break;
224 case 'B': p_g_dtmf = dtmf_samples[7]; break;
225 case '7': p_g_dtmf = dtmf_samples[8]; break;
226 case '8': p_g_dtmf = dtmf_samples[9]; break;
227 case '9': p_g_dtmf = dtmf_samples[10]; break;
229 case 'C': p_g_dtmf = dtmf_samples[11]; break;
230 case '*': p_g_dtmf = dtmf_samples[12]; break;
231 case '0': p_g_dtmf = dtmf_samples[13]; break;
232 case '#': p_g_dtmf = dtmf_samples[14]; break;
234 case 'D': p_g_dtmf = dtmf_samples[15]; break;
239 void Pgsm_bs::stop_dtmf_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
241 struct gsm_mncc *resp;
243 gsm_trace_header(p_interface_name, this, msg_type, DIRECTION_IN);
244 add_trace("keypad", NULL, "%c", mncc->keypad);
248 gsm_trace_header(p_interface_name, this, MNCC_STOP_DTMF_RSP, DIRECTION_OUT);
249 add_trace("keypad", NULL, "%c", mncc->keypad);
251 resp = create_mncc(MNCC_STOP_DTMF_RSP, p_g_callref);
252 resp->keypad = mncc->keypad;
253 send_and_free_mncc(p_g_lcr_gsm, resp->msg_type, resp);
259 /* HOLD INDICATION */
260 void Pgsm_bs::hold_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
262 struct lcr_msg *message;
263 struct gsm_mncc *resp, *frame;
265 gsm_trace_header(p_interface_name, this, msg_type, DIRECTION_IN);
268 /* notify the hold of call */
269 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_NOTIFY);
270 message->param.notifyinfo.notify = INFO_NOTIFY_REMOTE_HOLD;
271 message->param.notifyinfo.local = 1; /* call is held by supplementary service */
272 message_put(message);
274 /* acknowledge hold */
275 gsm_trace_header(p_interface_name, this, MNCC_HOLD_CNF, DIRECTION_OUT);
277 resp = create_mncc(MNCC_HOLD_CNF, p_g_callref);
278 send_and_free_mncc(p_g_lcr_gsm, resp->msg_type, resp);
281 if (p_g_tch_connected) { /* it should be true */
282 gsm_trace_header(p_interface_name, this, MNCC_FRAME_DROP, DIRECTION_OUT);
284 frame = create_mncc(MNCC_FRAME_DROP, p_g_callref);
285 send_and_free_mncc(p_g_lcr_gsm, frame->msg_type, frame);
286 p_g_tch_connected = 0;
291 /* RETRIEVE INDICATION */
292 void Pgsm_bs::retr_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
294 struct lcr_msg *message;
295 struct gsm_mncc *resp, *frame;
297 gsm_trace_header(p_interface_name, this, msg_type, DIRECTION_IN);
300 /* notify the retrieve of call */
301 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_NOTIFY);
302 message->param.notifyinfo.notify = INFO_NOTIFY_REMOTE_RETRIEVAL;
303 message->param.notifyinfo.local = 1; /* call is retrieved by supplementary service */
304 message_put(message);
306 /* acknowledge retr */
307 gsm_trace_header(p_interface_name, this, MNCC_RETRIEVE_CNF, DIRECTION_OUT);
309 resp = create_mncc(MNCC_RETRIEVE_CNF, p_g_callref);
310 send_and_free_mncc(p_g_lcr_gsm, resp->msg_type, resp);
313 if (!p_g_tch_connected) { /* it should be true */
314 gsm_trace_header(p_interface_name, this, MNCC_FRAME_RECV, DIRECTION_OUT);
316 frame = create_mncc(MNCC_FRAME_RECV, p_g_callref);
317 send_and_free_mncc(p_g_lcr_gsm, frame->msg_type, frame);
318 p_g_tch_connected = 1;
323 * select payload type by given list or GSM V1 FR
324 * return the payload type or 0 if not given
327 void Pgsm_bs::select_payload_type(struct gsm_mncc *mncc, unsigned char *payload_types, int *media_types, int *payloads, int max_payloads)
330 unsigned char payload_type;
331 void *encoder, *decoder;
335 gsm_trace_header(p_interface_name, this, 1 /* codec negotioation */, DIRECTION_NONE);
336 if ((mncc->fields & MNCC_F_BEARER_CAP)) {
337 /* select preferred payload type from list */
339 unsigned char dynamic_type = 96;
341 add_trace("bearer", "capa", "given by MS");
342 for (i = 0; mncc->bearer_cap.speech_ver[i] >= 0; i++) {
343 /* select payload type we support */
344 switch (mncc->bearer_cap.speech_ver[i]) {
346 add_trace("speech", "version", "Full Rate given");
347 media_type = MEDIA_TYPE_GSM;
348 payload_type = PAYLOAD_TYPE_GSM;
349 encoder = p_g_fr_encoder;
350 decoder = p_g_fr_decoder;
353 add_trace("speech", "version", "EFR given");
354 media_type = MEDIA_TYPE_GSM_EFR;
355 payload_type = dynamic_type++;
356 encoder = p_g_amr_encoder;
357 decoder = p_g_amr_decoder;
360 add_trace("speech", "version", "AMR given");
361 media_type = MEDIA_TYPE_AMR;
362 payload_type = dynamic_type++;
363 encoder = p_g_amr_encoder;
364 decoder = p_g_amr_decoder;
367 add_trace("speech", "version", "Half Rate given");
368 media_type = MEDIA_TYPE_GSM_HR;
369 payload_type = dynamic_type++;
370 encoder = p_g_hr_encoder;
371 decoder = p_g_hr_decoder;
374 add_trace("speech", "version", "AMR Half Rate given");
375 media_type = MEDIA_TYPE_AMR;
376 payload_type = dynamic_type++;
377 encoder = p_g_amr_encoder;
378 decoder = p_g_amr_decoder;
381 add_trace("speech", "version", "%d given", mncc->bearer_cap.speech_ver[i]);
385 /* wen don't support it, so we check the next */
387 add_trace("speech", "ignored", "Not supported by LCR");
390 if (!p_g_rtp_bridge) {
391 if (!encoder || !decoder) {
392 add_trace("speech", "ignored", "Codec not supported");
396 if (*payloads <= max_payloads) {
397 media_types[*payloads] = media_type;
398 payload_types[*payloads] = payload_type;
403 add_trace("bearer", "capa", "not given by MS");
404 add_trace("speech", "version", "Full Rate given");
405 media_types[0] = MEDIA_TYPE_GSM;
406 payload_types[0] = PAYLOAD_TYPE_GSM;
410 add_trace("error", "", "All given payload types unsupported");
415 * handles all indications
417 /* SETUP INDICATION */
418 void Pgsm_bs::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
420 class Endpoint *epoint;
421 struct lcr_msg *message;
422 struct gsm_mncc *proceeding, *frame;
423 struct interface *interface;
425 unsigned char payload_types[8];
428 interface = getinterfacebyname(p_interface_name);
430 PERROR("Cannot find interface %s.\n", p_interface_name);
434 /* process given callref */
435 gsm_trace_header(p_interface_name, this, 0, DIRECTION_IN);
436 add_trace("callref", "new", "0x%x", callref);
438 /* release in case the ID is already in use */
439 add_trace("error", NULL, "callref already in use");
441 mncc = create_mncc(MNCC_REJ_REQ, callref);
442 gsm_trace_header(p_interface_name, this, MNCC_REJ_REQ, DIRECTION_OUT);
443 mncc->fields |= MNCC_F_CAUSE;
444 mncc->cause.coding = 3;
445 mncc->cause.location = 1;
446 mncc->cause.value = 47;
447 add_trace("cause", "coding", "%d", mncc->cause.coding);
448 add_trace("cause", "location", "%d", mncc->cause.location);
449 add_trace("cause", "value", "%d", mncc->cause.value);
450 add_trace("reason", NULL, "callref already in use");
452 send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
453 new_state(PORT_STATE_RELEASE);
454 trigger_work(&p_g_delete);
457 p_g_callref = callref;
462 p_callerinfo.present = INFO_PRESENT_RESTRICTED;
464 p_callerinfo.present = INFO_PRESENT_ALLOWED;
465 if (mncc->calling.number[0])
466 SCPY(p_callerinfo.id, mncc->calling.number);
468 p_callerinfo.present = INFO_PRESENT_NOTAVAIL;
469 SCPY(p_callerinfo.imsi, mncc->imsi);
470 p_callerinfo.screen = INFO_SCREEN_NETWORK;
471 p_callerinfo.ntype = INFO_NTYPE_UNKNOWN;
472 SCPY(p_callerinfo.interface, p_interface_name);
474 /* dialing information */
475 SCAT(p_dialinginfo.id, mncc->called.number);
476 switch (mncc->called.type) {
478 p_dialinginfo.ntype = INFO_NTYPE_INTERNATIONAL;
481 p_dialinginfo.ntype = INFO_NTYPE_NATIONAL;
484 p_dialinginfo.ntype = INFO_NTYPE_SUBSCRIBER;
487 p_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
490 if (mncc->emergency) {
491 SCPY(p_dialinginfo.id, "emergency");
493 p_dialinginfo.sending_complete = 1;
495 /* bearer capability */
496 p_capainfo.bearer_capa = INFO_BC_SPEECH;
497 p_capainfo.bearer_info1 = (options.law=='a')?3:2;
498 p_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
499 p_capainfo.source_mode = B_MODE_TRANSPARENT;
500 p_g_mode = p_capainfo.source_mode;
502 /* get list of offered payload types */
503 select_payload_type(mncc, payload_types, media_types, &payloads, sizeof(payload_types));
504 /* if no given payload type is supported, we must release */
506 mncc = create_mncc(MNCC_REJ_REQ, callref);
507 gsm_trace_header(p_interface_name, this, MNCC_REJ_REQ, DIRECTION_OUT);
508 mncc->fields |= MNCC_F_CAUSE;
509 mncc->cause.coding = 3;
510 mncc->cause.location = 1;
511 mncc->cause.value = 65;
512 add_trace("cause", "coding", "%d", mncc->cause.coding);
513 add_trace("cause", "location", "%d", mncc->cause.location);
514 add_trace("cause", "value", "%d", mncc->cause.value);
515 add_trace("reason", NULL, "Given lchan not supported");
517 send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
518 new_state(PORT_STATE_RELEASE);
519 trigger_work(&p_g_delete);
523 /* if no given payload type is supported, we reject the call */
530 /* what infos did we got ... */
531 gsm_trace_header(p_interface_name, this, msg_type, DIRECTION_IN);
532 if (p_callerinfo.id[0])
533 add_trace("calling", "number", "%s", p_callerinfo.id);
535 SPRINT(p_callerinfo.id, "imsi-%s", p_callerinfo.imsi);
536 add_trace("calling", "imsi", "%s", p_callerinfo.imsi);
537 add_trace("dialing", "number", "%s", p_dialinginfo.id);
540 /* create endpoint */
542 FATAL("Incoming call but already got an endpoint.\n");
543 if (!(epoint = new Endpoint(p_serial, 0)))
544 FATAL("No memory for Endpoint instance\n");
545 epoint->ep_app = new_endpointapp(epoint, 0, interface->app); //incoming
546 epointlist_new(epoint->ep_serial);
548 /* modify lchan in case of no rtp bridge */
550 modify_lchan(media_types[0]);
552 /* send call proceeding */
553 gsm_trace_header(p_interface_name, this, MNCC_CALL_PROC_REQ, DIRECTION_OUT);
554 proceeding = create_mncc(MNCC_CALL_PROC_REQ, p_g_callref);
556 proceeding->fields |= MNCC_F_PROGRESS;
557 proceeding->progress.coding = 3; /* GSM */
558 proceeding->progress.location = 1;
559 proceeding->progress.descr = 8;
560 add_trace("progress", "coding", "%d", proceeding->progress.coding);
561 add_trace("progress", "location", "%d", proceeding->progress.location);
562 add_trace("progress", "descr", "%d", proceeding->progress.descr);
565 send_and_free_mncc(p_g_lcr_gsm, proceeding->msg_type, proceeding);
567 new_state(PORT_STATE_IN_PROCEEDING);
569 if (p_g_tones && !p_g_tch_connected) { /* only if ... */
570 gsm_trace_header(p_interface_name, this, MNCC_FRAME_RECV, DIRECTION_OUT);
572 frame = create_mncc(MNCC_FRAME_RECV, p_g_callref);
573 send_and_free_mncc(p_g_lcr_gsm, frame->msg_type, frame);
574 p_g_tch_connected = 1;
577 /* send setup message to endpoit */
578 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_SETUP);
579 message->param.setup.port_type = p_type;
580 // message->param.setup.dtmf = 0;
581 memcpy(&message->param.setup.dialinginfo, &p_dialinginfo, sizeof(struct dialing_info));
582 memcpy(&message->param.setup.callerinfo, &p_callerinfo, sizeof(struct caller_info));
583 memcpy(&message->param.setup.capainfo, &p_capainfo, sizeof(struct capa_info));
584 SCPY((char *)message->param.setup.useruser.data, (char *)mncc->useruser.info);
585 message->param.setup.useruser.len = strlen(mncc->useruser.info);
586 message->param.setup.useruser.protocol = mncc->useruser.proto;
587 if (p_g_rtp_bridge) {
588 struct gsm_mncc_rtp *rtp;
591 PDEBUG(DEBUG_GSM, "Request RTP peer info, before forwarding setup\n");
592 p_g_setup_pending = message;
593 rtp = (struct gsm_mncc_rtp *) create_mncc(MNCC_RTP_CREATE, p_g_callref);
594 send_and_free_mncc(p_g_lcr_gsm, rtp->msg_type, rtp);
596 for (i = 0; i < (int)sizeof(message->param.setup.rtpinfo.payload_types) && i < payloads; i++) {
597 message->param.setup.rtpinfo.media_types[i] = media_types[i];
598 message->param.setup.rtpinfo.payload_types[i] = payload_types[i];
599 message->param.setup.rtpinfo.payloads++;
603 message_put(message);
608 * BSC sends message to port
610 int message_bsc(struct lcr_gsm *lcr_gsm, int msg_type, void *arg)
612 struct gsm_mncc *mncc = (struct gsm_mncc *)arg;
613 unsigned int callref = mncc->callref;
615 class Pgsm_bs *pgsm_bs = NULL;
617 // struct mISDNport *mISDNport;
619 /* Special messages */
624 callref = mncc->callref;
627 if ((port->p_type & PORT_CLASS_GSM_MASK) == PORT_CLASS_GSM_BS) {
628 pgsm_bs = (class Pgsm_bs *)port;
629 if (pgsm_bs->p_g_callref == callref) {
636 if (msg_type == GSM_TCHF_FRAME
637 || msg_type == GSM_TCHF_FRAME_EFR
638 || msg_type == GSM_TCHH_FRAME
639 || msg_type == GSM_TCH_FRAME_AMR
640 || msg_type == GSM_BAD_FRAME) {
642 /* inject DTMF, if enabled */
643 if (pgsm_bs->p_g_dtmf) {
644 unsigned char data[160];
647 for (i = 0; i < 160; i++) {
648 data[i] = pgsm_bs->p_g_dtmf[pgsm_bs->p_g_dtmf_index++];
649 if (pgsm_bs->p_g_dtmf_index == 8000)
650 pgsm_bs->p_g_dtmf_index = 0;
653 pgsm_bs->bridge_tx(data, 160);
655 pgsm_bs->frame_receive(arg);
656 /* if we do not bridge we need to inject audio, if available */
657 if (!pgsm_bs->p_bridge || pgsm_bs->p_tone_name[0]) {
658 unsigned char data[160];
661 i = pgsm_bs->read_audio(data, 160);
663 pgsm_bs->audio_send(data, i);
670 struct interface *interface;
672 if (msg_type != MNCC_SETUP_IND)
675 interface = getinterfacebyname(lcr_gsm->interface_name);
677 struct gsm_mncc *rej;
679 rej = create_mncc(MNCC_REJ_REQ, callref);
680 rej->fields |= MNCC_F_CAUSE;
681 rej->cause.coding = 3;
682 rej->cause.location = 1;
683 rej->cause.value = 27;
684 gsm_trace_header(NULL, NULL, MNCC_REJ_REQ, DIRECTION_OUT);
685 add_trace("cause", "coding", "%d", rej->cause.coding);
686 add_trace("cause", "location", "%d", rej->cause.location);
687 add_trace("cause", "value", "%d", rej->cause.value);
688 add_trace("reason", NULL, "interface %s not found", lcr_gsm->interface_name);
690 send_and_free_mncc(lcr_gsm, rej->msg_type, rej);
693 /* creating port object, transparent until setup with hdlc */
694 SPRINT(name, "%s-%d-in", interface->name, 0);
695 if (!(pgsm_bs = new Pgsm_bs(PORT_TYPE_GSM_BS_IN, name, NULL, interface)))
696 FATAL("Cannot create Port instance.\n");
701 pgsm_bs->setup_ind(msg_type, callref, mncc);
704 case MNCC_RTP_CREATE:
705 pgsm_bs->rtp_create_ind(msg_type, callref, mncc);
708 case MNCC_RTP_CONNECT:
709 pgsm_bs->rtp_connect_ind(msg_type, callref, mncc);
712 case MNCC_START_DTMF_IND:
713 pgsm_bs->start_dtmf_ind(msg_type, callref, mncc);
716 case MNCC_STOP_DTMF_IND:
717 pgsm_bs->stop_dtmf_ind(msg_type, callref, mncc);
720 case MNCC_CALL_CONF_IND:
721 pgsm_bs->call_conf_ind(msg_type, callref, mncc);
725 pgsm_bs->alert_ind(msg_type, callref, mncc);
729 pgsm_bs->setup_cnf(msg_type, callref, mncc);
732 case MNCC_SETUP_COMPL_IND:
733 pgsm_bs->setup_compl_ind(msg_type, callref, mncc);
737 pgsm_bs->disc_ind(msg_type, callref, mncc);
743 pgsm_bs->rel_ind(msg_type, callref, mncc);
746 case MNCC_NOTIFY_IND:
747 pgsm_bs->notify_ind(msg_type, callref, mncc);
751 pgsm_bs->hold_ind(msg_type, callref, mncc);
754 case MNCC_RETRIEVE_IND:
755 pgsm_bs->retr_ind(msg_type, callref, mncc);
759 PDEBUG(DEBUG_GSM, "Pgsm_bs(%s) gsm port with (caller id %s) received unhandled nessage: 0x%x\n", pgsm_bs->p_name, pgsm_bs->p_callerinfo.id, msg_type);
765 void Pgsm_bs::message_setup(unsigned int epoint_id, int message_id, union parameter *param)
767 struct lcr_msg *message;
768 struct epoint_list *epointlist;
769 struct gsm_mncc *mncc;
770 struct interface *interface;
771 int page_with_tchh = 0;
773 interface = getinterfacebyname(p_interface_name);
775 PERROR("Cannot find interface %s.\n", p_interface_name);
779 /* copy setup infos to port */
780 memcpy(&p_callerinfo, ¶m->setup.callerinfo, sizeof(p_callerinfo));
781 memcpy(&p_dialinginfo, ¶m->setup.dialinginfo, sizeof(p_dialinginfo));
782 memcpy(&p_capainfo, ¶m->setup.capainfo, sizeof(p_capainfo));
783 memcpy(&p_redirinfo, ¶m->setup.redirinfo, sizeof(p_redirinfo));
785 /* no GSM MNCC connection */
786 if (p_g_lcr_gsm->mncc_lfd.fd < 0) {
787 gsm_trace_header(p_interface_name, this, MNCC_SETUP_REQ, DIRECTION_OUT);
788 add_trace("failure", NULL, "No MNCC connection.");
790 message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
791 message->param.disconnectinfo.cause = 41; // temp. failure.
792 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
793 message_put(message);
794 new_state(PORT_STATE_RELEASE);
795 trigger_work(&p_g_delete);
800 if (!p_dialinginfo.id[0]) {
801 gsm_trace_header(p_interface_name, this, MNCC_SETUP_REQ, DIRECTION_OUT);
802 add_trace("failure", NULL, "No dialed subscriber given.");
804 message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
805 message->param.disconnectinfo.cause = 28;
806 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
807 message_put(message);
808 new_state(PORT_STATE_RELEASE);
809 trigger_work(&p_g_delete);
813 /* unsupported codec for RTP bridge */
814 if (param->setup.rtpinfo.port) {
817 p_g_rtp_payloads = 0;
818 gsm_trace_header(p_interface_name, this, 1 /* codec negotioation */, DIRECTION_NONE);
819 for (i = 0; i < param->setup.rtpinfo.payloads; i++) {
820 switch (param->setup.rtpinfo.media_types[i]) {
822 case MEDIA_TYPE_GSM_HR:
823 /* because offered codecs are compatible with half rate, we can page with tchh */
827 case MEDIA_TYPE_GSM_EFR:
828 add_trace("rtp", "payload", "%s:%d supported", media_type2name(param->setup.rtpinfo.media_types[i]), param->setup.rtpinfo.payload_types[i]);
829 if (p_g_rtp_payloads < (int)sizeof(p_g_rtp_payload_types)) {
830 p_g_rtp_media_types[p_g_rtp_payloads] = param->setup.rtpinfo.media_types[i];
831 p_g_rtp_payload_types[p_g_rtp_payloads] = param->setup.rtpinfo.payload_types[i];
836 add_trace("rtp", "payload", "%s:%d unsupported", media_type2name(param->setup.rtpinfo.media_types[i]), param->setup.rtpinfo.payload_types[i]);
840 if (!p_g_rtp_payloads) {
841 gsm_trace_header(p_interface_name, this, MNCC_SETUP_REQ, DIRECTION_OUT);
842 add_trace("failure", NULL, "No payload given that is supported by GSM");
844 message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
845 message->param.disconnectinfo.cause = 65;
846 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
847 message_put(message);
848 new_state(PORT_STATE_RELEASE);
849 trigger_work(&p_g_delete);
853 /* since we support half rate compatible codecss, we can page with tchh */
854 if (p_g_hr_encoder || p_g_amr_encoder)
858 // SCPY(&p_m_tones_dir, param->setup.ext.tones_dir);
859 /* screen outgoing caller id */
860 do_screen(1, p_callerinfo.id, sizeof(p_callerinfo.id), &p_callerinfo.ntype, &p_callerinfo.present, p_interface_name);
862 /* attach only if not already */
863 epointlist = p_epointlist;
865 if (epointlist->epoint_id == epoint_id)
867 epointlist = epointlist->next;
870 epointlist_new(epoint_id);
873 gsm_trace_header(p_interface_name, this, 0, DIRECTION_OUT);
874 p_g_callref = new_callref++;
875 add_trace("callref", "new", "0x%x", p_g_callref);
878 gsm_trace_header(p_interface_name, this, MNCC_SETUP_REQ, DIRECTION_OUT);
879 mncc = create_mncc(MNCC_SETUP_REQ, p_g_callref);
880 /* caller information */
881 mncc->fields |= MNCC_F_CALLING;
882 mncc->calling.plan = 1;
883 switch (p_callerinfo.ntype) {
884 case INFO_NTYPE_UNKNOWN:
885 mncc->calling.type = 0x0;
887 case INFO_NTYPE_INTERNATIONAL:
888 mncc->calling.type = 0x1;
890 case INFO_NTYPE_NATIONAL:
891 mncc->calling.type = 0x2;
893 case INFO_NTYPE_SUBSCRIBER:
894 mncc->calling.type = 0x4;
896 default: /* INFO_NTYPE_NOTPRESENT */
897 mncc->fields &= ~MNCC_F_CALLING;
900 switch (p_callerinfo.screen) {
901 case INFO_SCREEN_USER:
902 mncc->calling.screen = 0;
904 default: /* INFO_SCREEN_NETWORK */
905 mncc->calling.screen = 3;
908 switch (p_callerinfo.present) {
909 case INFO_PRESENT_ALLOWED:
910 mncc->calling.present = 0;
912 case INFO_PRESENT_RESTRICTED:
913 mncc->calling.present = 1;
915 default: /* INFO_PRESENT_NOTAVAIL */
916 mncc->calling.present = 2;
919 if (mncc->fields & MNCC_F_CALLING) {
920 SCPY(mncc->calling.number, p_callerinfo.id);
921 add_trace("calling", "type", "%d", mncc->calling.type);
922 add_trace("calling", "plan", "%d", mncc->calling.plan);
923 add_trace("calling", "present", "%d", mncc->calling.present);
924 add_trace("calling", "screen", "%d", mncc->calling.screen);
925 add_trace("calling", "number", "%s", mncc->calling.number);
927 /* dialing information */
928 mncc->fields |= MNCC_F_CALLED;
929 if (!strncmp(p_dialinginfo.id, "imsi-", 5)) {
930 SCPY(mncc->imsi, p_dialinginfo.id+5);
931 add_trace("dialing", "imsi", "%s", mncc->imsi);
933 SCPY(mncc->called.number, p_dialinginfo.id);
934 add_trace("dialing", "number", "%s", mncc->called.number);
937 /* sending user-user */
939 /* redirecting number */
940 mncc->fields |= MNCC_F_REDIRECTING;
941 mncc->redirecting.plan = 1;
942 switch (p_redirinfo.ntype) {
943 case INFO_NTYPE_UNKNOWN:
944 mncc->redirecting.type = 0x0;
946 case INFO_NTYPE_INTERNATIONAL:
947 mncc->redirecting.type = 0x1;
949 case INFO_NTYPE_NATIONAL:
950 mncc->redirecting.type = 0x2;
952 case INFO_NTYPE_SUBSCRIBER:
953 mncc->redirecting.type = 0x4;
955 default: /* INFO_NTYPE_NOTPRESENT */
956 mncc->fields &= ~MNCC_F_REDIRECTING;
959 switch (p_redirinfo.screen) {
960 case INFO_SCREEN_USER:
961 mncc->redirecting.screen = 0;
963 default: /* INFO_SCREE_NETWORK */
964 mncc->redirecting.screen = 3;
967 switch (p_redirinfo.present) {
968 case INFO_PRESENT_ALLOWED:
969 mncc->redirecting.present = 0;
971 case INFO_PRESENT_RESTRICTED:
972 mncc->redirecting.present = 1;
974 default: /* INFO_PRESENT_NOTAVAIL */
975 mncc->redirecting.present = 2;
978 /* sending redirecting number only in ntmode */
979 if (mncc->fields & MNCC_F_REDIRECTING) {
980 SCPY(mncc->redirecting.number, p_redirinfo.id);
981 add_trace("redir", "type", "%d", mncc->redirecting.type);
982 add_trace("redir", "plan", "%d", mncc->redirecting.plan);
983 add_trace("redir", "present", "%d", mncc->redirecting.present);
984 add_trace("redir", "screen", "%d", mncc->redirecting.screen);
985 add_trace("redir", "number", "%s", mncc->redirecting.number);
988 /* if we support any half rate codec we page the mobile with TCH/H
989 * support indication. the mobile will reply paging with a channel
990 * request that indicates half rate support. if no SDCCH and TCH/F
991 * channel is available, BSC can assign a TCH/H channel, because it
992 * knows that the phone supports it. */
993 if (page_with_tchh) {
994 add_trace("lchan", "type", "TCH/H or TCH/F");
995 mncc->lchan_type = GSM_LCHAN_TCH_H;
997 add_trace("lchan", "type", "TCH/F");
998 mncc->lchan_type = GSM_LCHAN_TCH_F;
1002 send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
1004 new_state(PORT_STATE_OUT_SETUP);
1006 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_PROCEEDING);
1007 message_put(message);
1010 if (param->setup.rtpinfo.port) {
1012 p_g_rtp_ip_remote = param->setup.rtpinfo.ip;
1013 p_g_rtp_port_remote = param->setup.rtpinfo.port;
1019 * endpoint sends messages to the port
1021 int Pgsm_bs::message_epoint(unsigned int epoint_id, int message_id, union parameter *param)
1023 if (Pgsm::message_epoint(epoint_id, message_id, param))
1026 switch(message_id) {
1027 case MESSAGE_SETUP: /* dial-out command received from epoint */
1028 if (p_state!=PORT_STATE_IDLE)
1030 message_setup(epoint_id, message_id, param);
1034 PDEBUG(DEBUG_GSM, "Pgsm_bs(%s) gsm port with (caller id %s) received unhandled nessage: %d\n", p_name, p_callerinfo.id, message_id);
1040 int gsm_bs_exit(int rc)
1042 /* free gsm instance */
1044 if (gsm_bs->mncc_lfd.fd > -1) {
1045 close(gsm_bs->mncc_lfd.fd);
1046 unregister_fd(&gsm_bs->mncc_lfd);
1049 del_timer(&gsm_bs->socket_retry);
1058 int gsm_bs_init(struct interface *interface)
1060 /* create gsm instance */
1061 gsm_bs = (struct lcr_gsm *)MALLOC(sizeof(struct lcr_gsm));
1063 SCPY(gsm_bs->interface_name, interface->name);
1064 gsm_bs->type = LCR_GSM_TYPE_NETWORK;
1065 gsm_bs->sun.sun_family = AF_UNIX;
1066 SCPY(gsm_bs->sun.sun_path, "/tmp/bsc_mncc");
1068 memset(&gsm_bs->socket_retry, 0, sizeof(gsm_bs->socket_retry));
1069 add_timer(&gsm_bs->socket_retry, mncc_socket_retry_cb, gsm_bs, 0);
1071 /* do the initial connect */
1072 mncc_socket_retry_cb(&gsm_bs->socket_retry, gsm_bs, 0);