1 /*****************************************************************************\
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg **
7 ** MNCC-Interface: Harald Welte **
11 \*****************************************************************************/
20 #include "gsm_audio.h"
25 #define SOCKET_RETRY_TIMER 5
27 //struct lcr_gsm *gsm = NULL;
31 /* names of MNCC-SAP */
32 static const struct _value_string {
36 { 0, "New call ref" },
37 { 1, "Codec negotiation" },
38 { MNCC_SETUP_REQ, "MNCC_SETUP_REQ" },
39 { MNCC_SETUP_IND, "MNCC_SETUP_IND" },
40 { MNCC_SETUP_RSP, "MNCC_SETUP_RSP" },
41 { MNCC_SETUP_CNF, "MNCC_SETUP_CNF" },
42 { MNCC_SETUP_COMPL_REQ, "MNCC_SETUP_COMPL_REQ" },
43 { MNCC_SETUP_COMPL_IND, "MNCC_SETUP_COMPL_IND" },
44 { MNCC_CALL_CONF_IND, "MNCC_CALL_CONF_IND" },
45 { MNCC_CALL_PROC_REQ, "MNCC_CALL_PROC_REQ" },
46 { MNCC_PROGRESS_REQ, "MNCC_PROGRESS_REQ" },
47 { MNCC_ALERT_REQ, "MNCC_ALERT_REQ" },
48 { MNCC_ALERT_IND, "MNCC_ALERT_IND" },
49 { MNCC_NOTIFY_REQ, "MNCC_NOTIFY_REQ" },
50 { MNCC_NOTIFY_IND, "MNCC_NOTIFY_IND" },
51 { MNCC_DISC_REQ, "MNCC_DISC_REQ" },
52 { MNCC_DISC_IND, "MNCC_DISC_IND" },
53 { MNCC_REL_REQ, "MNCC_REL_REQ" },
54 { MNCC_REL_IND, "MNCC_REL_IND" },
55 { MNCC_REL_CNF, "MNCC_REL_CNF" },
56 { MNCC_FACILITY_REQ, "MNCC_FACILITY_REQ" },
57 { MNCC_FACILITY_IND, "MNCC_FACILITY_IND" },
58 { MNCC_START_DTMF_IND, "MNCC_START_DTMF_IND" },
59 { MNCC_START_DTMF_RSP, "MNCC_START_DTMF_RSP" },
60 { MNCC_START_DTMF_REJ, "MNCC_START_DTMF_REJ" },
61 { MNCC_STOP_DTMF_IND, "MNCC_STOP_DTMF_IND" },
62 { MNCC_STOP_DTMF_RSP, "MNCC_STOP_DTMF_RSP" },
63 { MNCC_MODIFY_REQ, "MNCC_MODIFY_REQ" },
64 { MNCC_MODIFY_IND, "MNCC_MODIFY_IND" },
65 { MNCC_MODIFY_RSP, "MNCC_MODIFY_RSP" },
66 { MNCC_MODIFY_CNF, "MNCC_MODIFY_CNF" },
67 { MNCC_MODIFY_REJ, "MNCC_MODIFY_REJ" },
68 { MNCC_HOLD_IND, "MNCC_HOLD_IND" },
69 { MNCC_HOLD_CNF, "MNCC_HOLD_CNF" },
70 { MNCC_HOLD_REJ, "MNCC_HOLD_REJ" },
71 { MNCC_RETRIEVE_IND, "MNCC_RETRIEVE_IND" },
72 { MNCC_RETRIEVE_CNF, "MNCC_RETRIEVE_CNF" },
73 { MNCC_RETRIEVE_REJ, "MNCC_RETRIEVE_REJ" },
74 { MNCC_USERINFO_REQ, "MNCC_USERINFO_REQ" },
75 { MNCC_USERINFO_IND, "MNCC_USERINFO_IND" },
76 { MNCC_REJ_REQ, "MNCC_REJ_REQ" },
77 { MNCC_REJ_IND, "MNCC_REJ_IND" },
78 { MNCC_PROGRESS_IND, "MNCC_PROGRESS_IND" },
79 { MNCC_CALL_PROC_IND, "MNCC_CALL_PROC_IND" },
80 { MNCC_CALL_CONF_REQ, "MNCC_CALL_CONF_REQ" },
81 { MNCC_START_DTMF_REQ, "MNCC_START_DTMF_REQ" },
82 { MNCC_STOP_DTMF_REQ, "MNCC_STOP_DTMF_REQ" },
83 { MNCC_HOLD_REQ, "MNCC_HOLD_REQ " },
84 { MNCC_RETRIEVE_REQ, "MNCC_RETRIEVE_REQ" },
85 { MNCC_LCHAN_MODIFY, "MNCC_LCHAN_MODIFY" },
89 const char *mncc_name(int value)
93 while (mncc_names[i].name) {
94 if (mncc_names[i].msg_type == value)
95 return mncc_names[i].name;
101 static int mncc_send(struct lcr_gsm *lcr_gsm, int msg_type, void *data);
104 * create and send mncc message
106 struct gsm_mncc *create_mncc(int msg_type, unsigned int callref)
108 struct gsm_mncc *mncc;
110 mncc = (struct gsm_mncc *)MALLOC(sizeof(struct gsm_mncc));
111 mncc->msg_type = msg_type;
112 mncc->callref = callref;
115 int send_and_free_mncc(struct lcr_gsm *lcr_gsm, unsigned int msg_type, void *data)
120 ret = mncc_send(lcr_gsm, msg_type, data);
127 void Pgsm::send_mncc_rtp_connect(void)
129 struct gsm_mncc_rtp *nrtp;
131 nrtp = (struct gsm_mncc_rtp *) create_mncc(MNCC_RTP_CONNECT, p_g_callref);
132 nrtp->ip = p_g_rtp_ip_remote;
133 nrtp->port = p_g_rtp_port_remote;
134 switch (p_g_media_type) {
136 nrtp->payload_msg_type = GSM_TCHF_FRAME;
138 case MEDIA_TYPE_GSM_EFR:
139 nrtp->payload_msg_type = GSM_TCHF_FRAME_EFR;
142 nrtp->payload_msg_type = GSM_TCH_FRAME_AMR;
144 case MEDIA_TYPE_GSM_HR:
145 nrtp->payload_msg_type = GSM_TCHH_FRAME;
148 nrtp->payload_type = p_g_payload_type;
149 PDEBUG(DEBUG_GSM, "sending MNCC RTP connect with payload_msg_type=%x, payload_type=%d\n", nrtp->payload_msg_type, nrtp->payload_type);
150 send_and_free_mncc(p_g_lcr_gsm, nrtp->msg_type, nrtp);
153 static int delete_event(struct lcr_work *work, void *instance, int index);
158 Pgsm::Pgsm(int type, char *portname, struct port_settings *settings, struct interface *interface) : Port(type, portname, settings, interface)
161 if (interface->is_tones == IS_YES)
164 if (interface->is_earlyb == IS_YES)
167 if (interface->rtp_bridge)
169 p_g_rtp_payloads = 0;
170 memset(&p_g_samples, 0, sizeof(p_g_samples));
171 p_callerinfo.itype = (interface->extension)?INFO_ITYPE_ISDN_EXTENSION:INFO_ITYPE_ISDN;
172 memset(&p_g_delete, 0, sizeof(p_g_delete));
173 add_work(&p_g_delete, delete_event, this, 0);
178 p_g_gsm_b_index = -1;
179 p_g_gsm_b_active = 0;
180 p_g_notify_pending = NULL;
181 p_g_setup_pending = NULL;
182 p_g_connect_pending = NULL;
183 p_g_fr_decoder = NULL;
184 p_g_fr_encoder = NULL;
185 p_g_hr_decoder = NULL;
186 p_g_hr_encoder = NULL;
187 p_g_amr_decoder = NULL;
188 p_g_amr_encoder = NULL;
190 p_g_amr_cmr_valid = 0;
192 p_g_fr_decoder = gsm_fr_create();
193 p_g_fr_encoder = gsm_fr_create();
194 if (!p_g_fr_encoder || !p_g_fr_decoder) {
195 PERROR("Failed to create GSM FR codec instance\n");
196 trigger_work(&p_g_delete);
200 p_g_amr_decoder = gsm_amr_create();
201 p_g_amr_encoder = gsm_amr_create();
202 if (!p_g_amr_encoder || !p_g_amr_decoder) {
203 PERROR("Failed to create GSM AMR codec instance\n");
204 trigger_work(&p_g_delete);
208 p_g_tch_connected = 0;
211 PDEBUG(DEBUG_GSM, "Created new GSMPort(%s).\n", portname);
219 PDEBUG(DEBUG_GSM, "Destroyed GSM process(%s).\n", p_name);
221 del_work(&p_g_delete);
223 /* remove queued message */
224 if (p_g_notify_pending)
225 message_free(p_g_notify_pending);
226 if (p_g_setup_pending)
227 message_free(p_g_setup_pending);
228 if (p_g_connect_pending)
229 message_free(p_g_connect_pending);
234 gsm_fr_destroy(p_g_fr_encoder);
236 gsm_fr_destroy(p_g_fr_decoder);
241 gsm_amr_destroy(p_g_amr_encoder);
243 gsm_amr_destroy(p_g_amr_decoder);
248 /* receive encoded frame from gsm */
249 void Pgsm::frame_receive(void *arg)
251 struct gsm_data_frame *frame = (struct gsm_data_frame *)arg;
252 unsigned char data[160];
258 switch (frame->msg_type) {
260 if (p_g_media_type != MEDIA_TYPE_GSM) {
261 PERROR("FR frame, but current media type mismatches.\n");
264 if (!p_g_fr_decoder) {
265 PERROR("FR frame, but decoder not created.\n");
268 if ((frame->data[0]>>4) != 0xd) {
269 PDEBUG(DEBUG_GSM, "received GSM frame with wrong magig 0x%x\n", frame->data[0]>>4);
274 gsm_fr_decode(p_g_fr_decoder, frame->data, p_g_samples);
275 for (i = 0; i < 160; i++) {
276 data[i] = audio_s16_to_law[p_g_samples[i] & 0xffff];
280 case GSM_TCHF_FRAME_EFR:
281 if (p_g_media_type != MEDIA_TYPE_GSM_EFR) {
282 PERROR("EFR frame, but current media type mismatches.\n");
285 if (!p_g_amr_decoder) {
286 PERROR("EFR frame, but decoder not created.\n");
289 if ((frame->data[0]>>4) != 0xc)
293 gsm_efr_decode(p_g_amr_decoder, frame->data, p_g_samples);
294 for (i = 0; i < 160; i++) {
295 data[i] = audio_s16_to_law[p_g_samples[i] & 0xffff];
299 case GSM_TCH_FRAME_AMR:
300 if (p_g_media_type != MEDIA_TYPE_AMR) {
301 PERROR("AMR frame, but current media type mismatches.\n");
304 if (!p_g_amr_decoder) {
305 PERROR("AMR frame, but decoder not created.\n");
308 cmr = (frame->data[1] >> 4);
311 p_g_amr_cmr_valid = 1;
313 if (!(frame->data[2] & 0x04))
316 /* decode (skip length byte in front) */
317 gsm_amr_decode(p_g_amr_decoder, frame->data + 1, p_g_samples);
318 for (i = 0; i < 160; i++) {
319 data[i] = audio_s16_to_law[p_g_samples[i] & 0xffff];
327 /* beep on bad frame */
328 for (i = 0; i < 160; i++) {
330 p_g_samples[i] = 15000;
332 p_g_samples[i] = -15000;
333 data[i] = audio_s16_to_law[p_g_samples[i] & 0xffff];
336 /* repeat on bad frame */
337 for (i = 0; i < 160; i++) {
338 p_g_samples[i] = (p_g_samples[i] * 14) >> 4;
339 data[i] = audio_s16_to_law[p_g_samples[i] & 0xffff];
346 record(data, 160, 0); // from down
348 tap(data, 160, 0); // from down
352 bridge_rx(data, 160);
355 bridge_tx(data, 160);
358 /* send traffic to gsm */
359 int Pgsm::bridge_rx(unsigned char *data, int len)
364 return audio_send(data, len);
367 int Pgsm::audio_send(unsigned char *data, int len)
369 unsigned char frame[33];
374 record(data, len, 1); // from up
376 tap(data, len, 1); // from up
378 /* encoder init failed */
382 /* (currently) not connected, so don't flood tch! */
383 if (!p_g_tch_connected)
386 /* write to rx buffer */
388 p_g_rxdata[p_g_rxpos++] = audio_law_to_s32[*data++];
389 if (p_g_rxpos != 160)
393 switch (p_g_media_type) {
395 if (!p_g_fr_encoder) {
396 PERROR("FR frame, but encoder not created.\n");
401 gsm_fr_encode(p_g_fr_encoder, p_g_rxdata, frame);
402 frame_send(frame, 33, GSM_TCHF_FRAME);
405 case MEDIA_TYPE_GSM_EFR:
406 if (!p_g_amr_encoder) {
407 PERROR("EFR frame, but encoder not created.\n");
412 gsm_efr_encode(p_g_amr_encoder, p_g_rxdata, frame);
413 frame_send(frame, 31, GSM_TCHF_FRAME_EFR);
417 if (!p_g_amr_encoder) {
418 PERROR("AMR frame, but encoder not created.\n");
421 if (!p_g_amr_cmr_valid) {
422 PDEBUG(DEBUG_GSM, "no valid CMR yet.\n");
426 /* encode data (prefix a length byte) */
427 ret = gsm_amr_encode(p_g_amr_encoder, p_g_rxdata, frame + 1, p_g_amr_cmr);
429 frame_send(frame, ret + 1, GSM_TCH_FRAME_AMR);
438 void Pgsm::frame_send(void *_frame, int len, int msg_type)
440 unsigned char buffer[sizeof(struct gsm_data_frame) + len];
441 struct gsm_data_frame *frame = (struct gsm_data_frame *)buffer;
443 frame->msg_type = msg_type;
444 frame->callref = p_g_callref;
445 memcpy(frame->data, _frame, len);
448 mncc_send(p_g_lcr_gsm, frame->msg_type, frame);
455 void gsm_trace_header(const char *interface_name, class Pgsm *port, unsigned int msg_type, int direction)
458 struct interface *interface = interface_first;
460 interface = getinterfacebyname(interface_name);
464 /* select message and primitive text */
465 SCPY(msgtext, mncc_name(msg_type));
469 switch(port->p_type) {
470 case PORT_TYPE_GSM_BS_OUT:
471 case PORT_TYPE_GSM_BS_IN:
472 SCAT(msgtext, " LCR<->BSC");
474 case PORT_TYPE_GSM_MS_OUT:
475 case PORT_TYPE_GSM_MS_IN:
476 SCAT(msgtext, " LCR<->MS");
480 SCAT(msgtext, " ----");
482 /* init trace with given values */
485 port?numberrize_callerinfo(port->p_callerinfo.id, port->p_callerinfo.ntype, options.national, options.international):NULL,
486 port?port->p_dialinginfo.id:NULL,
489 port?port->p_serial:0,
493 /* modify lchan to given payload type */
494 void Pgsm::modify_lchan(int media_type)
496 struct gsm_mncc *mode;
498 /* already modified to that media type */
499 if (p_g_media_type == media_type)
502 p_g_media_type = media_type;
503 gsm_trace_header(p_interface_name, this, MNCC_LCHAN_MODIFY, DIRECTION_OUT);
504 mode = create_mncc(MNCC_LCHAN_MODIFY, p_g_callref);
505 switch (media_type) {
506 case MEDIA_TYPE_GSM_EFR:
507 add_trace("speech", "version", "EFR given");
508 mode->lchan_mode = 0x21; /* GSM V2 */
511 add_trace("speech", "version", "AMR given");
512 mode->lchan_mode = 0x41; /* GSM V3 */
515 add_trace("speech", "version", "Full/Half Rate given");
516 mode->lchan_mode = 0x01; /* GSM V1 */
518 mode->lchan_type = 0x02; /* FIXME: unused */
519 add_trace("mode", NULL, "0x%02x", mode->lchan_mode);
521 send_and_free_mncc(p_g_lcr_gsm, mode->msg_type, mode);
524 /* CALL PROCEEDING INDICATION (from network) */
525 void Pgsm::call_proc_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
527 struct lcr_msg *message;
528 struct gsm_mncc *frame;
530 gsm_trace_header(p_interface_name, this, msg_type, DIRECTION_IN);
533 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_PROCEEDING);
534 message_put(message);
536 new_state(PORT_STATE_OUT_PROCEEDING);
538 if (p_g_earlyb && !p_g_tch_connected) { /* only if ... */
539 gsm_trace_header(p_interface_name, this, MNCC_FRAME_RECV, DIRECTION_OUT);
541 frame = create_mncc(MNCC_FRAME_RECV, p_g_callref);
542 send_and_free_mncc(p_g_lcr_gsm, frame->msg_type, frame);
543 p_g_tch_connected = 1;
546 /* modify to GSM FR (this is GSM user side only, so there is FR supported only) */
547 modify_lchan(MEDIA_TYPE_GSM);
550 /* ALERTING INDICATION */
551 void Pgsm::alert_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
553 struct lcr_msg *message;
554 struct gsm_mncc *frame;
556 gsm_trace_header(p_interface_name, this, msg_type, DIRECTION_IN);
559 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_ALERTING);
560 message_put(message);
562 new_state(PORT_STATE_OUT_ALERTING);
564 if (p_g_earlyb && !p_g_tch_connected) { /* only if ... */
565 gsm_trace_header(p_interface_name, this, MNCC_FRAME_RECV, DIRECTION_OUT);
567 frame = create_mncc(MNCC_FRAME_RECV, p_g_callref);
568 send_and_free_mncc(p_g_lcr_gsm, frame->msg_type, frame);
569 p_g_tch_connected = 1;
572 /* modify to GSM FR, if not already */
573 if (!p_g_media_type) {
574 modify_lchan(MEDIA_TYPE_GSM);
578 /* CONNECT INDICATION */
579 void Pgsm::setup_cnf(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
581 struct gsm_mncc *resp, *frame;
582 struct lcr_msg *message;
584 SCPY(p_connectinfo.id, mncc->connected.number);
585 SCPY(p_connectinfo.imsi, mncc->imsi);
586 p_connectinfo.present = INFO_PRESENT_ALLOWED;
587 p_connectinfo.screen = INFO_SCREEN_NETWORK;
588 p_connectinfo.ntype = INFO_NTYPE_UNKNOWN;
589 SCPY(p_connectinfo.interface, p_interface_name);
591 gsm_trace_header(p_interface_name, this, msg_type, DIRECTION_IN);
592 if (p_connectinfo.id[0])
593 add_trace("connect", "number", "%s", p_connectinfo.id);
594 else if (mncc->imsi[0])
595 SPRINT(p_connectinfo.id, "imsi-%s", p_connectinfo.imsi);
597 add_trace("connect", "imsi", "%s", p_connectinfo.imsi);
601 gsm_trace_header(p_interface_name, this, MNCC_SETUP_COMPL_REQ, DIRECTION_OUT);
602 resp = create_mncc(MNCC_SETUP_COMPL_REQ, p_g_callref);
604 send_and_free_mncc(p_g_lcr_gsm, resp->msg_type, resp);
606 new_state(PORT_STATE_CONNECT);
608 if (!p_g_tch_connected) { /* only if ... */
609 gsm_trace_header(p_interface_name, this, MNCC_FRAME_RECV, DIRECTION_OUT);
611 frame = create_mncc(MNCC_FRAME_RECV, p_g_callref);
612 send_and_free_mncc(p_g_lcr_gsm, frame->msg_type, frame);
613 p_g_tch_connected = 1;
616 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CONNECT);
617 memcpy(&message->param.connectinfo, &p_connectinfo, sizeof(struct connect_info));
619 /* if we have a bridge, but not yet modified, the phone accepts out requested payload.
620 * we force the first in list */
621 if (p_g_rtp_bridge) {
622 if (!p_g_media_type) {
623 /* modify to first given type */
624 modify_lchan(p_g_rtp_media_types[0]);
625 /* also set payload type */
626 p_g_payload_type = p_g_rtp_payload_types[0];
628 message->param.connectinfo.rtpinfo.media_types[0] = p_g_media_type;
629 message->param.connectinfo.rtpinfo.payload_types[0] = p_g_payload_type;
630 message->param.connectinfo.rtpinfo.payloads = 1;
632 /* modify to GSM FR, if not already
633 * for network side, this should have been already happened */
635 modify_lchan(MEDIA_TYPE_GSM);
639 if (p_g_rtp_bridge) {
640 struct gsm_mncc_rtp *rtp;
642 PDEBUG(DEBUG_GSM, "Request RTP peer info, before forwarding connect msg\n");
643 p_g_connect_pending = message;
644 rtp = (struct gsm_mncc_rtp *) create_mncc(MNCC_RTP_CREATE, p_g_callref);
645 send_and_free_mncc(p_g_lcr_gsm, rtp->msg_type, rtp);
647 message_put(message);
650 /* CONNECT ACK INDICATION */
651 void Pgsm::setup_compl_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
653 struct gsm_mncc *frame;
655 gsm_trace_header(p_interface_name, this, msg_type, DIRECTION_IN);
658 new_state(PORT_STATE_CONNECT);
660 if (!p_g_tch_connected) { /* only if ... */
661 gsm_trace_header(p_interface_name, this, MNCC_FRAME_RECV, DIRECTION_OUT);
663 frame = create_mncc(MNCC_FRAME_RECV, p_g_callref);
664 send_and_free_mncc(p_g_lcr_gsm, frame->msg_type, frame);
665 p_g_tch_connected = 1;
669 /* DISCONNECT INDICATION */
670 void Pgsm::disc_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
672 struct lcr_msg *message;
673 int cause = 16, location = 0;
674 struct gsm_mncc *resp;
676 gsm_trace_header(p_interface_name, this, msg_type, DIRECTION_IN);
677 if (mncc->fields & MNCC_F_CAUSE) {
678 location = mncc->cause.location;
679 cause = mncc->cause.value;
680 add_trace("cause", "coding", "%d", mncc->cause.coding);
681 add_trace("cause", "location", "%d", location);
682 add_trace("cause", "value", "%d", cause);
687 resp = create_mncc(MNCC_REL_REQ, p_g_callref);
688 gsm_trace_header(p_interface_name, this, MNCC_REL_REQ, DIRECTION_OUT);
690 resp->fields |= MNCC_F_CAUSE;
691 resp->cause.coding = 3;
692 resp->cause.location = 1;
693 resp->cause.value = cause;
694 add_trace("cause", "coding", "%d", resp->cause.coding);
695 add_trace("cause", "location", "%d", resp->cause.location);
696 add_trace("cause", "value", "%d", resp->cause.value);
699 send_and_free_mncc(p_g_lcr_gsm, resp->msg_type, resp);
701 /* sending release to endpoint */
702 while(p_epointlist) {
703 message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
704 message->param.disconnectinfo.cause = cause;
705 message->param.disconnectinfo.location = location;
706 message_put(message);
708 free_epointlist(p_epointlist);
710 new_state(PORT_STATE_RELEASE);
711 trigger_work(&p_g_delete);
714 /* CC_RELEASE INDICATION */
715 void Pgsm::rel_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
717 int location = 0, cause = 16;
718 struct lcr_msg *message;
720 gsm_trace_header(p_interface_name, this, msg_type, DIRECTION_IN);
721 if (mncc->fields & MNCC_F_CAUSE) {
722 location = mncc->cause.location;
723 cause = mncc->cause.value;
724 add_trace("cause", "coding", "%d", mncc->cause.coding);
725 add_trace("cause", "location", "%d", mncc->cause.location);
726 add_trace("cause", "value", "%d", mncc->cause.value);
730 /* sending release to endpoint */
731 while(p_epointlist) {
732 message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
733 message->param.disconnectinfo.cause = cause;
734 message->param.disconnectinfo.location = location;
735 message_put(message);
737 free_epointlist(p_epointlist);
739 new_state(PORT_STATE_RELEASE);
740 trigger_work(&p_g_delete);
743 /* NOTIFY INDICATION */
744 void Pgsm::notify_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
746 struct lcr_msg *message;
748 gsm_trace_header(p_interface_name, this, msg_type, DIRECTION_IN);
749 add_trace("notify", NULL, "%d", mncc->notify);
752 message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_NOTIFY);
753 message->param.notifyinfo.notify = mncc->notify;
754 message_put(message);
758 void Pgsm::message_notify(unsigned int epoint_id, int message_id, union parameter *param)
760 struct gsm_mncc *mncc;
763 // printf("if = %d\n", param->notifyinfo.notify);
764 if (param->notifyinfo.notify>INFO_NOTIFY_NONE) {
765 notify = param->notifyinfo.notify & 0x7f;
766 if (p_state!=PORT_STATE_CONNECT /*&& p_state!=PORT_STATE_IN_PROCEEDING*/ && p_state!=PORT_STATE_IN_ALERTING) {
767 /* queue notification */
768 if (p_g_notify_pending)
769 message_free(p_g_notify_pending);
770 p_g_notify_pending = message_create(ACTIVE_EPOINT(p_epointlist), p_serial, EPOINT_TO_PORT, message_id);
771 memcpy(&p_g_notify_pending->param, param, sizeof(union parameter));
773 /* sending notification */
774 gsm_trace_header(p_interface_name, this, MNCC_NOTIFY_REQ, DIRECTION_OUT);
775 add_trace("notify", NULL, "%d", notify);
777 mncc = create_mncc(MNCC_NOTIFY_REQ, p_g_callref);
778 mncc->notify = notify;
779 send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
784 /* RTP create indication */
785 void Pgsm::rtp_create_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
787 struct gsm_mncc_rtp *rtp = (struct gsm_mncc_rtp *) mncc;
789 /* send queued setup, as we received remote RTP info */
790 if (p_g_setup_pending) {
791 struct lcr_msg *message;
793 message = p_g_setup_pending;
794 PDEBUG(DEBUG_GSM, "Got RTP peer info (%08x,%d) forwarding setup\n", rtp->ip, rtp->port);
795 message->param.setup.rtpinfo.ip = rtp->ip;
796 message->param.setup.rtpinfo.port = rtp->port;
797 message_put(message);
798 p_g_setup_pending = NULL;
800 if (p_g_connect_pending) {
801 PDEBUG(DEBUG_GSM, "Got RTP peer info (%08x,%d) connecting RTP... \n", rtp->ip, rtp->port);
802 send_mncc_rtp_connect();
806 /* RTP connect indication */
807 void Pgsm::rtp_connect_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
809 struct lcr_msg *message;
810 struct gsm_mncc_rtp *rtp = (struct gsm_mncc_rtp *) mncc;
812 if (p_g_connect_pending) {
813 message = p_g_connect_pending;
814 PDEBUG(DEBUG_GSM, "Got RTP peer info (%08x,%d) forwarding connect\n", rtp->ip, rtp->port);
815 message->param.connectinfo.rtpinfo.ip = rtp->ip;
816 message->param.connectinfo.rtpinfo.port = rtp->port;
817 message_put(message);
818 p_g_connect_pending = NULL;
822 /* MESSAGE_PROGRESS */
823 void Pgsm::message_progress(unsigned int epoint_id, int message_id, union parameter *param)
825 if (param->progressinfo.progress == 8) {
826 PDEBUG(DEBUG_GSM, "Remote provides tones for us\n");
830 if (param->progressinfo.rtpinfo.port) {
831 PDEBUG(DEBUG_GSM, "PROGRESS with RTP peer info, sent to BSC (%08x,%d) with media %d, pt %d\n", param->progressinfo.rtpinfo.ip, param->progressinfo.rtpinfo.port, param->progressinfo.rtpinfo.media_types[0], param->progressinfo.rtpinfo.payload_types[0]);
833 /* modify channel to givne type, also sets media type */
834 modify_lchan(param->progressinfo.rtpinfo.media_types[0]);
837 p_g_rtp_ip_remote = param->progressinfo.rtpinfo.ip;
838 p_g_rtp_port_remote = param->progressinfo.rtpinfo.port;
839 /* p_g_media_type is already set by modify_lchan() */
840 p_g_payload_type = param->progressinfo.rtpinfo.payload_types[0];
841 send_mncc_rtp_connect();
845 /* MESSAGE_ALERTING */
846 void Pgsm::message_alerting(unsigned int epoint_id, int message_id, union parameter *param)
848 struct gsm_mncc *mncc;
851 gsm_trace_header(p_interface_name, this, MNCC_ALERT_REQ, DIRECTION_OUT);
852 mncc = create_mncc(MNCC_ALERT_REQ, p_g_callref);
854 mncc->fields |= MNCC_F_PROGRESS;
855 mncc->progress.coding = 3; /* GSM */
856 mncc->progress.location = 1;
857 mncc->progress.descr = 8;
858 add_trace("progress", "coding", "%d", mncc->progress.coding);
859 add_trace("progress", "location", "%d", mncc->progress.location);
860 add_trace("progress", "descr", "%d", mncc->progress.descr);
863 send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
865 new_state(PORT_STATE_IN_ALERTING);
867 if (p_g_tones && !p_g_tch_connected) { /* only if ... */
868 gsm_trace_header(p_interface_name, this, MNCC_FRAME_RECV, DIRECTION_OUT);
870 mncc = create_mncc(MNCC_FRAME_RECV, p_g_callref);
871 send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
872 p_g_tch_connected = 1;
876 /* MESSAGE_CONNECT */
877 void Pgsm::message_connect(unsigned int epoint_id, int message_id, union parameter *param)
879 struct gsm_mncc *mncc;
881 /* copy connected information */
882 memcpy(&p_connectinfo, ¶m->connectinfo, sizeof(p_connectinfo));
883 /* screen outgoing caller id */
884 do_screen(1, p_connectinfo.id, sizeof(p_connectinfo.id), &p_connectinfo.ntype, &p_connectinfo.present, p_interface_name);
887 mncc = create_mncc(MNCC_SETUP_RSP, p_g_callref);
888 gsm_trace_header(p_interface_name, this, MNCC_SETUP_RSP, DIRECTION_OUT);
889 /* caller information */
890 mncc->fields |= MNCC_F_CONNECTED;
891 mncc->connected.plan = 1;
892 switch (p_callerinfo.ntype) {
893 case INFO_NTYPE_UNKNOWN:
894 mncc->connected.type = 0x0;
896 case INFO_NTYPE_INTERNATIONAL:
897 mncc->connected.type = 0x1;
899 case INFO_NTYPE_NATIONAL:
900 mncc->connected.type = 0x2;
902 case INFO_NTYPE_SUBSCRIBER:
903 mncc->connected.type = 0x4;
905 default: /* INFO_NTYPE_NOTPRESENT */
906 mncc->fields &= ~MNCC_F_CONNECTED;
909 switch (p_callerinfo.screen) {
910 case INFO_SCREEN_USER:
911 mncc->connected.screen = 0;
913 default: /* INFO_SCREEN_NETWORK */
914 mncc->connected.screen = 3;
917 switch (p_callerinfo.present) {
918 case INFO_PRESENT_ALLOWED:
919 mncc->connected.present = 0;
921 case INFO_PRESENT_RESTRICTED:
922 mncc->connected.present = 1;
924 default: /* INFO_PRESENT_NOTAVAIL */
925 mncc->connected.present = 2;
928 if (mncc->fields & MNCC_F_CONNECTED) {
929 SCPY(mncc->connected.number, p_connectinfo.id);
930 add_trace("connected", "type", "%d", mncc->connected.type);
931 add_trace("connected", "plan", "%d", mncc->connected.plan);
932 add_trace("connected", "present", "%d", mncc->connected.present);
933 add_trace("connected", "screen", "%d", mncc->connected.screen);
934 add_trace("connected", "number", "%s", mncc->connected.number);
937 send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
939 new_state(PORT_STATE_CONNECT_WAITING);
941 if (param->connectinfo.rtpinfo.port) {
942 PDEBUG(DEBUG_GSM, "CONNECT with RTP peer info, sent to BSC (%08x,%d)\n", param->connectinfo.rtpinfo.ip, param->connectinfo.rtpinfo.port);
944 /* modify channel to givne type, also sets media type */
945 modify_lchan(param->connectinfo.rtpinfo.media_types[0]);
948 p_g_rtp_ip_remote = param->connectinfo.rtpinfo.ip;
949 p_g_rtp_port_remote = param->connectinfo.rtpinfo.port;
950 /* p_g_media_type is already set by modify_lchan() */
951 p_g_payload_type = param->connectinfo.rtpinfo.payload_types[0];
952 send_mncc_rtp_connect();
956 /* MESSAGE_DISCONNECT */
957 void Pgsm::message_disconnect(unsigned int epoint_id, int message_id, union parameter *param)
959 struct gsm_mncc *mncc;
961 /* send disconnect */
962 mncc = create_mncc(MNCC_DISC_REQ, p_g_callref);
963 gsm_trace_header(p_interface_name, this, MNCC_DISC_REQ, DIRECTION_OUT);
965 mncc->fields |= MNCC_F_PROGRESS;
966 mncc->progress.coding = 3; /* GSM */
967 mncc->progress.location = 1;
968 mncc->progress.descr = 8;
969 add_trace("progress", "coding", "%d", mncc->progress.coding);
970 add_trace("progress", "location", "%d", mncc->progress.location);
971 add_trace("progress", "descr", "%d", mncc->progress.descr);
973 mncc->fields |= MNCC_F_CAUSE;
974 mncc->cause.coding = 3;
975 mncc->cause.location = param->disconnectinfo.location;
976 mncc->cause.value = param->disconnectinfo.cause;
977 add_trace("cause", "coding", "%d", mncc->cause.coding);
978 add_trace("cause", "location", "%d", mncc->cause.location);
979 add_trace("cause", "value", "%d", mncc->cause.value);
981 send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
983 new_state(PORT_STATE_OUT_DISCONNECT);
985 if (p_g_tones && !p_g_tch_connected) { /* only if ... */
986 gsm_trace_header(p_interface_name, this, MNCC_FRAME_RECV, DIRECTION_OUT);
988 mncc = create_mncc(MNCC_FRAME_RECV, p_g_callref);
989 send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
990 p_g_tch_connected = 1;
995 /* MESSAGE_RELEASE */
996 void Pgsm::message_release(unsigned int epoint_id, int message_id, union parameter *param)
998 struct gsm_mncc *mncc;
1001 mncc = create_mncc(MNCC_REL_REQ, p_g_callref);
1002 gsm_trace_header(p_interface_name, this, MNCC_REL_REQ, DIRECTION_OUT);
1003 mncc->fields |= MNCC_F_CAUSE;
1004 mncc->cause.coding = 3;
1005 mncc->cause.location = param->disconnectinfo.location;
1006 mncc->cause.value = param->disconnectinfo.cause;
1007 add_trace("cause", "coding", "%d", mncc->cause.coding);
1008 add_trace("cause", "location", "%d", mncc->cause.location);
1009 add_trace("cause", "value", "%d", mncc->cause.value);
1011 send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
1013 new_state(PORT_STATE_RELEASE);
1014 trigger_work(&p_g_delete);
1019 * endpoint sends messages to the port
1021 int Pgsm::message_epoint(unsigned int epoint_id, int message_id, union parameter *param)
1025 if (Port::message_epoint(epoint_id, message_id, param))
1028 switch(message_id) {
1029 case MESSAGE_NOTIFY: /* display and notifications */
1031 message_notify(epoint_id, message_id, param);
1034 // case MESSAGE_FACILITY: /* facility message */
1035 // message_facility(epoint_id, message_id, param);
1038 case MESSAGE_PROCEEDING: /* message not handles */
1042 case MESSAGE_PROGRESS:
1044 message_progress(epoint_id, message_id, param);
1047 case MESSAGE_ALERTING: /* call of endpoint is ringing */
1049 if (p_state!=PORT_STATE_IN_PROCEEDING)
1051 message_alerting(epoint_id, message_id, param);
1052 if (p_g_notify_pending) {
1053 /* send pending notify message during connect */
1054 message_notify(ACTIVE_EPOINT(p_epointlist), p_g_notify_pending->type, &p_g_notify_pending->param);
1055 message_free(p_g_notify_pending);
1056 p_g_notify_pending = NULL;
1060 case MESSAGE_CONNECT: /* call of endpoint is connected */
1062 if (p_state!=PORT_STATE_IN_PROCEEDING
1063 && p_state!=PORT_STATE_IN_ALERTING)
1065 message_connect(epoint_id, message_id, param);
1066 if (p_g_notify_pending) {
1067 /* send pending notify message during connect */
1068 message_notify(ACTIVE_EPOINT(p_epointlist), p_g_notify_pending->type, &p_g_notify_pending->param);
1069 message_free(p_g_notify_pending);
1070 p_g_notify_pending = NULL;
1074 case MESSAGE_DISCONNECT: /* call has been disconnected */
1076 if (p_state!=PORT_STATE_IN_PROCEEDING
1077 && p_state!=PORT_STATE_IN_ALERTING
1078 && p_state!=PORT_STATE_OUT_SETUP
1079 && p_state!=PORT_STATE_OUT_OVERLAP
1080 && p_state!=PORT_STATE_OUT_PROCEEDING
1081 && p_state!=PORT_STATE_OUT_ALERTING
1082 && p_state!=PORT_STATE_CONNECT
1083 && p_state!=PORT_STATE_CONNECT_WAITING)
1085 message_disconnect(epoint_id, message_id, param);
1088 case MESSAGE_RELEASE: /* release isdn port */
1090 if (p_state==PORT_STATE_RELEASE)
1092 message_release(epoint_id, message_id, param);
1100 /* deletes only if l3id is release, otherwhise it will be triggered then */
1101 static int delete_event(struct lcr_work *work, void *instance, int index)
1103 class Pgsm *gsmport = (class Pgsm *)instance;
1110 int gsm_exit(int rc)
1127 static int mncc_q_enqueue(struct lcr_gsm *lcr_gsm, struct gsm_mncc *mncc, unsigned int len)
1129 struct mncc_q_entry *qe;
1131 qe = (struct mncc_q_entry *) MALLOC(sizeof(*qe)+sizeof(*mncc)+len);
1137 memcpy(qe->data, mncc, len);
1139 /* in case of empty list ... */
1140 if (!lcr_gsm->mncc_q_hd && !lcr_gsm->mncc_q_tail) {
1141 /* the list head and tail both point to the new qe */
1142 lcr_gsm->mncc_q_hd = lcr_gsm->mncc_q_tail = qe;
1144 /* append to tail of list */
1145 lcr_gsm->mncc_q_tail->next = qe;
1146 lcr_gsm->mncc_q_tail = qe;
1149 lcr_gsm->mncc_lfd.when |= LCR_FD_WRITE;
1154 static struct mncc_q_entry *mncc_q_dequeue(struct lcr_gsm *lcr_gsm)
1156 struct mncc_q_entry *qe = lcr_gsm->mncc_q_hd;
1160 /* dequeue the successfully sent message */
1161 lcr_gsm->mncc_q_hd = qe->next;
1164 if (qe == lcr_gsm->mncc_q_tail)
1165 lcr_gsm->mncc_q_tail = NULL;
1170 /* routine called by LCR code if it wants to send a message to OpenBSC */
1171 static int mncc_send(struct lcr_gsm *lcr_gsm, int msg_type, void *data)
1175 /* FIXME: the caller should provide this */
1177 case GSM_TCHF_FRAME:
1178 len = sizeof(struct gsm_data_frame) + 33;
1181 len = sizeof(struct gsm_mncc);
1185 return mncc_q_enqueue(lcr_gsm, (struct gsm_mncc *)data, len);
1188 /* close MNCC socket */
1189 static int mncc_fd_close(struct lcr_gsm *lcr_gsm, struct lcr_fd *lfd)
1192 class Pgsm *pgsm = NULL;
1193 struct lcr_msg *message;
1195 PERROR("Lost MNCC socket, retrying in %u seconds\n", SOCKET_RETRY_TIMER);
1200 /* free all the calls that were running through the MNCC interface */
1203 if ((port->p_type & PORT_CLASS_mISDN_MASK) == PORT_CLASS_GSM) {
1204 pgsm = (class Pgsm *)port;
1205 if (pgsm->p_g_lcr_gsm == lcr_gsm) {
1206 message = message_create(pgsm->p_serial, ACTIVE_EPOINT(pgsm->p_epointlist), PORT_TO_EPOINT, MESSAGE_RELEASE);
1207 message->param.disconnectinfo.cause = 27; // temp. unavail.
1208 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1209 message_put(message);
1210 pgsm->new_state(PORT_STATE_RELEASE);
1211 trigger_work(&pgsm->p_g_delete);
1217 /* flush the queue */
1218 while (mncc_q_dequeue(lcr_gsm))
1221 /* start the re-connect timer */
1222 schedule_timer(&lcr_gsm->socket_retry, SOCKET_RETRY_TIMER, 0);
1227 /* write to OpenBSC via MNCC socket */
1228 static int mncc_fd_write(struct lcr_fd *lfd, void *inst, int idx)
1230 struct lcr_gsm *lcr_gsm = (struct lcr_gsm *) inst;
1231 struct mncc_q_entry *qe, *qe2;
1235 qe = lcr_gsm->mncc_q_hd;
1237 lfd->when &= ~LCR_FD_WRITE;
1240 rc = write(lfd->fd, qe->data, qe->len);
1242 return mncc_fd_close(lcr_gsm, lfd);
1245 if (rc < (int)qe->len)
1247 /* dequeue the successfully sent message */
1248 qe2 = mncc_q_dequeue(lcr_gsm);
1255 /* read from OpenBSC via MNCC socket */
1256 static int mncc_fd_read(struct lcr_fd *lfd, void *inst, int idx)
1258 struct lcr_gsm *lcr_gsm = (struct lcr_gsm *) inst;
1260 static char buf[sizeof(struct gsm_mncc)+1024];
1261 struct gsm_mncc *mncc_prim = (struct gsm_mncc *) buf;
1263 memset(buf, 0, sizeof(buf));
1264 rc = recv(lfd->fd, buf, sizeof(buf), 0);
1266 return mncc_fd_close(lcr_gsm, lfd);
1270 /* Hand the MNCC message into LCR */
1271 switch (lcr_gsm->type) {
1273 case LCR_GSM_TYPE_NETWORK:
1274 return message_bsc(lcr_gsm, mncc_prim->msg_type, mncc_prim);
1277 case LCR_GSM_TYPE_MS:
1278 return message_ms(lcr_gsm, mncc_prim->msg_type, mncc_prim);
1285 /* file descriptor callback if we can read or write form MNCC socket */
1286 static int mncc_fd_cb(struct lcr_fd *lfd, unsigned int what, void *inst, int idx)
1290 if (what & LCR_FD_READ)
1291 rc = mncc_fd_read(lfd, inst, idx);
1295 if (what & LCR_FD_WRITE)
1296 rc = mncc_fd_write(lfd, inst, idx);
1301 int mncc_socket_retry_cb(struct lcr_timer *timer, void *inst, int index)
1303 struct lcr_gsm *lcr_gsm = (struct lcr_gsm *) inst;
1306 lcr_gsm->mncc_lfd.fd = -1;
1308 fd = socket(PF_UNIX, SOCK_SEQPACKET, 0);
1310 PERROR("Cannot create SEQPACKET socket, giving up!\n");
1314 rc = connect(fd, (struct sockaddr *) &lcr_gsm->sun,
1315 sizeof(lcr_gsm->sun));
1317 PERROR("Could not connect to MNCC socket %s, "
1318 "retrying in %u seconds\n", lcr_gsm->sun.sun_path,
1319 SOCKET_RETRY_TIMER);
1321 schedule_timer(&lcr_gsm->socket_retry, SOCKET_RETRY_TIMER, 0);
1323 PDEBUG(DEBUG_GSM, "Connected to MNCC socket %s!\n", lcr_gsm->sun.sun_path);
1324 lcr_gsm->mncc_lfd.fd = fd;
1325 register_fd(&lcr_gsm->mncc_lfd, LCR_FD_READ, &mncc_fd_cb, lcr_gsm, 0);