1 /*****************************************************************************\
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg **
10 \*****************************************************************************/
20 #include <openbsc/db.h>
21 #include <openbsc/select.h>
22 #include <openbsc/debug.h>
23 #include <openbsc/e1_input.h>
24 #include <openbsc/talloc.h>
25 #include <openbsc/mncc.h>
26 #include <openbsc/trau_frame.h>
27 struct gsm_network *bsc_gsmnet = 0;
28 extern int ipacc_rtp_direct;
29 extern int bsc_bootstrap_network(int (*mmc_rev)(struct gsm_network *, int, void *),
30 const char *cfg_file);
31 extern int bsc_shutdown_net(struct gsm_network *net);
32 void talloc_ctx_init(void);
33 void on_dso_load_token(void);
34 void on_dso_load_rrlp(void);
36 #include "gsm_audio.h"
41 #define PF_ISDN AF_ISDN
45 struct lcr_gsm *gsm = NULL;
47 static unsigned int new_callref = 1;
51 * create and send mncc message
53 static struct gsm_mncc *create_mncc(int msg_type, unsigned int callref)
55 struct gsm_mncc *mncc;
57 mncc = (struct gsm_mncc *)MALLOC(sizeof(struct gsm_mncc));
58 mncc->msg_type = msg_type;
59 mncc->callref = callref;
62 static int send_and_free_mncc(struct gsm_network *net, unsigned int msg_type, void *data)
66 ret = mncc_send(net, msg_type, data);
76 Pgsm::Pgsm(int type, struct mISDNport *mISDNport, char *portname, struct port_settings *settings, int channel, int exclusive, int mode) : PmISDN(type, mISDNport, portname, settings, channel, exclusive, mode)
78 p_callerinfo.itype = (mISDNport->ifport->interface->extension)?INFO_ITYPE_ISDN_EXTENSION:INFO_ITYPE_ISDN;
81 p_m_g_gsm_b_sock = -1;
82 p_m_g_gsm_b_index = -1;
83 p_m_g_gsm_b_active = 0;
84 p_m_g_notify_pending = NULL;
85 p_m_g_decoder = gsm_audio_create();
86 p_m_g_encoder = gsm_audio_create();
87 if (!p_m_g_encoder || !p_m_g_decoder) {
88 PERROR("Failed to create GSM audio codec instance\n");
92 p_m_g_tch_connected = 0;
94 PDEBUG(DEBUG_GSM, "Created new mISDNPort(%s).\n", portname);
102 PDEBUG(DEBUG_GSM, "Destroyed GSM process(%s).\n", p_name);
104 /* remove queued message */
105 if (p_m_g_notify_pending)
106 message_free(p_m_g_notify_pending);
108 /* close audio transfer socket */
109 if (p_m_g_gsm_b_sock > -1)
114 gsm_audio_destroy(p_m_g_encoder);
116 gsm_audio_destroy(p_m_g_decoder);
120 /* close bsc side bchannel */
121 void Pgsm::bchannel_close(void)
123 if (p_m_g_gsm_b_sock > -1)
124 close(p_m_g_gsm_b_sock);
125 p_m_g_gsm_b_sock = -1;
126 p_m_g_gsm_b_index = -1;
127 p_m_g_gsm_b_active = 0;
130 /* open bsc side bchannel */
131 int Pgsm::bchannel_open(int index)
135 struct sockaddr_mISDN addr;
136 struct mISDNhead act;
138 if (p_m_g_gsm_b_sock > -1) {
139 PERROR("Socket already created for index %d\n", index);
144 ret = p_m_g_gsm_b_sock = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_B_RAW);
146 PERROR("Failed to open bchannel-socket for index %d\n", index);
151 /* set nonblocking io */
152 ret = ioctl(p_m_g_gsm_b_sock, FIONBIO, &on);
154 PERROR("Failed to set bchannel-socket index %d into nonblocking IO\n", index);
159 /* bind socket to bchannel */
160 addr.family = AF_ISDN;
161 addr.dev = gsm->gsm_port;
162 addr.channel = index+1+(index>15);
163 ret = bind(p_m_g_gsm_b_sock, (struct sockaddr *)&addr, sizeof(addr));
165 PERROR("Failed to bind bchannel-socket for index %d\n", index);
169 /* activate bchannel */
170 PDEBUG(DEBUG_GSM, "Activating GSM side channel index %i.\n", index);
171 act.prim = PH_ACTIVATE_REQ;
173 ret = sendto(p_m_g_gsm_b_sock, &act, MISDN_HEADER_LEN, 0, NULL, 0);
175 PERROR("Failed to activate index %d\n", index);
180 p_m_g_gsm_b_index = index;
185 /* receive from bchannel */
186 void Pgsm::bchannel_receive(struct mISDNhead *hh, unsigned char *data, int len)
189 unsigned char frame[33];
190 struct decoded_trau_frame tf;
192 /* encoder init failed */
196 /* (currently) not connected, so don't flood tch! */
197 if (!p_m_g_tch_connected)
200 /* write to rx buffer */
202 p_m_g_rxdata[p_m_g_rxpos++] = audio_law_to_s32[*data++];
203 if (p_m_g_rxpos == 160) {
207 gsm_audio_encode(p_m_g_encoder, p_m_g_rxdata, frame);
209 /* set c-bits and t-bits */
215 memset(&tf.c_bits[5], 0, 6);
216 memset(&tf.c_bits[11], 1, 10);
217 memset(&tf.t_bits[0], 1, 4);
219 /* reassemble d-bits */
224 tf.d_bits[i] = (frame[j] >> k) & 1;
237 /* transmit to bchannel */
238 void Pgsm::bchannel_send(unsigned int prim, unsigned int id, unsigned char *data, int len)
240 unsigned char buf[MISDN_HEADER_LEN+len];
241 struct mISDNhead *hh = (struct mISDNhead *)buf;
244 if (!p_m_g_gsm_b_active)
247 /* make and send frame */
248 hh->prim = PH_DATA_REQ;
250 memcpy(buf+MISDN_HEADER_LEN, data, len);
251 ret = sendto(p_m_g_gsm_b_sock, buf, MISDN_HEADER_LEN+len, 0, NULL, 0);
253 PERROR("Failed to send to socket index %d\n", index);
256 void Pgsm::trau_send(void *_tf)
258 struct decoded_trau_frame *tf = (struct decoded_trau_frame *)_tf;
259 unsigned char data[sizeof(struct gsm_trau_frame) + sizeof(struct decoded_trau_frame)];
260 struct gsm_trau_frame *frame = (struct gsm_trau_frame *)data;
262 frame->msg_type = GSM_TRAU_FRAME;
263 frame->callref = p_m_g_callref;
264 memcpy(frame->data, tf, sizeof(struct decoded_trau_frame));
265 mncc_send((struct gsm_network *)gsm->network, frame->msg_type, frame);
269 void Pgsm::trau_receive(void *_frame)
271 struct gsm_trau_frame *frm = (struct gsm_trau_frame *)_frame;
272 struct decoded_trau_frame *tf = (struct decoded_trau_frame *)frm->data;
273 //struct decoded_trau_frame *tf = (struct decoded_trau_frame *)_frame;
274 unsigned char frame[33];
275 signed short samples[160];
276 unsigned char data[160];
282 // printf("got trau %d %d %d %d %d\n", tf->c_bits[0], tf->c_bits[1], tf->c_bits[2], tf->c_bits[3], tf->c_bits[4]);
283 if (tf->c_bits[0]!=0 || tf->c_bits[1]!=0 || tf->c_bits[2]!=0 || tf->c_bits[3]!=1 || tf->c_bits[4]!=0)
284 PERROR("illegal trau (C1-C5) %d %d %d %d %d\n", tf->c_bits[0], tf->c_bits[1], tf->c_bits[2], tf->c_bits[3], tf->c_bits[4]);
287 memset(&frame, 0, sizeof(frame));
288 // frame[0] = 0xd << 4;
290 /* reassemble bits */
295 if (tf->d_bits[i] > 1)
297 frame[j] |= (tf->d_bits[i] << k);
306 gsm_audio_decode(p_m_g_decoder, frame, samples);
307 for (i = 0; i < 160; i++) {
308 data[i] = audio_s16_to_law[samples[i] & 0xffff];
312 bchannel_send(PH_DATA_REQ, 0, data, 160);
319 static void gsm_trace_header(struct mISDNport *mISDNport, class PmISDN *port, unsigned int msg_type, int direction)
323 /* select message and primitive text */
324 SCPY(msgtext, get_mncc_name(msg_type));
327 if (direction == DIRECTION_OUT)
328 SCAT(msgtext, " MSC->BSC");
330 SCAT(msgtext, " MSC<-BSC");
332 /* init trace with given values */
333 start_trace(mISDNport?mISDNport->portnum:-1,
334 mISDNport?(mISDNport->ifport?mISDNport->ifport->interface:NULL):NULL,
335 port?numberrize_callerinfo(port->p_callerinfo.id, port->p_callerinfo.ntype, options.national, options.international):NULL,
336 port?port->p_dialinginfo.id:NULL,
339 port?port->p_serial:0,
345 /* select bchannel */
346 int Pgsm::hunt_bchannel(void)
351 chan_trace_header(p_m_mISDNport, this, "CHANNEL SELECTION (setup)", DIRECTION_NONE);
352 add_trace("channel", "reserved", "%d", p_m_mISDNport->b_reserved);
353 if (p_m_mISDNport->b_reserved >= p_m_mISDNport->b_num) { // of out chan..
354 add_trace("conclusion", NULL, "all channels are reserved");
356 return(-34); // no channel
361 while(i < p_m_mISDNport->b_num) {
362 if (p_m_mISDNport->b_port[i] == NULL) {
363 channel = i+1+(i>=15);
369 add_trace("conclusion", NULL, "no channel available");
371 return(-6); // channel unacceptable
373 add_trace("conclusion", NULL, "channel available");
374 add_trace("connect", "channel", "%d", channel);
381 * handles all indications
383 /* SETUP INDICATION */
384 void Pgsm::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
387 class Endpoint *epoint;
388 struct lcr_msg *message;
390 struct gsm_mncc *mode, *proceeding, *frame;
392 /* emergency shutdown */
393 printf("%d %d\n", mncc->emergency, !gsm->conf.noemergshut);
394 if (mncc->emergency && !gsm->conf.noemergshut) {
395 start_trace(p_m_mISDNport->portnum,
396 p_m_mISDNport->ifport->interface,
402 "EMERGENCY SHUTDOWN (due to received emergency call)");
406 /* process given callref */
407 l1l2l3_trace_header(p_m_mISDNport, this, L3_NEW_L3ID_IND, DIRECTION_IN);
408 add_trace("callref", "new", "0x%x", callref);
410 /* release in case the ID is already in use */
411 add_trace("error", NULL, "callref already in use");
413 mncc = create_mncc(MNCC_REJ_REQ, callref);
414 gsm_trace_header(p_m_mISDNport, this, MNCC_REJ_REQ, DIRECTION_OUT);
415 mncc->fields |= MNCC_F_CAUSE;
416 mncc->cause.coding = 3;
417 mncc->cause.location = 1;
418 mncc->cause.value = 47;
419 add_trace("cause", "coding", "%d", mncc->cause.coding);
420 add_trace("cause", "location", "%d", mncc->cause.location);
421 add_trace("cause", "value", "%d", mncc->cause.value);
422 add_trace("reason", NULL, "callref already in use");
424 send_and_free_mncc((struct gsm_network *)gsm->network, mncc->msg_type, mncc);
425 new_state(PORT_STATE_RELEASE);
429 p_m_g_callref = callref;
432 /* if blocked, release call with MT_RELEASE_COMPLETE */
433 if (p_m_mISDNport->ifport->block) {
434 mncc = create_mncc(MNCC_REJ_REQ, p_m_g_callref);
435 gsm_trace_header(p_m_mISDNport, this, MNCC_REJ_REQ, DIRECTION_OUT);
436 mncc->fields |= MNCC_F_CAUSE;
437 mncc->cause.coding = 3;
438 mncc->cause.location = 1;
439 mncc->cause.value = 27;
440 add_trace("cause", "coding", "%d", mncc->cause.coding);
441 add_trace("cause", "location", "%d", mncc->cause.location);
442 add_trace("cause", "value", "%d", mncc->cause.value);
443 add_trace("reason", NULL, "port is blocked");
445 send_and_free_mncc((struct gsm_network *)gsm->network, mncc->msg_type, mncc);
446 new_state(PORT_STATE_RELEASE);
453 p_callerinfo.present = INFO_PRESENT_RESTRICTED;
455 p_callerinfo.present = INFO_PRESENT_ALLOWED;
456 if (mncc->calling.number[0])
457 SCPY(p_callerinfo.id, mncc->calling.number);
459 p_callerinfo.present = INFO_PRESENT_NOTAVAIL;
460 SCPY(p_callerinfo.imsi, mncc->imsi);
461 p_callerinfo.screen = INFO_SCREEN_NETWORK;
462 p_callerinfo.ntype = INFO_NTYPE_UNKNOWN;
463 p_callerinfo.isdn_port = p_m_portnum;
464 SCPY(p_callerinfo.interface, p_m_mISDNport->ifport->interface->name);
466 /* dialing information */
467 SCAT(p_dialinginfo.id, mncc->called.number);
468 switch (mncc->called.type) {
470 p_dialinginfo.ntype = INFO_NTYPE_INTERNATIONAL;
473 p_dialinginfo.ntype = INFO_NTYPE_NATIONAL;
476 p_dialinginfo.ntype = INFO_NTYPE_SUBSCRIBER;
479 p_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
482 if (mncc->emergency) {
483 SCPY(p_dialinginfo.id, "emergency");
485 p_dialinginfo.sending_complete = 1;
487 /* bearer capability */
489 p_capainfo.bearer_capa = INFO_BC_SPEECH;
490 p_capainfo.bearer_info1 = (options.law=='a')?3:2;
491 p_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
492 p_capainfo.source_mode = B_MODE_TRANSPARENT;
493 p_m_g_mode = p_capainfo.source_mode;
498 ret = channel = hunt_bchannel();
503 ret = seize_bchannel(channel, 1);
506 mncc = create_mncc(MNCC_REJ_REQ, p_m_g_callref);
507 gsm_trace_header(p_m_mISDNport, 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 = 34;
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, "no channel");
517 send_and_free_mncc((struct gsm_network *)gsm->network, mncc->msg_type, mncc);
518 new_state(PORT_STATE_RELEASE);
522 bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE);
523 if (bchannel_open(p_m_b_index))
526 /* what infos did we got ... */
527 gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
528 if (p_callerinfo.id[0])
529 add_trace("calling", "number", "%s", p_callerinfo.id);
531 SPRINT(p_callerinfo.id, "imsi-%s", p_callerinfo.imsi);
532 add_trace("calling", "imsi", "%s", p_callerinfo.imsi);
533 add_trace("dialing", "number", "%s", p_dialinginfo.id);
536 /* create endpoint */
538 FATAL("Incoming call but already got an endpoint.\n");
539 if (!(epoint = new Endpoint(p_serial, 0)))
540 FATAL("No memory for Endpoint instance\n");
541 if (!(epoint->ep_app = new DEFAULT_ENDPOINT_APP(epoint, 0))) //incoming
542 FATAL("No memory for Endpoint Application instance\n");
543 epointlist_new(epoint->ep_serial);
545 /* modify lchan to GSM codec V1 */
546 gsm_trace_header(p_m_mISDNport, this, MNCC_LCHAN_MODIFY, DIRECTION_OUT);
547 mode = create_mncc(MNCC_LCHAN_MODIFY, p_m_g_callref);
548 mode->lchan_mode = 0x01; /* GSM V1 */
549 add_trace("mode", NULL, "0x%02x", mode->lchan_mode);
551 send_and_free_mncc((struct gsm_network *)gsm->network, mode->msg_type, mode);
553 /* send call proceeding */
554 gsm_trace_header(p_m_mISDNport, this, MNCC_CALL_PROC_REQ, DIRECTION_OUT);
555 proceeding = create_mncc(MNCC_CALL_PROC_REQ, p_m_g_callref);
556 if (p_m_mISDNport->tones) {
557 proceeding->fields |= MNCC_F_PROGRESS;
558 proceeding->progress.coding = 3; /* GSM */
559 proceeding->progress.location = 1;
560 proceeding->progress.descr = 8;
561 add_trace("progress", "coding", "%d", proceeding->progress.coding);
562 add_trace("progress", "location", "%d", proceeding->progress.location);
563 add_trace("progress", "descr", "%d", proceeding->progress.descr);
566 send_and_free_mncc((struct gsm_network *)gsm->network, proceeding->msg_type, proceeding);
568 new_state(PORT_STATE_IN_PROCEEDING);
570 if (p_m_mISDNport->tones && !p_m_g_tch_connected) { /* only if ... */
571 gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
573 frame = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
574 send_and_free_mncc((struct gsm_network *)gsm->network, frame->msg_type, frame);
575 p_m_g_tch_connected = 1;
578 /* send setup message to endpoit */
579 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_SETUP);
580 message->param.setup.isdn_port = p_m_portnum;
581 message->param.setup.port_type = p_type;
582 // message->param.setup.dtmf = 0;
583 memcpy(&message->param.setup.dialinginfo, &p_dialinginfo, sizeof(struct dialing_info));
584 memcpy(&message->param.setup.callerinfo, &p_callerinfo, sizeof(struct caller_info));
585 memcpy(&message->param.setup.capainfo, &p_capainfo, sizeof(struct capa_info));
586 SCPY((char *)message->param.setup.useruser.data, (char *)mncc->useruser.info);
587 message->param.setup.useruser.len = strlen(mncc->useruser.info);
588 message->param.setup.useruser.protocol = mncc->useruser.proto;
589 message_put(message);
592 /* DTMF INDICATION */
593 void Pgsm::start_dtmf_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
595 struct lcr_msg *message;
596 struct gsm_mncc *resp;
598 gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
599 add_trace("keypad", NULL, "%c", mncc->keypad);
601 SPRINT(p_dialinginfo.id, "%c", mncc->keypad);
602 p_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
605 gsm_trace_header(p_m_mISDNport, this, MNCC_START_DTMF_RSP, DIRECTION_OUT);
606 add_trace("keypad", NULL, "%c", mncc->keypad);
608 resp = create_mncc(MNCC_START_DTMF_RSP, p_m_g_callref);
609 resp->keypad = mncc->keypad;
610 send_and_free_mncc((struct gsm_network *)gsm->network, resp->msg_type, resp);
612 /* send dialing information */
613 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_INFORMATION);
614 memcpy(&message->param.information, &p_dialinginfo, sizeof(struct dialing_info));
615 message_put(message);
617 void Pgsm::stop_dtmf_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
619 struct gsm_mncc *resp;
621 gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
622 add_trace("keypad", NULL, "%c", mncc->keypad);
626 gsm_trace_header(p_m_mISDNport, this, MNCC_STOP_DTMF_RSP, DIRECTION_OUT);
627 add_trace("keypad", NULL, "%c", mncc->keypad);
629 resp = create_mncc(MNCC_STOP_DTMF_RSP, p_m_g_callref);
630 resp->keypad = mncc->keypad;
631 send_and_free_mncc((struct gsm_network *)gsm->network, resp->msg_type, resp);
634 /* PROCEEDING INDICATION */
635 void Pgsm::call_conf_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
637 struct gsm_mncc *mode;
639 gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
640 if (mncc->fields & MNCC_F_CAUSE) {
641 add_trace("cause", "coding", "%d", mncc->cause.coding);
642 add_trace("cause", "location", "%", mncc->cause.location);
643 add_trace("cause", "value", "%", mncc->cause.value);
647 /* modify lchan to GSM codec V1 */
648 gsm_trace_header(p_m_mISDNport, this, MNCC_LCHAN_MODIFY, DIRECTION_OUT);
649 mode = create_mncc(MNCC_LCHAN_MODIFY, p_m_g_callref);
650 mode->lchan_mode = 0x01; /* GSM V1 */
651 add_trace("mode", NULL, "0x%02x", mode->lchan_mode);
653 send_and_free_mncc((struct gsm_network *)gsm->network, mode->msg_type, mode);
657 /* ALERTING INDICATION */
658 void Pgsm::alert_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
660 struct lcr_msg *message;
662 gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
665 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_ALERTING);
666 message_put(message);
668 new_state(PORT_STATE_OUT_ALERTING);
672 /* CONNECT INDICATION */
673 void Pgsm::setup_cnf(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
675 struct gsm_mncc *resp, *frame;
676 struct lcr_msg *message;
678 SCPY(p_connectinfo.id, mncc->connected.number);
679 SCPY(p_connectinfo.imsi, mncc->imsi);
680 p_connectinfo.present = INFO_PRESENT_ALLOWED;
681 p_connectinfo.screen = INFO_SCREEN_NETWORK;
682 p_connectinfo.ntype = INFO_NTYPE_UNKNOWN;
683 p_connectinfo.isdn_port = p_m_portnum;
684 SCPY(p_connectinfo.interface, p_m_mISDNport->ifport->interface->name);
686 gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
687 if (p_connectinfo.id[0])
688 add_trace("connect", "number", "%s", p_connectinfo.id);
689 else if (mncc->imsi[0])
690 SPRINT(p_connectinfo.id, "imsi-%s", p_connectinfo.imsi);
692 add_trace("connect", "imsi", "%s", p_connectinfo.imsi);
696 gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_COMPL_REQ, DIRECTION_OUT);
697 resp = create_mncc(MNCC_SETUP_COMPL_REQ, p_m_g_callref);
699 send_and_free_mncc((struct gsm_network *)gsm->network, resp->msg_type, resp);
701 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CONNECT);
702 memcpy(&message->param.connectinfo, &p_connectinfo, sizeof(struct connect_info));
703 message_put(message);
705 new_state(PORT_STATE_CONNECT);
707 if (!p_m_g_tch_connected) { /* only if ... */
708 gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
710 frame = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
711 send_and_free_mncc((struct gsm_network *)gsm->network, frame->msg_type, frame);
712 p_m_g_tch_connected = 1;
716 /* CONNECT ACK INDICATION */
717 void Pgsm::setup_compl_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
719 struct gsm_mncc *frame;
721 gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
724 new_state(PORT_STATE_CONNECT);
726 if (!p_m_g_tch_connected) { /* only if ... */
727 gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
729 frame = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
730 send_and_free_mncc((struct gsm_network *)gsm->network, frame->msg_type, frame);
731 p_m_g_tch_connected = 1;
735 /* DISCONNECT INDICATION */
736 void Pgsm::disc_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
738 struct lcr_msg *message;
739 int cause = 16, location = 0;
740 struct gsm_mncc *resp;
742 gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
743 if (mncc->fields & MNCC_F_CAUSE) {
744 location = mncc->cause.location;
745 cause = mncc->cause.value;
746 add_trace("cause", "coding", "%d", mncc->cause.coding);
747 add_trace("cause", "location", "%d", location);
748 add_trace("cause", "value", "%d", cause);
753 resp = create_mncc(MNCC_REL_REQ, p_m_g_callref);
754 gsm_trace_header(p_m_mISDNport, this, MNCC_REL_REQ, DIRECTION_OUT);
756 resp->fields |= MNCC_F_CAUSE;
757 resp->cause.coding = 3;
758 resp->cause.location = 1;
759 resp->cause.value = cause;
760 add_trace("cause", "coding", "%d", resp->cause.coding);
761 add_trace("cause", "location", "%d", resp->cause.location);
762 add_trace("cause", "value", "%d", resp->cause.value);
765 send_and_free_mncc((struct gsm_network *)gsm->network, resp->msg_type, resp);
767 /* sending release to endpoint */
768 while(p_epointlist) {
769 message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
770 message->param.disconnectinfo.cause = cause;
771 message->param.disconnectinfo.location = location;
772 message_put(message);
774 free_epointlist(p_epointlist);
776 new_state(PORT_STATE_RELEASE);
780 /* CC_RELEASE INDICATION */
781 void Pgsm::rel_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
783 int location = 0, cause = 16;
784 struct lcr_msg *message;
786 gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
787 if (mncc->fields & MNCC_F_CAUSE) {
788 location = mncc->cause.location;
789 cause = mncc->cause.value;
790 add_trace("cause", "coding", "%d", mncc->cause.coding);
791 add_trace("cause", "location", "%d", mncc->cause.location);
792 add_trace("cause", "value", "%d", mncc->cause.value);
796 /* sending release to endpoint */
797 while(p_epointlist) {
798 message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
799 message->param.disconnectinfo.cause = cause;
800 message->param.disconnectinfo.location = location;
801 message_put(message);
803 free_epointlist(p_epointlist);
805 new_state(PORT_STATE_RELEASE);
809 /* NOTIFY INDICATION */
810 void Pgsm::notify_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
812 gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
817 /* HOLD INDICATION */
818 void Pgsm::hold_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
820 struct lcr_msg *message;
821 struct gsm_mncc *resp, *frame;
823 gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
826 /* notify the hold of call */
827 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_NOTIFY);
828 message->param.notifyinfo.notify = INFO_NOTIFY_REMOTE_HOLD;
829 message->param.notifyinfo.local = 1; /* call is held by supplementary service */
830 message_put(message);
832 /* acknowledge hold */
833 gsm_trace_header(p_m_mISDNport, this, MNCC_HOLD_CNF, DIRECTION_OUT);
835 resp = create_mncc(MNCC_HOLD_CNF, p_m_g_callref);
836 send_and_free_mncc((struct gsm_network *)gsm->network, resp->msg_type, resp);
839 if (p_m_g_tch_connected) { /* it should be true */
840 gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_DROP, DIRECTION_OUT);
842 frame = create_mncc(MNCC_FRAME_DROP, p_m_g_callref);
843 send_and_free_mncc((struct gsm_network *)gsm->network, frame->msg_type, frame);
844 p_m_g_tch_connected = 0;
849 /* RETRIEVE INDICATION */
850 void Pgsm::retr_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
852 struct lcr_msg *message;
853 struct gsm_mncc *resp, *frame;
855 gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
858 /* notify the retrieve of call */
859 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_NOTIFY);
860 message->param.notifyinfo.notify = INFO_NOTIFY_REMOTE_RETRIEVAL;
861 message->param.notifyinfo.local = 1; /* call is retrieved by supplementary service */
862 message_put(message);
864 /* acknowledge retr */
865 gsm_trace_header(p_m_mISDNport, this, MNCC_RETRIEVE_CNF, DIRECTION_OUT);
867 resp = create_mncc(MNCC_RETRIEVE_CNF, p_m_g_callref);
868 send_and_free_mncc((struct gsm_network *)gsm->network, resp->msg_type, resp);
871 if (!p_m_g_tch_connected) { /* it should be true */
872 gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
874 frame = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
875 send_and_free_mncc((struct gsm_network *)gsm->network, frame->msg_type, frame);
876 p_m_g_tch_connected = 1;
881 * BSC sends message to port
883 static int message_bsc(struct gsm_network *net, int msg_type, void *arg)
885 struct gsm_mncc *mncc = (struct gsm_mncc *)arg;
886 unsigned int callref = mncc->callref;
888 class Pgsm *pgsm = NULL;
890 struct mISDNport *mISDNport;
892 /* Special messages */
897 callref = mncc->callref;
900 if ((port->p_type & PORT_CLASS_mISDN_MASK) == PORT_CLASS_mISDN_GSM) {
901 pgsm = (class Pgsm *)port;
902 if (pgsm->p_m_g_callref == callref) {
909 if (msg_type == GSM_TRAU_FRAME) {
911 pgsm->trau_receive((struct gsm_trau_frame *)arg);
916 if (msg_type != MNCC_SETUP_IND)
919 mISDNport = mISDNport_first;
923 mISDNport = mISDNport->next;
926 struct gsm_mncc *rej;
928 rej = create_mncc(MNCC_REJ_REQ, callref);
929 rej->fields |= MNCC_F_CAUSE;
930 rej->cause.coding = 3;
931 rej->cause.location = 1;
932 rej->cause.value = 27;
933 gsm_trace_header(NULL, NULL, MNCC_REJ_REQ, DIRECTION_OUT);
934 add_trace("cause", "coding", "%d", rej->cause.coding);
935 add_trace("cause", "location", "%d", rej->cause.location);
936 add_trace("cause", "value", "%d", rej->cause.value);
938 send_and_free_mncc((struct gsm_network *)gsm->network, rej->msg_type, rej);
941 /* creating port object, transparent until setup with hdlc */
942 SPRINT(name, "%s-%d-in", mISDNport->ifport->interface->name, mISDNport->portnum);
943 if (!(pgsm = new Pgsm(PORT_TYPE_GSM_IN, mISDNport, name, NULL, 0, 0, B_MODE_TRANSPARENT)))
945 FATAL("Cannot create Port instance.\n");
950 pgsm->setup_ind(msg_type, callref, mncc);
953 case MNCC_START_DTMF_IND:
954 pgsm->start_dtmf_ind(msg_type, callref, mncc);
957 case MNCC_STOP_DTMF_IND:
958 pgsm->stop_dtmf_ind(msg_type, callref, mncc);
961 case MNCC_CALL_CONF_IND:
962 pgsm->call_conf_ind(msg_type, callref, mncc);
966 pgsm->alert_ind(msg_type, callref, mncc);
970 pgsm->setup_cnf(msg_type, callref, mncc);
973 case MNCC_SETUP_COMPL_IND:
974 pgsm->setup_compl_ind(msg_type, callref, mncc);
978 pgsm->disc_ind(msg_type, callref, mncc);
984 pgsm->rel_ind(msg_type, callref, mncc);
987 case MNCC_NOTIFY_IND:
988 pgsm->notify_ind(msg_type, callref, mncc);
992 pgsm->hold_ind(msg_type, callref, mncc);
995 case MNCC_RETRIEVE_IND:
996 pgsm->retr_ind(msg_type, callref, mncc);
1000 PDEBUG(DEBUG_GSM, "Pgsm(%s) gsm port with (caller id %s) received unhandled nessage: 0x%x\n", pgsm->p_name, pgsm->p_callerinfo.id, msg_type);
1006 void Pgsm::message_setup(unsigned int epoint_id, int message_id, union parameter *param)
1008 struct lcr_msg *message;
1010 struct epoint_list *epointlist;
1011 struct gsm_mncc *mncc;
1014 /* copy setup infos to port */
1015 memcpy(&p_callerinfo, ¶m->setup.callerinfo, sizeof(p_callerinfo));
1016 memcpy(&p_dialinginfo, ¶m->setup.dialinginfo, sizeof(p_dialinginfo));
1017 memcpy(&p_capainfo, ¶m->setup.capainfo, sizeof(p_capainfo));
1018 memcpy(&p_redirinfo, ¶m->setup.redirinfo, sizeof(p_redirinfo));
1021 if (!p_dialinginfo.id[0]) {
1022 gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
1023 add_trace("failure", NULL, "No dialed subscriber given.");
1025 message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
1026 message->param.disconnectinfo.cause = 28;
1027 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1028 message_put(message);
1029 new_state(PORT_STATE_RELEASE);
1034 /* release if port is blocked */
1035 if (p_m_mISDNport->ifport->block) {
1036 gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
1037 add_trace("failure", NULL, "Port blocked.");
1039 message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
1040 message->param.disconnectinfo.cause = 27; // temp. unavail.
1041 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1042 message_put(message);
1043 new_state(PORT_STATE_RELEASE);
1049 ret = channel = hunt_bchannel();
1053 ret = seize_bchannel(channel, 1);
1056 gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
1057 add_trace("failure", NULL, "No internal audio channel available.");
1059 message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
1060 message->param.disconnectinfo.cause = 34;
1061 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1062 message_put(message);
1063 new_state(PORT_STATE_RELEASE);
1067 bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE);
1068 if (bchannel_open(p_m_b_index))
1071 // SCPY(&p_m_tones_dir, param->setup.ext.tones_dir);
1072 /* screen outgoing caller id */
1073 do_screen(1, p_callerinfo.id, sizeof(p_callerinfo.id), &p_callerinfo.ntype, &p_callerinfo.present, p_m_mISDNport->ifport->interface);
1075 /* attach only if not already */
1076 epointlist = p_epointlist;
1078 if (epointlist->epoint_id == epoint_id)
1080 epointlist = epointlist->next;
1083 epointlist_new(epoint_id);
1086 l1l2l3_trace_header(p_m_mISDNport, this, L3_NEW_L3ID_REQ, DIRECTION_OUT);
1087 p_m_g_callref = new_callref++;
1088 add_trace("callref", "new", "0x%x", p_m_g_callref);
1091 gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
1092 mncc = create_mncc(MNCC_SETUP_REQ, p_m_g_callref);
1093 /* caller information */
1094 mncc->fields |= MNCC_F_CALLING;
1095 mncc->calling.plan = 1;
1096 switch (p_callerinfo.ntype) {
1097 case INFO_NTYPE_UNKNOWN:
1098 mncc->calling.type = 0x0;
1100 case INFO_NTYPE_INTERNATIONAL:
1101 mncc->calling.type = 0x1;
1103 case INFO_NTYPE_NATIONAL:
1104 mncc->calling.type = 0x2;
1106 case INFO_NTYPE_SUBSCRIBER:
1107 mncc->calling.type = 0x4;
1109 default: /* INFO_NTYPE_NOTPRESENT */
1110 mncc->fields &= ~MNCC_F_CALLING;
1113 switch (p_callerinfo.screen) {
1114 case INFO_SCREEN_USER:
1115 mncc->calling.screen = 0;
1117 default: /* INFO_SCREEN_NETWORK */
1118 mncc->calling.screen = 3;
1121 switch (p_callerinfo.present) {
1122 case INFO_PRESENT_ALLOWED:
1123 mncc->calling.present = 0;
1125 case INFO_PRESENT_RESTRICTED:
1126 mncc->calling.present = 1;
1128 default: /* INFO_PRESENT_NOTAVAIL */
1129 mncc->calling.present = 2;
1132 if (mncc->fields & MNCC_F_CALLING) {
1133 SCPY(mncc->calling.number, p_callerinfo.id);
1134 add_trace("calling", "type", "%d", mncc->calling.type);
1135 add_trace("calling", "plan", "%d", mncc->calling.plan);
1136 add_trace("calling", "present", "%d", mncc->calling.present);
1137 add_trace("calling", "screen", "%d", mncc->calling.screen);
1138 add_trace("calling", "number", "%s", mncc->calling.number);
1140 /* dialing information */
1141 mncc->fields |= MNCC_F_CALLED;
1142 if (!strncmp(p_dialinginfo.id, "imsi-", 5)) {
1143 SCPY(mncc->imsi, p_dialinginfo.id+5);
1144 add_trace("dialing", "imsi", "%s", mncc->imsi);
1146 SCPY(mncc->called.number, p_dialinginfo.id);
1147 add_trace("dialing", "number", "%s", mncc->called.number);
1150 /* sending user-user */
1152 /* redirecting number */
1153 mncc->fields |= MNCC_F_REDIRECTING;
1154 mncc->redirecting.plan = 1;
1155 switch (p_redirinfo.ntype) {
1156 case INFO_NTYPE_UNKNOWN:
1157 mncc->redirecting.type = 0x0;
1159 case INFO_NTYPE_INTERNATIONAL:
1160 mncc->redirecting.type = 0x1;
1162 case INFO_NTYPE_NATIONAL:
1163 mncc->redirecting.type = 0x2;
1165 case INFO_NTYPE_SUBSCRIBER:
1166 mncc->redirecting.type = 0x4;
1168 default: /* INFO_NTYPE_NOTPRESENT */
1169 mncc->fields &= ~MNCC_F_REDIRECTING;
1172 switch (p_redirinfo.screen) {
1173 case INFO_SCREEN_USER:
1174 mncc->redirecting.screen = 0;
1176 default: /* INFO_SCREE_NETWORK */
1177 mncc->redirecting.screen = 3;
1180 switch (p_redirinfo.present) {
1181 case INFO_PRESENT_ALLOWED:
1182 mncc->redirecting.present = 0;
1184 case INFO_PRESENT_RESTRICTED:
1185 mncc->redirecting.present = 1;
1187 default: /* INFO_PRESENT_NOTAVAIL */
1188 mncc->redirecting.present = 2;
1191 /* sending redirecting number only in ntmode */
1192 if (mncc->fields & MNCC_F_REDIRECTING) {
1193 SCPY(mncc->redirecting.number, p_redirinfo.id);
1194 add_trace("redir", "type", "%d", mncc->redirecting.type);
1195 add_trace("redir", "plan", "%d", mncc->redirecting.plan);
1196 add_trace("redir", "present", "%d", mncc->redirecting.present);
1197 add_trace("redir", "screen", "%d", mncc->redirecting.screen);
1198 add_trace("redir", "number", "%s", mncc->redirecting.number);
1200 /* bearer capability */
1204 send_and_free_mncc((struct gsm_network *)gsm->network, mncc->msg_type, mncc);
1206 new_state(PORT_STATE_OUT_SETUP);
1208 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_PROCEEDING);
1209 message_put(message);
1211 new_state(PORT_STATE_OUT_PROCEEDING);
1214 /* MESSAGE_NOTIFY */
1215 void Pgsm::message_notify(unsigned int epoint_id, int message_id, union parameter *param)
1217 struct gsm_mncc *mncc;
1220 // printf("if = %d\n", param->notifyinfo.notify);
1221 if (param->notifyinfo.notify>INFO_NOTIFY_NONE) {
1222 notify = param->notifyinfo.notify & 0x7f;
1223 if (p_state!=PORT_STATE_CONNECT /*&& p_state!=PORT_STATE_IN_PROCEEDING*/ && p_state!=PORT_STATE_IN_ALERTING) {
1224 /* queue notification */
1225 if (p_m_g_notify_pending)
1226 message_free(p_m_g_notify_pending);
1227 p_m_g_notify_pending = message_create(ACTIVE_EPOINT(p_epointlist), p_serial, EPOINT_TO_PORT, message_id);
1228 memcpy(&p_m_g_notify_pending->param, param, sizeof(union parameter));
1230 /* sending notification */
1231 gsm_trace_header(p_m_mISDNport, this, MNCC_NOTIFY_REQ, DIRECTION_OUT);
1232 add_trace("notify", NULL, "%d", notify);
1234 mncc = create_mncc(MNCC_NOTIFY_REQ, p_m_g_callref);
1235 mncc->notify = notify;
1236 send_and_free_mncc((struct gsm_network *)gsm->network, mncc->msg_type, mncc);
1241 /* MESSAGE_ALERTING */
1242 void Pgsm::message_alerting(unsigned int epoint_id, int message_id, union parameter *param)
1244 struct gsm_mncc *mncc;
1247 gsm_trace_header(p_m_mISDNport, this, MNCC_ALERT_REQ, DIRECTION_OUT);
1248 mncc = create_mncc(MNCC_ALERT_REQ, p_m_g_callref);
1249 if (p_m_mISDNport->tones) {
1250 mncc->fields |= MNCC_F_PROGRESS;
1251 mncc->progress.coding = 3; /* GSM */
1252 mncc->progress.location = 1;
1253 mncc->progress.descr = 8;
1254 add_trace("progress", "coding", "%d", mncc->progress.coding);
1255 add_trace("progress", "location", "%d", mncc->progress.location);
1256 add_trace("progress", "descr", "%d", mncc->progress.descr);
1259 send_and_free_mncc((struct gsm_network *)gsm->network, mncc->msg_type, mncc);
1261 new_state(PORT_STATE_IN_ALERTING);
1263 if (p_m_mISDNport->tones && !p_m_g_tch_connected) { /* only if ... */
1264 gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
1266 mncc = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
1267 send_and_free_mncc((struct gsm_network *)gsm->network, mncc->msg_type, mncc);
1268 p_m_g_tch_connected = 1;
1272 /* MESSAGE_CONNECT */
1273 void Pgsm::message_connect(unsigned int epoint_id, int message_id, union parameter *param)
1275 struct gsm_mncc *mncc;
1277 /* copy connected information */
1278 memcpy(&p_connectinfo, ¶m->connectinfo, sizeof(p_connectinfo));
1279 /* screen outgoing caller id */
1280 do_screen(1, p_connectinfo.id, sizeof(p_connectinfo.id), &p_connectinfo.ntype, &p_connectinfo.present, p_m_mISDNport->ifport->interface);
1283 mncc = create_mncc(MNCC_SETUP_RSP, p_m_g_callref);
1284 gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_RSP, DIRECTION_OUT);
1285 /* caller information */
1286 mncc->fields |= MNCC_F_CONNECTED;
1287 mncc->connected.plan = 1;
1288 switch (p_callerinfo.ntype) {
1289 case INFO_NTYPE_UNKNOWN:
1290 mncc->connected.type = 0x0;
1292 case INFO_NTYPE_INTERNATIONAL:
1293 mncc->connected.type = 0x1;
1295 case INFO_NTYPE_NATIONAL:
1296 mncc->connected.type = 0x2;
1298 case INFO_NTYPE_SUBSCRIBER:
1299 mncc->connected.type = 0x4;
1301 default: /* INFO_NTYPE_NOTPRESENT */
1302 mncc->fields &= ~MNCC_F_CONNECTED;
1305 switch (p_callerinfo.screen) {
1306 case INFO_SCREEN_USER:
1307 mncc->connected.screen = 0;
1309 default: /* INFO_SCREEN_NETWORK */
1310 mncc->connected.screen = 3;
1313 switch (p_callerinfo.present) {
1314 case INFO_PRESENT_ALLOWED:
1315 mncc->connected.present = 0;
1317 case INFO_PRESENT_RESTRICTED:
1318 mncc->connected.present = 1;
1320 default: /* INFO_PRESENT_NOTAVAIL */
1321 mncc->connected.present = 2;
1324 if (mncc->fields & MNCC_F_CONNECTED) {
1325 SCPY(mncc->connected.number, p_connectinfo.id);
1326 add_trace("connected", "type", "%d", mncc->connected.type);
1327 add_trace("connected", "plan", "%d", mncc->connected.plan);
1328 add_trace("connected", "present", "%d", mncc->connected.present);
1329 add_trace("connected", "screen", "%d", mncc->connected.screen);
1330 add_trace("connected", "number", "%s", mncc->connected.number);
1333 send_and_free_mncc((struct gsm_network *)gsm->network, mncc->msg_type, mncc);
1335 new_state(PORT_STATE_CONNECT_WAITING);
1338 /* MESSAGE_DISCONNECT */
1339 void Pgsm::message_disconnect(unsigned int epoint_id, int message_id, union parameter *param)
1341 struct gsm_mncc *mncc;
1343 /* send disconnect */
1344 mncc = create_mncc(MNCC_DISC_REQ, p_m_g_callref);
1345 gsm_trace_header(p_m_mISDNport, this, MNCC_DISC_REQ, DIRECTION_OUT);
1346 if (p_m_mISDNport->tones) {
1347 mncc->fields |= MNCC_F_PROGRESS;
1348 mncc->progress.coding = 3; /* GSM */
1349 mncc->progress.location = 1;
1350 mncc->progress.descr = 8;
1351 add_trace("progress", "coding", "%d", mncc->progress.coding);
1352 add_trace("progress", "location", "%d", mncc->progress.location);
1353 add_trace("progress", "descr", "%d", mncc->progress.descr);
1355 mncc->fields |= MNCC_F_CAUSE;
1356 mncc->cause.coding = 3;
1357 mncc->cause.location = param->disconnectinfo.location;
1358 mncc->cause.value = param->disconnectinfo.cause;
1359 add_trace("cause", "coding", "%d", mncc->cause.coding);
1360 add_trace("cause", "location", "%d", mncc->cause.location);
1361 add_trace("cause", "value", "%d", mncc->cause.value);
1363 send_and_free_mncc((struct gsm_network *)gsm->network, mncc->msg_type, mncc);
1365 new_state(PORT_STATE_OUT_DISCONNECT);
1367 if (p_m_mISDNport->tones && !p_m_g_tch_connected) { /* only if ... */
1368 gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
1370 mncc = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
1371 send_and_free_mncc((struct gsm_network *)gsm->network, mncc->msg_type, mncc);
1372 p_m_g_tch_connected = 1;
1377 /* MESSAGE_RELEASE */
1378 void Pgsm::message_release(unsigned int epoint_id, int message_id, union parameter *param)
1380 struct gsm_mncc *mncc;
1383 mncc = create_mncc(MNCC_REL_REQ, p_m_g_callref);
1384 gsm_trace_header(p_m_mISDNport, this, MNCC_REL_REQ, DIRECTION_OUT);
1385 mncc->fields |= MNCC_F_CAUSE;
1386 mncc->cause.coding = 3;
1387 mncc->cause.location = param->disconnectinfo.location;
1388 mncc->cause.value = param->disconnectinfo.cause;
1389 add_trace("cause", "coding", "%d", mncc->cause.coding);
1390 add_trace("cause", "location", "%d", mncc->cause.location);
1391 add_trace("cause", "value", "%d", mncc->cause.value);
1393 send_and_free_mncc((struct gsm_network *)gsm->network, mncc->msg_type, mncc);
1395 new_state(PORT_STATE_RELEASE);
1402 * endpoint sends messages to the port
1404 int Pgsm::message_epoint(unsigned int epoint_id, int message_id, union parameter *param)
1406 if (PmISDN::message_epoint(epoint_id, message_id, param))
1409 switch(message_id) {
1410 case MESSAGE_SETUP: /* dial-out command received from epoint */
1411 if (p_state!=PORT_STATE_IDLE)
1413 message_setup(epoint_id, message_id, param);
1416 case MESSAGE_NOTIFY: /* display and notifications */
1417 message_notify(epoint_id, message_id, param);
1420 // case MESSAGE_FACILITY: /* facility message */
1421 // message_facility(epoint_id, message_id, param);
1424 case MESSAGE_PROCEEDING: /* message not handles */
1427 case MESSAGE_ALERTING: /* call of endpoint is ringing */
1428 if (p_state!=PORT_STATE_IN_PROCEEDING)
1430 message_alerting(epoint_id, message_id, param);
1431 if (p_m_g_notify_pending) {
1432 /* send pending notify message during connect */
1433 message_notify(ACTIVE_EPOINT(p_epointlist), p_m_g_notify_pending->type, &p_m_g_notify_pending->param);
1434 message_free(p_m_g_notify_pending);
1435 p_m_g_notify_pending = NULL;
1439 case MESSAGE_CONNECT: /* call of endpoint is connected */
1440 if (p_state!=PORT_STATE_IN_PROCEEDING
1441 && p_state!=PORT_STATE_IN_ALERTING)
1443 message_connect(epoint_id, message_id, param);
1444 if (p_m_g_notify_pending) {
1445 /* send pending notify message during connect */
1446 message_notify(ACTIVE_EPOINT(p_epointlist), p_m_g_notify_pending->type, &p_m_g_notify_pending->param);
1447 message_free(p_m_g_notify_pending);
1448 p_m_g_notify_pending = NULL;
1452 case MESSAGE_DISCONNECT: /* call has been disconnected */
1453 if (p_state!=PORT_STATE_IN_PROCEEDING
1454 && p_state!=PORT_STATE_IN_ALERTING
1455 && p_state!=PORT_STATE_OUT_SETUP
1456 && p_state!=PORT_STATE_OUT_OVERLAP
1457 && p_state!=PORT_STATE_OUT_PROCEEDING
1458 && p_state!=PORT_STATE_OUT_ALERTING
1459 && p_state!=PORT_STATE_CONNECT
1460 && p_state!=PORT_STATE_CONNECT_WAITING)
1462 message_disconnect(epoint_id, message_id, param);
1465 case MESSAGE_RELEASE: /* release isdn port */
1466 if (p_state==PORT_STATE_RELEASE)
1468 message_release(epoint_id, message_id, param);
1472 PDEBUG(DEBUG_GSM, "Pgsm(%s) gsm port with (caller id %s) received unhandled nessage: %d\n", p_name, p_callerinfo.id, message_id);
1482 int Pgsm::handler(void)
1486 unsigned char buffer[2048+MISDN_HEADER_LEN];
1487 struct mISDNhead *hh = (struct mISDNhead *)buffer;
1489 if ((ret = PmISDN::handler()))
1492 /* handle destruction */
1498 /* handle message from bchannel */
1499 if (p_m_g_gsm_b_sock > -1) {
1500 ret = recv(p_m_g_gsm_b_sock, buffer, sizeof(buffer), 0);
1501 if (ret >= (int)MISDN_HEADER_LEN) {
1503 /* we don't care about confirms, we use rx data to sync tx */
1506 /* we receive audio data, we respond to it AND we send tones */
1508 bchannel_receive(hh, buffer+MISDN_HEADER_LEN, ret-MISDN_HEADER_LEN);
1510 case PH_ACTIVATE_IND:
1511 p_m_g_gsm_b_active = 1;
1513 case PH_DEACTIVATE_IND:
1514 p_m_g_gsm_b_active = 0;
1519 if (ret < 0 && errno != EWOULDBLOCK)
1520 PERROR("Read from GSM port, index %d failed with return code %d\n", ret);
1529 * handles bsc select function within LCR's main loop
1531 int handle_gsm(void)
1535 ret1 = bsc_upqueue((struct gsm_network *)gsm->network);
1536 ret2 = bsc_select_main(1); /* polling */
1542 static void gsm_sock_close(void)
1544 if (gsm->gsm_sock > -1)
1545 close(gsm->gsm_sock);
1549 static int gsm_sock_open(char *portname)
1553 unsigned long on = 1;
1554 struct sockaddr_mISDN addr;
1555 struct mISDN_devinfo devinfo;
1558 /* check port counts */
1559 ret = ioctl(mISDNsocket, IMGETCOUNT, &cnt);
1561 fprintf(stderr, "Cannot get number of mISDN devices. (ioctl IMGETCOUNT failed ret=%d)\n", ret);
1566 PERROR_RUNTIME("Found no card. Please be sure to load card drivers.\n");
1569 gsm->gsm_port = mISDN_getportbyname(mISDNsocket, cnt, portname);
1570 if (gsm->gsm_port < 0) {
1571 PERROR_RUNTIME("Port name '%s' not found, did you load loopback interface for GSM?.\n", portname);
1572 return gsm->gsm_port;
1576 devinfo.id = gsm->gsm_port;
1577 ret = ioctl(mISDNsocket, IMGETDEVINFO, &devinfo);
1579 PERROR_RUNTIME("Cannot get device information for port %d. (ioctl IMGETDEVINFO failed ret=%d)\n", gsm->gsm_port, ret);
1582 if (devinfo.Dprotocols & (1 << ISDN_P_TE_S0)) {
1585 if (devinfo.Dprotocols & (1 << ISDN_P_TE_E1)) {
1589 PERROR_RUNTIME("GSM port %d does not support TE PRI or TE BRI.\n", gsm->gsm_port);
1592 if ((gsm->gsm_sock = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_TE_S0)) < 0) {
1593 PERROR_RUNTIME("GSM port %d failed to open socket.\n", gsm->gsm_port);
1595 return gsm->gsm_sock;
1597 /* set nonblocking io */
1598 if ((ret = ioctl(gsm->gsm_sock, FIONBIO, &on)) < 0) {
1599 PERROR_RUNTIME("GSM port %d failed to set socket into nonblocking io.\n", gsm->gsm_port);
1603 /* bind socket to dchannel */
1604 memset(&addr, 0, sizeof(addr));
1605 addr.family = AF_ISDN;
1606 addr.dev = gsm->gsm_port;
1608 if ((ret = bind(gsm->gsm_sock, (struct sockaddr *)&addr, sizeof(addr))) < 0) {
1609 PERROR_RUNTIME("GSM port %d failed to bind socket. (name = %s errno=%d)\n", gsm->gsm_port, portname, errno);
1618 int gsm_exit(int rc)
1620 /* free gsm instance */
1622 if (gsm->gsm_sock > -1)
1624 /* shutdown network */
1626 bsc_shutdown_net((struct gsm_network *)gsm->network);
1628 // if (gsm->network) {
1629 // free((struct gsm_network *)gsm->network); /* TBD */
1640 char hlr[128], cfg[128], filename[128];
1641 mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
1644 tall_bsc_ctx = talloc_named_const(NULL, 1, "openbsc");
1646 on_dso_load_token();
1652 /* create gsm instance */
1653 gsm = (struct lcr_gsm *)MALLOC(sizeof(struct lcr_gsm));
1657 if (!gsm_conf(&gsm->conf)) {
1658 PERROR("%s", gsm_conf_error);
1659 return gsm_exit(-EINVAL);
1663 if (gsm->conf.debug[0])
1664 debug_parse_category_mask(gsm->conf.debug);
1666 /* open pcap file */
1667 if (gsm->conf.pcapfile[0]) {
1668 if (gsm->conf.pcapfile[0] == '/')
1669 SCPY(filename, gsm->conf.pcapfile);
1671 SPRINT(filename, "%s/%s", CONFIG_DATA, gsm->conf.pcapfile);
1672 pcapfd = open(filename, O_WRONLY|O_TRUNC|O_CREAT, mode);
1674 PERROR("Failed to open file for pcap\n");
1675 return gsm_exit(-1);
1677 e1_set_pcap_fd(pcapfd);
1680 /* set reject cause */
1681 if (gsm->conf.reject_cause)
1682 gsm0408_set_reject_cause(gsm->conf.reject_cause);
1684 /* use RTP proxy for audio streaming */
1685 if (gsm->conf.rtp_proxy)
1686 ipacc_rtp_direct = 0;
1689 if (gsm->conf.hlr[0] == '/')
1690 SCPY(hlr, gsm->conf.hlr);
1692 SPRINT(hlr, "%s/%s", CONFIG_DATA, gsm->conf.hlr);
1694 PERROR("GSM DB: Failed to init database '%s'. Please check the option settings.\n", hlr);
1695 return gsm_exit(-1);
1697 printf("DB: Database initialized.\n");
1699 PERROR("GSM DB: Failed to prepare database.\n");
1700 return gsm_exit(-1);
1702 printf("DB: Database prepared.\n");
1704 /* bootstrap network */
1705 if (gsm->conf.openbsc_cfg[0] == '/')
1706 SCPY(cfg, gsm->conf.openbsc_cfg);
1708 SPRINT(cfg, "%s/%s", CONFIG_DATA, gsm->conf.openbsc_cfg);
1709 rc = bsc_bootstrap_network(&message_bsc, cfg);
1711 PERROR("Failed to bootstrap GSM network.\n");
1712 return gsm_exit(-1);
1714 gsm->network = bsc_gsmnet;
1716 /* open gsm loop interface */
1717 if (gsm_sock_open(gsm->conf.interface_bsc)) {
1718 return gsm_exit(-1);