1 /*****************************************************************************\
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg **
8 ** mISDN gsm (BS mode) **
10 \*****************************************************************************/
15 struct lcr_gsm *gsm_bs = NULL;
17 #define RTP_PT_GSM_FULL 3
18 #define RTP_PT_GSM_HALF 96
19 #define RTP_PT_GSM_EFR 97
20 #define RTP_PT_GSM_AMR 98
25 unsigned char dtmf_samples[16][8000];
26 static int dtmf_x[4] = { 1209, 1336, 1477, 1633 };
27 static int dtmf_y[4] = { 697, 770, 852, 941 };
29 void generate_dtmf(void)
31 double fx, fy, sample;
35 for (y = 0; y < 4; y++) {
36 fy = 2 * 3.1415927 * ((double)dtmf_y[y]) / 8000.0;
37 for (x = 0; x < 4; x++) {
38 fx = 2 * 3.1415927 * ((double)dtmf_x[x]) / 8000.0;
39 law = dtmf_samples[y << 2 | x];
40 for (i = 0; i < 8000; i++) {
41 sample = sin(fy * ((double)i)) * 0.251 * 32767.0; /* -6 dB */
42 sample += sin(fx * ((double)i)) * 0.158 * 32767.0; /* -8 dB */
43 *law++ = audio_s16_to_law[(int)sample & 0xffff];
53 Pgsm_bs::Pgsm_bs(int type, char *portname, struct port_settings *settings, struct interface *interface) : Pgsm(type, portname, settings, interface)
59 PDEBUG(DEBUG_GSM, "Created new GSMBSPort(%s).\n", portname);
67 PDEBUG(DEBUG_GSM, "Destroyed GSM BS process(%s).\n", p_name);
70 /* PROCEEDING INDICATION (from MS) */
71 void Pgsm_bs::call_conf_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
73 unsigned char payload_types[8];
76 gsm_trace_header(p_g_interface_name, this, msg_type, DIRECTION_IN);
77 if (mncc->fields & MNCC_F_CAUSE) {
78 add_trace("cause", "coding", "%d", mncc->cause.coding);
79 add_trace("cause", "location", "%", mncc->cause.location);
80 add_trace("cause", "value", "%", mncc->cause.value);
84 new_state(PORT_STATE_OUT_PROCEEDING);
86 /* get list of offered payload types
87 * if list ist empty, the FR V1 is selected */
88 select_payload_type(mncc, payload_types, &payloads, sizeof(payload_types));
89 /* if no given payload type is supported, we assume */
91 payload_types[0] = RTP_PT_GSM_FULL;
95 /* select first payload type that matches the rtp list */
99 for (i = 0; i < p_g_rtp_payloads; i++) {
100 for (j = 0; j < payloads; j++) {
101 if (p_g_rtp_payload_types[i] == payload_types[j])
107 if (i == p_g_rtp_payloads) {
108 struct lcr_msg *message;
110 /* payload offered by remote RTP is not supported */
111 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_RELEASE);
112 message->param.disconnectinfo.cause = 65;
113 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
114 message_put(message);
116 mncc = create_mncc(MNCC_REL_REQ, p_g_callref);
117 gsm_trace_header(p_g_interface_name, this, MNCC_REL_REQ, DIRECTION_OUT);
118 mncc->fields |= MNCC_F_CAUSE;
119 mncc->cause.coding = 3;
120 mncc->cause.location = LOCATION_PRIVATE_LOCAL;
121 mncc->cause.value = 65;
122 add_trace("cause", "coding", "%d", mncc->cause.coding);
123 add_trace("cause", "location", "%d", mncc->cause.location);
124 add_trace("cause", "value", "%d", mncc->cause.value);
125 add_trace("reason", NULL, "None of the payload types are supported by MS");
127 send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
128 new_state(PORT_STATE_RELEASE);
129 trigger_work(&p_g_delete);
131 modify_lchan(p_g_rtp_payload_types[i]);
133 /* modify to first given payload */
134 modify_lchan(payload_types[0]);
138 /* DTMF INDICATION */
139 void Pgsm_bs::start_dtmf_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
141 struct gsm_mncc *resp;
143 gsm_trace_header(p_g_interface_name, this, msg_type, DIRECTION_IN);
144 add_trace("keypad", NULL, "%c", mncc->keypad);
146 SPRINT(p_dialinginfo.id, "%c", mncc->keypad);
147 p_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
150 gsm_trace_header(p_g_interface_name, this, MNCC_START_DTMF_RSP, DIRECTION_OUT);
151 add_trace("keypad", NULL, "%c", mncc->keypad);
153 resp = create_mncc(MNCC_START_DTMF_RSP, p_g_callref);
154 resp->fields |= MNCC_F_KEYPAD;
155 resp->keypad = mncc->keypad;
156 send_and_free_mncc(p_g_lcr_gsm, resp->msg_type, resp);
158 if (p_g_rtp_bridge) {
159 class Port *remote = bridge_remote();
162 struct lcr_msg *message;
164 /* send dtmf information, because we bridge RTP directly */
165 message = message_create(0, remote->p_serial, EPOINT_TO_PORT, MESSAGE_DTMF);
166 message->param.dtmf = mncc->keypad;
167 message_put(message);
170 /* generate DTMF tones, since we do audio forwarding inside LCR */
171 switch (mncc->keypad) {
172 case '1': p_g_dtmf = dtmf_samples[0]; break;
173 case '2': p_g_dtmf = dtmf_samples[1]; break;
174 case '3': p_g_dtmf = dtmf_samples[2]; break;
176 case 'A': p_g_dtmf = dtmf_samples[3]; break;
177 case '4': p_g_dtmf = dtmf_samples[4]; break;
178 case '5': p_g_dtmf = dtmf_samples[5]; break;
179 case '6': p_g_dtmf = dtmf_samples[6]; break;
181 case 'B': p_g_dtmf = dtmf_samples[7]; break;
182 case '7': p_g_dtmf = dtmf_samples[8]; break;
183 case '8': p_g_dtmf = dtmf_samples[9]; break;
184 case '9': p_g_dtmf = dtmf_samples[10]; break;
186 case 'C': p_g_dtmf = dtmf_samples[11]; break;
187 case '*': p_g_dtmf = dtmf_samples[12]; break;
188 case '0': p_g_dtmf = dtmf_samples[13]; break;
189 case '#': p_g_dtmf = dtmf_samples[14]; break;
191 case 'D': p_g_dtmf = dtmf_samples[15]; break;
196 void Pgsm_bs::stop_dtmf_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
198 struct gsm_mncc *resp;
200 gsm_trace_header(p_g_interface_name, this, msg_type, DIRECTION_IN);
201 add_trace("keypad", NULL, "%c", mncc->keypad);
205 gsm_trace_header(p_g_interface_name, this, MNCC_STOP_DTMF_RSP, DIRECTION_OUT);
206 add_trace("keypad", NULL, "%c", mncc->keypad);
208 resp = create_mncc(MNCC_STOP_DTMF_RSP, p_g_callref);
209 resp->keypad = mncc->keypad;
210 send_and_free_mncc(p_g_lcr_gsm, resp->msg_type, resp);
216 /* HOLD INDICATION */
217 void Pgsm_bs::hold_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
219 struct lcr_msg *message;
220 struct gsm_mncc *resp, *frame;
222 gsm_trace_header(p_g_interface_name, this, msg_type, DIRECTION_IN);
225 /* notify the hold of call */
226 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_NOTIFY);
227 message->param.notifyinfo.notify = INFO_NOTIFY_REMOTE_HOLD;
228 message->param.notifyinfo.local = 1; /* call is held by supplementary service */
229 message_put(message);
231 /* acknowledge hold */
232 gsm_trace_header(p_g_interface_name, this, MNCC_HOLD_CNF, DIRECTION_OUT);
234 resp = create_mncc(MNCC_HOLD_CNF, p_g_callref);
235 send_and_free_mncc(p_g_lcr_gsm, resp->msg_type, resp);
238 if (p_g_tch_connected) { /* it should be true */
239 gsm_trace_header(p_g_interface_name, this, MNCC_FRAME_DROP, DIRECTION_OUT);
241 frame = create_mncc(MNCC_FRAME_DROP, p_g_callref);
242 send_and_free_mncc(p_g_lcr_gsm, frame->msg_type, frame);
243 p_g_tch_connected = 0;
248 /* RETRIEVE INDICATION */
249 void Pgsm_bs::retr_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
251 struct lcr_msg *message;
252 struct gsm_mncc *resp, *frame;
254 gsm_trace_header(p_g_interface_name, this, msg_type, DIRECTION_IN);
257 /* notify the retrieve of call */
258 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_NOTIFY);
259 message->param.notifyinfo.notify = INFO_NOTIFY_REMOTE_RETRIEVAL;
260 message->param.notifyinfo.local = 1; /* call is retrieved by supplementary service */
261 message_put(message);
263 /* acknowledge retr */
264 gsm_trace_header(p_g_interface_name, this, MNCC_RETRIEVE_CNF, DIRECTION_OUT);
266 resp = create_mncc(MNCC_RETRIEVE_CNF, p_g_callref);
267 send_and_free_mncc(p_g_lcr_gsm, resp->msg_type, resp);
270 if (!p_g_tch_connected) { /* it should be true */
271 gsm_trace_header(p_g_interface_name, this, MNCC_FRAME_RECV, DIRECTION_OUT);
273 frame = create_mncc(MNCC_FRAME_RECV, p_g_callref);
274 send_and_free_mncc(p_g_lcr_gsm, frame->msg_type, frame);
275 p_g_tch_connected = 1;
280 * select payload type by given list or GSM V1 FR
281 * return the payload type or 0 if not given
284 void Pgsm_bs::select_payload_type(struct gsm_mncc *mncc, unsigned char *payload_types, int *payloads, int max_payloads)
286 unsigned char payload_type;
290 gsm_trace_header(p_g_interface_name, this, 1 /* codec negotioation */, DIRECTION_NONE);
291 if ((mncc->fields & MNCC_F_BEARER_CAP)) {
292 /* select preferred payload type from list */
295 add_trace("bearer", "capa", "given by MS");
296 for (i = 0; mncc->bearer_cap.speech_ver[i] >= 0; i++) {
297 /* select payload type we support */
298 switch (mncc->bearer_cap.speech_ver[i]) {
300 add_trace("speech", "version", "Full Rate given");
301 payload_type = RTP_PT_GSM_FULL;
304 add_trace("speech", "version", "EFR given");
305 payload_type = RTP_PT_GSM_EFR;
308 add_trace("speech", "version", "AMR given");
309 payload_type = RTP_PT_GSM_AMR;
312 add_trace("speech", "version", "Half Rate given");
313 payload_type = RTP_PT_GSM_HALF;
316 add_trace("speech", "version", "%d given", mncc->bearer_cap.speech_ver[i]);
319 /* wen don't support it, so we check the next */
321 add_trace("speech", "ignored", "Not supported by LCR");
324 if (!p_g_rtp_bridge) {
325 if (payload_type != RTP_PT_GSM_FULL) {
326 add_trace("speech", "ignored", "Not suitable for LCR");
330 if (*payloads <= max_payloads) {
331 payload_types[*payloads] = payload_type;
336 add_trace("bearer", "capa", "not given by MS");
337 add_trace("speech", "version", "Full Rate given");
338 payload_types[0] = RTP_PT_GSM_FULL;
342 add_trace("error", "", "All given payload types unsupported");
347 * handles all indications
349 /* SETUP INDICATION */
350 void Pgsm_bs::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
352 class Endpoint *epoint;
353 struct lcr_msg *message;
354 struct gsm_mncc *proceeding, *frame;
355 struct interface *interface;
356 unsigned char payload_types[8];
359 interface = getinterfacebyname(p_g_interface_name);
361 PERROR("Cannot find interface %s.\n", p_g_interface_name);
365 /* process given callref */
366 gsm_trace_header(p_g_interface_name, this, 0, DIRECTION_IN);
367 add_trace("callref", "new", "0x%x", callref);
369 /* release in case the ID is already in use */
370 add_trace("error", NULL, "callref already in use");
372 mncc = create_mncc(MNCC_REJ_REQ, callref);
373 gsm_trace_header(p_g_interface_name, this, MNCC_REJ_REQ, DIRECTION_OUT);
374 mncc->fields |= MNCC_F_CAUSE;
375 mncc->cause.coding = 3;
376 mncc->cause.location = 1;
377 mncc->cause.value = 47;
378 add_trace("cause", "coding", "%d", mncc->cause.coding);
379 add_trace("cause", "location", "%d", mncc->cause.location);
380 add_trace("cause", "value", "%d", mncc->cause.value);
381 add_trace("reason", NULL, "callref already in use");
383 send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
384 new_state(PORT_STATE_RELEASE);
385 trigger_work(&p_g_delete);
388 p_g_callref = callref;
393 p_callerinfo.present = INFO_PRESENT_RESTRICTED;
395 p_callerinfo.present = INFO_PRESENT_ALLOWED;
396 if (mncc->calling.number[0])
397 SCPY(p_callerinfo.id, mncc->calling.number);
399 p_callerinfo.present = INFO_PRESENT_NOTAVAIL;
400 SCPY(p_callerinfo.imsi, mncc->imsi);
401 p_callerinfo.screen = INFO_SCREEN_NETWORK;
402 p_callerinfo.ntype = INFO_NTYPE_UNKNOWN;
403 SCPY(p_callerinfo.interface, p_g_interface_name);
405 /* dialing information */
406 SCAT(p_dialinginfo.id, mncc->called.number);
407 switch (mncc->called.type) {
409 p_dialinginfo.ntype = INFO_NTYPE_INTERNATIONAL;
412 p_dialinginfo.ntype = INFO_NTYPE_NATIONAL;
415 p_dialinginfo.ntype = INFO_NTYPE_SUBSCRIBER;
418 p_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
421 if (mncc->emergency) {
422 SCPY(p_dialinginfo.id, "emergency");
424 p_dialinginfo.sending_complete = 1;
426 /* bearer capability */
427 p_capainfo.bearer_capa = INFO_BC_SPEECH;
428 p_capainfo.bearer_info1 = (options.law=='a')?3:2;
429 p_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
430 p_capainfo.source_mode = B_MODE_TRANSPARENT;
431 p_g_mode = p_capainfo.source_mode;
433 /* get list of offered payload types
434 * if list ist empty, the FR V1 is selected */
435 select_payload_type(mncc, payload_types, &payloads, sizeof(payload_types));
436 /* if no given payload type is supported, we assume */
438 payload_types[0] = RTP_PT_GSM_FULL;
442 /* if no given payload type is supported, we reject the call */
444 mncc = create_mncc(MNCC_REJ_REQ, callref);
445 gsm_trace_header(p_g_interface_name, this, MNCC_REJ_REQ, DIRECTION_OUT);
446 mncc->fields |= MNCC_F_CAUSE;
447 mncc->cause.coding = 3;
448 mncc->cause.location = 1;
449 mncc->cause.value = 65;
450 add_trace("cause", "coding", "%d", mncc->cause.coding);
451 add_trace("cause", "location", "%d", mncc->cause.location);
452 add_trace("cause", "value", "%d", mncc->cause.value);
453 add_trace("reason", NULL, "Given speech codec(s) not supported");
455 send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
456 new_state(PORT_STATE_RELEASE);
457 trigger_work(&p_g_delete);
464 /* what infos did we got ... */
465 gsm_trace_header(p_g_interface_name, this, msg_type, DIRECTION_IN);
466 if (p_callerinfo.id[0])
467 add_trace("calling", "number", "%s", p_callerinfo.id);
469 SPRINT(p_callerinfo.id, "imsi-%s", p_callerinfo.imsi);
470 add_trace("calling", "imsi", "%s", p_callerinfo.imsi);
471 add_trace("dialing", "number", "%s", p_dialinginfo.id);
474 /* create endpoint */
476 FATAL("Incoming call but already got an endpoint.\n");
477 if (!(epoint = new Endpoint(p_serial, 0)))
478 FATAL("No memory for Endpoint instance\n");
479 epoint->ep_app = new_endpointapp(epoint, 0, interface->app); //incoming
480 epointlist_new(epoint->ep_serial);
482 /* modify lchan in case of no rtp bridge */
484 modify_lchan(payload_types[0]);
486 /* send call proceeding */
487 gsm_trace_header(p_g_interface_name, this, MNCC_CALL_PROC_REQ, DIRECTION_OUT);
488 proceeding = create_mncc(MNCC_CALL_PROC_REQ, p_g_callref);
490 proceeding->fields |= MNCC_F_PROGRESS;
491 proceeding->progress.coding = 3; /* GSM */
492 proceeding->progress.location = 1;
493 proceeding->progress.descr = 8;
494 add_trace("progress", "coding", "%d", proceeding->progress.coding);
495 add_trace("progress", "location", "%d", proceeding->progress.location);
496 add_trace("progress", "descr", "%d", proceeding->progress.descr);
499 send_and_free_mncc(p_g_lcr_gsm, proceeding->msg_type, proceeding);
501 new_state(PORT_STATE_IN_PROCEEDING);
503 if (p_g_tones && !p_g_tch_connected) { /* only if ... */
504 gsm_trace_header(p_g_interface_name, this, MNCC_FRAME_RECV, DIRECTION_OUT);
506 frame = create_mncc(MNCC_FRAME_RECV, p_g_callref);
507 send_and_free_mncc(p_g_lcr_gsm, frame->msg_type, frame);
508 p_g_tch_connected = 1;
511 /* send setup message to endpoit */
512 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_SETUP);
513 message->param.setup.port_type = p_type;
514 // message->param.setup.dtmf = 0;
515 memcpy(&message->param.setup.dialinginfo, &p_dialinginfo, sizeof(struct dialing_info));
516 memcpy(&message->param.setup.callerinfo, &p_callerinfo, sizeof(struct caller_info));
517 memcpy(&message->param.setup.capainfo, &p_capainfo, sizeof(struct capa_info));
518 SCPY((char *)message->param.setup.useruser.data, (char *)mncc->useruser.info);
519 message->param.setup.useruser.len = strlen(mncc->useruser.info);
520 message->param.setup.useruser.protocol = mncc->useruser.proto;
521 if (p_g_rtp_bridge) {
522 struct gsm_mncc_rtp *rtp;
525 PDEBUG(DEBUG_GSM, "Request RTP peer info, before forwarding setup\n");
526 p_g_setup_pending = message;
527 rtp = (struct gsm_mncc_rtp *) create_mncc(MNCC_RTP_CREATE, p_g_callref);
528 send_and_free_mncc(p_g_lcr_gsm, rtp->msg_type, rtp);
530 for (i = 0; i < (int)sizeof(message->param.setup.rtpinfo.payload_types) && i < payloads; i++) {
531 message->param.setup.rtpinfo.payload_types[i] = payload_types[i];
532 message->param.setup.rtpinfo.payloads++;
536 message_put(message);
541 * BSC sends message to port
543 int message_bsc(struct lcr_gsm *lcr_gsm, int msg_type, void *arg)
545 struct gsm_mncc *mncc = (struct gsm_mncc *)arg;
546 unsigned int callref = mncc->callref;
548 class Pgsm_bs *pgsm_bs = NULL;
550 // struct mISDNport *mISDNport;
552 /* Special messages */
557 callref = mncc->callref;
560 if ((port->p_type & PORT_CLASS_GSM_MASK) == PORT_CLASS_GSM_BS) {
561 pgsm_bs = (class Pgsm_bs *)port;
562 if (pgsm_bs->p_g_callref == callref) {
569 if (msg_type == GSM_TCHF_FRAME
570 || msg_type == GSM_TCHF_BAD_FRAME) {
572 /* inject DTMF, if enabled */
573 if (pgsm_bs->p_g_dtmf) {
574 unsigned char data[160];
577 for (i = 0; i < 160; i++) {
578 data[i] = pgsm_bs->p_g_dtmf[pgsm_bs->p_g_dtmf_index++];
579 if (pgsm_bs->p_g_dtmf_index == 8000)
580 pgsm_bs->p_g_dtmf_index = 0;
583 pgsm_bs->bridge_tx(data, 160);
585 pgsm_bs->frame_receive(arg);
586 /* if we do not bridge we need to inject audio, if available */
587 if (!pgsm_bs->p_bridge || pgsm_bs->p_tone_name[0]) {
588 unsigned char data[160];
591 i = pgsm_bs->read_audio(data, 160);
593 pgsm_bs->audio_send(data, i);
600 struct interface *interface;
602 if (msg_type != MNCC_SETUP_IND)
605 interface = getinterfacebyname(lcr_gsm->interface_name);
607 struct gsm_mncc *rej;
609 rej = create_mncc(MNCC_REJ_REQ, callref);
610 rej->fields |= MNCC_F_CAUSE;
611 rej->cause.coding = 3;
612 rej->cause.location = 1;
613 rej->cause.value = 27;
614 gsm_trace_header(NULL, NULL, MNCC_REJ_REQ, DIRECTION_OUT);
615 add_trace("cause", "coding", "%d", rej->cause.coding);
616 add_trace("cause", "location", "%d", rej->cause.location);
617 add_trace("cause", "value", "%d", rej->cause.value);
618 add_trace("reason", NULL, "interface %s not found", lcr_gsm->interface_name);
620 send_and_free_mncc(lcr_gsm, rej->msg_type, rej);
623 /* creating port object, transparent until setup with hdlc */
624 SPRINT(name, "%s-%d-in", interface->name, 0);
625 if (!(pgsm_bs = new Pgsm_bs(PORT_TYPE_GSM_BS_IN, name, NULL, interface)))
626 FATAL("Cannot create Port instance.\n");
631 pgsm_bs->setup_ind(msg_type, callref, mncc);
634 case MNCC_RTP_CREATE:
635 pgsm_bs->rtp_create_ind(msg_type, callref, mncc);
638 case MNCC_RTP_CONNECT:
639 pgsm_bs->rtp_connect_ind(msg_type, callref, mncc);
642 case MNCC_START_DTMF_IND:
643 pgsm_bs->start_dtmf_ind(msg_type, callref, mncc);
646 case MNCC_STOP_DTMF_IND:
647 pgsm_bs->stop_dtmf_ind(msg_type, callref, mncc);
650 case MNCC_CALL_CONF_IND:
651 pgsm_bs->call_conf_ind(msg_type, callref, mncc);
655 pgsm_bs->alert_ind(msg_type, callref, mncc);
659 pgsm_bs->setup_cnf(msg_type, callref, mncc);
662 case MNCC_SETUP_COMPL_IND:
663 pgsm_bs->setup_compl_ind(msg_type, callref, mncc);
667 pgsm_bs->disc_ind(msg_type, callref, mncc);
673 pgsm_bs->rel_ind(msg_type, callref, mncc);
676 case MNCC_NOTIFY_IND:
677 pgsm_bs->notify_ind(msg_type, callref, mncc);
681 pgsm_bs->hold_ind(msg_type, callref, mncc);
684 case MNCC_RETRIEVE_IND:
685 pgsm_bs->retr_ind(msg_type, callref, mncc);
689 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);
695 void Pgsm_bs::message_setup(unsigned int epoint_id, int message_id, union parameter *param)
697 struct lcr_msg *message;
698 struct epoint_list *epointlist;
699 struct gsm_mncc *mncc;
701 /* copy setup infos to port */
702 memcpy(&p_callerinfo, ¶m->setup.callerinfo, sizeof(p_callerinfo));
703 memcpy(&p_dialinginfo, ¶m->setup.dialinginfo, sizeof(p_dialinginfo));
704 memcpy(&p_capainfo, ¶m->setup.capainfo, sizeof(p_capainfo));
705 memcpy(&p_redirinfo, ¶m->setup.redirinfo, sizeof(p_redirinfo));
707 /* no GSM MNCC connection */
708 if (p_g_lcr_gsm->mncc_lfd.fd < 0) {
709 gsm_trace_header(p_g_interface_name, this, MNCC_SETUP_REQ, DIRECTION_OUT);
710 add_trace("failure", NULL, "No MNCC connection.");
712 message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
713 message->param.disconnectinfo.cause = 41; // temp. failure.
714 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
715 message_put(message);
716 new_state(PORT_STATE_RELEASE);
717 trigger_work(&p_g_delete);
722 if (!p_dialinginfo.id[0]) {
723 gsm_trace_header(p_g_interface_name, this, MNCC_SETUP_REQ, DIRECTION_OUT);
724 add_trace("failure", NULL, "No dialed subscriber given.");
726 message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
727 message->param.disconnectinfo.cause = 28;
728 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
729 message_put(message);
730 new_state(PORT_STATE_RELEASE);
731 trigger_work(&p_g_delete);
735 /* unsupported codec for RTP bridge */
736 if (param->setup.rtpinfo.port) {
739 p_g_rtp_payloads = 0;
740 gsm_trace_header(p_g_interface_name, this, 1 /* codec negotioation */, DIRECTION_NONE);
741 for (i = 0; i < param->setup.rtpinfo.payloads; i++) {
742 switch (param->setup.rtpinfo.payload_types[i]) {
743 case RTP_PT_GSM_FULL:
746 case RTP_PT_GSM_HALF:
747 add_trace("rtp", "payload", "%d supported", param->setup.rtpinfo.payload_types[i]);
748 if (p_g_rtp_payloads < (int)sizeof(p_g_rtp_payload_types)) {
749 p_g_rtp_payload_types[p_g_rtp_payloads++] = param->setup.rtpinfo.payload_types[i];
754 add_trace("rtp", "payload", "%d unsupported", param->setup.rtpinfo.payload_types[i]);
758 if (!p_g_rtp_payloads) {
759 gsm_trace_header(p_g_interface_name, this, MNCC_SETUP_REQ, DIRECTION_OUT);
760 add_trace("failure", NULL, "No payload given that is supported by GSM");
762 message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
763 message->param.disconnectinfo.cause = 65;
764 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
765 message_put(message);
766 new_state(PORT_STATE_RELEASE);
767 trigger_work(&p_g_delete);
772 // SCPY(&p_m_tones_dir, param->setup.ext.tones_dir);
773 /* screen outgoing caller id */
774 do_screen(1, p_callerinfo.id, sizeof(p_callerinfo.id), &p_callerinfo.ntype, &p_callerinfo.present, p_g_interface_name);
776 /* attach only if not already */
777 epointlist = p_epointlist;
779 if (epointlist->epoint_id == epoint_id)
781 epointlist = epointlist->next;
784 epointlist_new(epoint_id);
787 gsm_trace_header(p_g_interface_name, this, 0, DIRECTION_OUT);
788 p_g_callref = new_callref++;
789 add_trace("callref", "new", "0x%x", p_g_callref);
792 gsm_trace_header(p_g_interface_name, this, MNCC_SETUP_REQ, DIRECTION_OUT);
793 mncc = create_mncc(MNCC_SETUP_REQ, p_g_callref);
794 /* caller information */
795 mncc->fields |= MNCC_F_CALLING;
796 mncc->calling.plan = 1;
797 switch (p_callerinfo.ntype) {
798 case INFO_NTYPE_UNKNOWN:
799 mncc->calling.type = 0x0;
801 case INFO_NTYPE_INTERNATIONAL:
802 mncc->calling.type = 0x1;
804 case INFO_NTYPE_NATIONAL:
805 mncc->calling.type = 0x2;
807 case INFO_NTYPE_SUBSCRIBER:
808 mncc->calling.type = 0x4;
810 default: /* INFO_NTYPE_NOTPRESENT */
811 mncc->fields &= ~MNCC_F_CALLING;
814 switch (p_callerinfo.screen) {
815 case INFO_SCREEN_USER:
816 mncc->calling.screen = 0;
818 default: /* INFO_SCREEN_NETWORK */
819 mncc->calling.screen = 3;
822 switch (p_callerinfo.present) {
823 case INFO_PRESENT_ALLOWED:
824 mncc->calling.present = 0;
826 case INFO_PRESENT_RESTRICTED:
827 mncc->calling.present = 1;
829 default: /* INFO_PRESENT_NOTAVAIL */
830 mncc->calling.present = 2;
833 if (mncc->fields & MNCC_F_CALLING) {
834 SCPY(mncc->calling.number, p_callerinfo.id);
835 add_trace("calling", "type", "%d", mncc->calling.type);
836 add_trace("calling", "plan", "%d", mncc->calling.plan);
837 add_trace("calling", "present", "%d", mncc->calling.present);
838 add_trace("calling", "screen", "%d", mncc->calling.screen);
839 add_trace("calling", "number", "%s", mncc->calling.number);
841 /* dialing information */
842 mncc->fields |= MNCC_F_CALLED;
843 if (!strncmp(p_dialinginfo.id, "imsi-", 5)) {
844 SCPY(mncc->imsi, p_dialinginfo.id+5);
845 add_trace("dialing", "imsi", "%s", mncc->imsi);
847 SCPY(mncc->called.number, p_dialinginfo.id);
848 add_trace("dialing", "number", "%s", mncc->called.number);
851 /* sending user-user */
853 /* redirecting number */
854 mncc->fields |= MNCC_F_REDIRECTING;
855 mncc->redirecting.plan = 1;
856 switch (p_redirinfo.ntype) {
857 case INFO_NTYPE_UNKNOWN:
858 mncc->redirecting.type = 0x0;
860 case INFO_NTYPE_INTERNATIONAL:
861 mncc->redirecting.type = 0x1;
863 case INFO_NTYPE_NATIONAL:
864 mncc->redirecting.type = 0x2;
866 case INFO_NTYPE_SUBSCRIBER:
867 mncc->redirecting.type = 0x4;
869 default: /* INFO_NTYPE_NOTPRESENT */
870 mncc->fields &= ~MNCC_F_REDIRECTING;
873 switch (p_redirinfo.screen) {
874 case INFO_SCREEN_USER:
875 mncc->redirecting.screen = 0;
877 default: /* INFO_SCREE_NETWORK */
878 mncc->redirecting.screen = 3;
881 switch (p_redirinfo.present) {
882 case INFO_PRESENT_ALLOWED:
883 mncc->redirecting.present = 0;
885 case INFO_PRESENT_RESTRICTED:
886 mncc->redirecting.present = 1;
888 default: /* INFO_PRESENT_NOTAVAIL */
889 mncc->redirecting.present = 2;
892 /* sending redirecting number only in ntmode */
893 if (mncc->fields & MNCC_F_REDIRECTING) {
894 SCPY(mncc->redirecting.number, p_redirinfo.id);
895 add_trace("redir", "type", "%d", mncc->redirecting.type);
896 add_trace("redir", "plan", "%d", mncc->redirecting.plan);
897 add_trace("redir", "present", "%d", mncc->redirecting.present);
898 add_trace("redir", "screen", "%d", mncc->redirecting.screen);
899 add_trace("redir", "number", "%s", mncc->redirecting.number);
903 send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
905 new_state(PORT_STATE_OUT_SETUP);
907 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_PROCEEDING);
908 message_put(message);
911 if (param->setup.rtpinfo.port) {
913 p_g_rtp_ip_remote = param->setup.rtpinfo.ip;
914 p_g_rtp_port_remote = param->setup.rtpinfo.port;
920 * endpoint sends messages to the port
922 int Pgsm_bs::message_epoint(unsigned int epoint_id, int message_id, union parameter *param)
924 if (Pgsm::message_epoint(epoint_id, message_id, param))
928 case MESSAGE_SETUP: /* dial-out command received from epoint */
929 if (p_state!=PORT_STATE_IDLE)
931 message_setup(epoint_id, message_id, param);
935 PDEBUG(DEBUG_GSM, "Pgsm_bs(%s) gsm port with (caller id %s) received unhandled nessage: %d\n", p_name, p_callerinfo.id, message_id);
941 int gsm_bs_exit(int rc)
943 /* free gsm instance */
945 if (gsm_bs->mncc_lfd.fd > -1) {
946 close(gsm_bs->mncc_lfd.fd);
947 unregister_fd(&gsm_bs->mncc_lfd);
950 del_timer(&gsm_bs->socket_retry);
959 int gsm_bs_init(struct interface *interface)
961 /* create gsm instance */
962 gsm_bs = (struct lcr_gsm *)MALLOC(sizeof(struct lcr_gsm));
964 SCPY(gsm_bs->interface_name, interface->name);
965 gsm_bs->type = LCR_GSM_TYPE_NETWORK;
966 gsm_bs->sun.sun_family = AF_UNIX;
967 SCPY(gsm_bs->sun.sun_path, "/tmp/bsc_mncc");
969 memset(&gsm_bs->socket_retry, 0, sizeof(gsm_bs->socket_retry));
970 add_timer(&gsm_bs->socket_retry, mncc_socket_retry_cb, gsm_bs, 0);
972 /* do the initial connect */
973 mncc_socket_retry_cb(&gsm_bs->socket_retry, gsm_bs, 0);