Add support for TCH/H and half rate codec
[lcr.git] / gsm.cpp
1 /*****************************************************************************\
2 **                                                                           **
3 ** LCR                                                                       **
4 **                                                                           **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg                                              **
7 **            MNCC-Interface: Harald Welte                                   **
8 **                                                                           **
9 ** mISDN gsm                                                                 **
10 **                                                                           **
11 \*****************************************************************************/ 
12
13 #include "main.h"
14 #include "mncc.h"
15
16 #ifndef _GNU_SOURCE
17 #define _GNU_SOURCE
18 #endif
19 extern "C" {
20 #include "gsm_audio.h"
21 }
22
23 #include <assert.h>
24
25 #define SOCKET_RETRY_TIMER      5
26
27 //struct lcr_gsm *gsm = NULL;
28
29 int new_callref = 1;
30
31 /* names of MNCC-SAP */
32 static const struct _value_string {
33         int msg_type;
34         const char *name;
35 } mncc_names[] = {
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
86         { MNCC_LCHAN_MODIFY,    "MNCC_LCHAN_MODIFY" },
87
88         { MNCC_BRIDGE,          "MNCC_BRIDGE" },
89         { MNCC_FRAME_RECV,      "MNCC_FRAME_RECV" },
90         { MNCC_FRAME_DROP,      "MNCC_FRAME_DROP" },
91         { MNCC_RTP_CREATE,      "MNCC_RTP_CREATE" },
92         { MNCC_RTP_CONNECT,     "MNCC_RTP_CONNECT" },
93         { MNCC_RTP_FREE,        "MNCC_RTP_FREE" },
94
95         { 0,                    NULL }
96 };
97
98 const char *mncc_name(int value)
99 {
100         int i = 0;
101         static char ukn[32];
102
103         while (mncc_names[i].name) {
104                 if (mncc_names[i].msg_type == value)
105                         return mncc_names[i].name;
106                 i++;
107         }
108         SPRINT(ukn, "unknown(0x%x)", value);
109         return ukn;
110 }
111
112 static int mncc_send(struct lcr_gsm *lcr_gsm, int msg_type, void *data);
113
114 /*
115  * create and send mncc message
116  */
117 struct gsm_mncc *create_mncc(int msg_type, unsigned int callref)
118 {
119         struct gsm_mncc *mncc;
120
121         mncc = (struct gsm_mncc *)MALLOC(sizeof(struct gsm_mncc));
122         mncc->msg_type = msg_type;
123         mncc->callref = callref;
124         return (mncc);
125 }
126 int send_and_free_mncc(struct lcr_gsm *lcr_gsm, unsigned int msg_type, void *data)
127 {
128         int ret = 0;
129
130         if (lcr_gsm) {
131                 ret = mncc_send(lcr_gsm, msg_type, data);
132         }
133         free(data);
134
135         return ret;
136 }
137
138 void Pgsm::send_mncc_rtp_connect(void)
139 {
140         struct gsm_mncc_rtp *nrtp;
141
142         nrtp = (struct gsm_mncc_rtp *) create_mncc(MNCC_RTP_CONNECT, p_g_callref);
143         nrtp->ip = p_g_rtp_ip_remote;
144         nrtp->port = p_g_rtp_port_remote;
145         switch (p_g_media_type) {
146         case MEDIA_TYPE_GSM:
147                 nrtp->payload_msg_type = GSM_TCHF_FRAME;
148                 break;
149         case MEDIA_TYPE_GSM_EFR:
150                 nrtp->payload_msg_type = GSM_TCHF_FRAME_EFR;
151                 break;
152         case MEDIA_TYPE_AMR:
153                 nrtp->payload_msg_type = GSM_TCH_FRAME_AMR;
154                 break;
155         case MEDIA_TYPE_GSM_HR:
156                 nrtp->payload_msg_type = GSM_TCHH_FRAME;
157                 break;
158         }
159         nrtp->payload_type = p_g_payload_type;
160         PDEBUG(DEBUG_GSM, "sending MNCC RTP connect with payload_msg_type=%x, payload_type=%d\n", nrtp->payload_msg_type, nrtp->payload_type);
161         send_and_free_mncc(p_g_lcr_gsm, nrtp->msg_type, nrtp);
162 }
163
164 static int delete_event(struct lcr_work *work, void *instance, int index);
165
166 /*
167  * constructor
168  */
169 Pgsm::Pgsm(int type, char *portname, struct port_settings *settings, struct interface *interface) : Port(type, portname, settings, interface)
170 {
171 #ifdef WITH_GSMHR
172         signed short homing[160];
173         int i;
174 #endif
175
176         p_g_tones = 0;
177         if (interface->is_tones == IS_YES)
178                 p_g_tones = 1;
179         p_g_earlyb = 0;
180         if (interface->is_earlyb == IS_YES)
181                 p_g_earlyb = 1;
182         p_g_rtp_bridge = 0;
183         if (interface->rtp_bridge)
184                 p_g_rtp_bridge = 1;
185         p_g_rtp_payloads = 0;
186         memset(&p_g_samples, 0, sizeof(p_g_samples));
187         p_callerinfo.itype = (interface->extension)?INFO_ITYPE_ISDN_EXTENSION:INFO_ITYPE_ISDN;
188         memset(&p_g_delete, 0, sizeof(p_g_delete));
189         add_work(&p_g_delete, delete_event, this, 0);
190         p_g_lcr_gsm = NULL;
191         p_g_callref = 0;
192         p_g_mode = 0;
193         p_g_gsm_b_sock = -1;
194         p_g_gsm_b_index = -1;
195         p_g_gsm_b_active = 0;
196         p_g_notify_pending = NULL;
197         p_g_setup_pending = NULL;
198         p_g_connect_pending = NULL;
199         p_g_fr_decoder = NULL;
200         p_g_fr_encoder = NULL;
201         p_g_hr_decoder = NULL;
202         p_g_hr_encoder = NULL;
203         p_g_amr_decoder = NULL;
204         p_g_amr_encoder = NULL;
205         p_g_amr_cmr = 0;
206         p_g_amr_cmr_valid = 0;
207 #ifdef WITH_GSMFR
208         p_g_fr_decoder = gsm_fr_create();
209         p_g_fr_encoder = gsm_fr_create();
210         if (!p_g_fr_encoder || !p_g_fr_decoder) {
211                 PERROR("Failed to create GSM FR codec instance\n");
212                 trigger_work(&p_g_delete);
213         }
214 #endif
215 #ifdef WITH_GSMHR
216         p_g_hr_decoder = gsm_hr_create();
217         p_g_hr_encoder = gsm_hr_create();
218         if (!p_g_hr_encoder || !p_g_hr_decoder) {
219                 PERROR("Failed to create GSM HR codec instance\n");
220                 trigger_work(&p_g_delete);
221         }
222         /* Homing */
223         for (i = 0; i < 160; i++)
224                 homing[i] = 0x0008;
225         gsm_hr_encode(p_g_hr_encoder, homing, NULL);
226 #endif
227 #ifdef WITH_GSMAMR
228         p_g_amr_decoder = gsm_amr_create();
229         p_g_amr_encoder = gsm_amr_create();
230         if (!p_g_amr_encoder || !p_g_amr_decoder) {
231                 PERROR("Failed to create GSM AMR codec instance\n");
232                 trigger_work(&p_g_delete);
233         }
234 #endif
235         p_g_rxpos = 0;
236         p_g_tch_connected = 0;
237         p_g_media_type = 0;
238
239         PDEBUG(DEBUG_GSM, "Created new GSMPort(%s).\n", portname);
240 }
241
242 /*
243  * destructor
244  */
245 Pgsm::~Pgsm()
246 {
247         PDEBUG(DEBUG_GSM, "Destroyed GSM process(%s).\n", p_name);
248
249         del_work(&p_g_delete);
250
251         /* remove queued message */
252         if (p_g_notify_pending)
253                 message_free(p_g_notify_pending);
254         if (p_g_setup_pending)
255                 message_free(p_g_setup_pending);
256         if (p_g_connect_pending)
257                 message_free(p_g_connect_pending);
258
259 //#ifdef WITH_GSMFR
260         /* close codec */
261         if (p_g_fr_encoder)
262                 gsm_fr_destroy(p_g_fr_encoder);
263         if (p_g_fr_decoder)
264                 gsm_fr_destroy(p_g_fr_decoder);
265 //#endif
266 #ifdef WITH_GSMHR
267         if (p_g_hr_encoder)
268                 gsm_hr_destroy(p_g_hr_encoder);
269         if (p_g_hr_decoder)
270                 gsm_hr_destroy(p_g_hr_decoder);
271 #endif
272 #ifdef WITH_GSMAMR
273         /* close codec */
274         if (p_g_amr_encoder)
275                 gsm_amr_destroy(p_g_amr_encoder);
276         if (p_g_amr_decoder)
277                 gsm_amr_destroy(p_g_amr_decoder);
278 #endif
279 }
280
281
282 /* receive encoded frame from gsm */
283 void Pgsm::frame_receive(void *arg)
284 {
285         struct gsm_data_frame *frame = (struct gsm_data_frame *)arg;
286         unsigned char data[160];
287         int i, cmr;
288
289         if (!p_g_fr_decoder)
290                 return;
291
292         switch (frame->msg_type) {
293         case GSM_TCHF_FRAME:
294                 if (p_g_media_type != MEDIA_TYPE_GSM) {
295                         PERROR("FR frame, but current media type mismatches.\n");
296                         return;
297                 }
298                 if (!p_g_fr_decoder) {
299                         PERROR("FR frame, but decoder not created.\n");
300                         return;
301                 }
302                 if ((frame->data[0]>>4) != 0xd) {
303                         PDEBUG(DEBUG_GSM, "received GSM frame with wrong magig 0x%x\n", frame->data[0]>>4);
304                         goto bfi;
305                 }
306 #ifdef WITH_GSMFR
307                 /* decode */
308                 gsm_fr_decode(p_g_fr_decoder, frame->data, p_g_samples);
309                 for (i = 0; i < 160; i++) {
310                         data[i] = audio_s16_to_law[p_g_samples[i] & 0xffff];
311                 }
312 #endif
313                 break;
314         case GSM_TCHH_FRAME:
315                 if (p_g_media_type != MEDIA_TYPE_GSM_HR) {
316                         PERROR("HR frame, but current media type mismatches.\n");
317                         return;
318                 }
319                 if (!p_g_hr_decoder) {
320                         PERROR("HR frame, but decoder not created.\n");
321                         return;
322                 }
323                 if ((frame->data[0]>>4) != 0x0)
324                         goto bfi;
325 #ifdef WITH_GSMHR
326                 /* decode */
327                 if (gsm_hr_decode(p_g_hr_decoder, frame->data, p_g_samples))
328                         goto bfi;
329                 for (i = 0; i < 160; i++) {
330                         data[i] = audio_s16_to_law[p_g_samples[i] & 0xffff];
331                 }
332 #endif
333                 break;
334         case GSM_TCHF_FRAME_EFR:
335                 if (p_g_media_type != MEDIA_TYPE_GSM_EFR) {
336                         PERROR("EFR frame, but current media type mismatches.\n");
337                         return;
338                 }
339                 if (!p_g_amr_decoder) {
340                         PERROR("EFR frame, but decoder not created.\n");
341                         return;
342                 }
343                 if ((frame->data[0]>>4) != 0xc)
344                         goto bfi;
345 #ifdef WITH_GSMAMR
346                 /* decode */
347                 gsm_efr_decode(p_g_amr_decoder, frame->data, p_g_samples);
348                 for (i = 0; i < 160; i++) {
349                         data[i] = audio_s16_to_law[p_g_samples[i] & 0xffff];
350                 }
351 #endif
352                 break;
353         case GSM_TCH_FRAME_AMR:
354                 if (p_g_media_type != MEDIA_TYPE_AMR) {
355                         PERROR("AMR frame, but current media type mismatches.\n");
356                         return;
357                 }
358                 if (!p_g_amr_decoder) {
359                         PERROR("AMR frame, but decoder not created.\n");
360                         return;
361                 }
362                 cmr = (frame->data[1] >> 4);
363                 if (cmr <= 7) {
364                         p_g_amr_cmr = cmr;
365                         p_g_amr_cmr_valid = 1;
366                 }
367                 if (!(frame->data[2] & 0x04))
368                         goto bfi;
369 #ifdef WITH_GSMAMR
370                 /* decode (skip length byte in front) */
371                 gsm_amr_decode(p_g_amr_decoder, frame->data + 1, p_g_samples);
372                 for (i = 0; i < 160; i++) {
373                         data[i] = audio_s16_to_law[p_g_samples[i] & 0xffff];
374                 }
375 #endif
376                 break;
377         case GSM_BAD_FRAME:
378         default:
379 bfi:
380                 if (p_echotest) {
381                         /* beep on bad frame */
382                         for (i = 0; i < 160; i++) {
383                                 if ((i & 3) > 2)
384                                         p_g_samples[i] = 15000;
385                                 else
386                                         p_g_samples[i] = -15000;
387                                 data[i] = audio_s16_to_law[p_g_samples[i] & 0xffff];
388                         }
389                 } else {
390                         /* repeat on bad frame */
391                         for (i = 0; i < 160; i++) {
392                                 p_g_samples[i] = (p_g_samples[i] * 14) >> 4;
393                                 data[i] = audio_s16_to_law[p_g_samples[i] & 0xffff];
394                         }
395                 }
396         }
397
398         /* record data */
399         if (p_record)
400                 record(data, 160, 0); // from down
401         if (p_tap)
402                 tap(data, 160, 0); // from down
403
404         /* local echo */
405         if (p_echotest)
406                 bridge_rx(data, 160);
407
408         /* send to remote*/
409         bridge_tx(data, 160);
410 }
411
412 /* send traffic to gsm */
413 int Pgsm::bridge_rx(unsigned char *data, int len)
414 {
415         if (p_tone_name[0])
416                 return -EINVAL;
417
418         return audio_send(data, len);
419 }
420
421 int Pgsm::audio_send(unsigned char *data, int len)
422 {
423         unsigned char frame[33];
424         int ret;
425
426         /* record data */
427         if (p_record)
428                 record(data, len, 1); // from up
429         if (p_tap)
430                 tap(data, len, 1); // from up
431
432         /* encoder init failed */
433         if (!p_g_fr_encoder)
434                 return -EINVAL;
435
436         /* (currently) not connected, so don't flood tch! */
437         if (!p_g_tch_connected)
438                 return -EINVAL;
439
440         /* write to rx buffer */
441         while(len--) {
442                 p_g_rxdata[p_g_rxpos++] = audio_law_to_s32[*data++];
443                 if (p_g_rxpos != 160)
444                         continue;
445                 p_g_rxpos = 0;
446
447                 switch (p_g_media_type) {
448                 case MEDIA_TYPE_GSM:
449                         if (!p_g_fr_encoder) {
450                                 PERROR("FR frame, but encoder not created.\n");
451                                 break;
452                         }
453 #ifdef WITH_GSMFR
454                         /* encode data */
455                         gsm_fr_encode(p_g_fr_encoder, p_g_rxdata, frame);
456                         frame_send(frame, 33, GSM_TCHF_FRAME);
457 #endif
458                         break;
459                 case MEDIA_TYPE_GSM_HR:
460                         if (!p_g_hr_encoder) {
461                                 PERROR("HR frame, but encoder not created.\n");
462                                 break;
463                         }
464 #ifdef WITH_GSMHR
465                         /* encode data */
466                         gsm_hr_encode(p_g_hr_encoder, p_g_rxdata, frame);
467                         frame_send(frame, 15, GSM_TCHH_FRAME);
468 #endif
469                         break;
470                 case MEDIA_TYPE_GSM_EFR:
471                         if (!p_g_amr_encoder) {
472                                 PERROR("EFR frame, but encoder not created.\n");
473                                 break;
474                         }
475 #ifdef WITH_GSMAMR
476                         /* encode data */
477                         gsm_efr_encode(p_g_amr_encoder, p_g_rxdata, frame);
478                         frame_send(frame, 31, GSM_TCHF_FRAME_EFR);
479 #endif
480                         break;
481                 case MEDIA_TYPE_AMR:
482                         if (!p_g_amr_encoder) {
483                                 PERROR("AMR frame, but encoder not created.\n");
484                                 break;
485                         }
486                         if (!p_g_amr_cmr_valid) {
487                                 PDEBUG(DEBUG_GSM, "no valid CMR yet.\n");
488                                 break;
489                         }
490 #ifdef WITH_GSMAMR
491                         /* encode data (prefix a length byte) */
492                         ret = gsm_amr_encode(p_g_amr_encoder, p_g_rxdata, frame + 1, p_g_amr_cmr);
493                         frame[0] = ret;
494                         frame_send(frame, ret + 1, GSM_TCH_FRAME_AMR);
495 #endif
496                         break;
497                 }
498         }
499
500         return 0;
501 }
502
503 void Pgsm::frame_send(void *_frame, int len, int msg_type)
504 {
505         unsigned char buffer[sizeof(struct gsm_data_frame) + len];
506         struct gsm_data_frame *frame = (struct gsm_data_frame *)buffer;
507         
508         frame->msg_type = msg_type;
509         frame->callref = p_g_callref;
510         memcpy(frame->data, _frame, len);
511
512         if (p_g_lcr_gsm) {
513                 mncc_send(p_g_lcr_gsm, frame->msg_type, frame);
514         }
515 }
516
517 /*
518  * create trace
519  */
520 void gsm_trace_header(const char *interface_name, class Pgsm *port, unsigned int msg_type, int direction)
521 {
522         char msgtext[64];
523         struct interface *interface = interface_first;
524
525         interface = getinterfacebyname(interface_name);
526         if (!interface)
527                 return;
528
529         /* select message and primitive text */
530         SCPY(msgtext, mncc_name(msg_type));
531
532         /* add direction */
533         if (port) {
534                 switch(port->p_type) {
535                 case PORT_TYPE_GSM_BS_OUT:
536                 case PORT_TYPE_GSM_BS_IN:
537                         SCAT(msgtext, " LCR<->BSC");
538                         break;
539                 case PORT_TYPE_GSM_MS_OUT:
540                 case PORT_TYPE_GSM_MS_IN:
541                         SCAT(msgtext, " LCR<->MS");
542                         break;
543                 }
544         } else
545                 SCAT(msgtext, " ----");
546
547         /* init trace with given values */
548         start_trace(-1,
549                     interface,
550                     port?numberrize_callerinfo(port->p_callerinfo.id, port->p_callerinfo.ntype, options.national, options.international):NULL,
551                     port?port->p_dialinginfo.id:NULL,
552                     direction,
553                     CATEGORY_CH,
554                     port?port->p_serial:0,
555                     msgtext);
556 }
557
558 /* modify lchan to given payload type */
559 void Pgsm::modify_lchan(int media_type)
560 {
561         struct gsm_mncc *mode;
562
563         /* already modified to that media type */
564         if (p_g_media_type == media_type)
565                 return;
566
567         p_g_media_type = media_type;
568         gsm_trace_header(p_interface_name, this, MNCC_LCHAN_MODIFY, DIRECTION_OUT);
569         mode = create_mncc(MNCC_LCHAN_MODIFY, p_g_callref);
570         switch (media_type) {
571         case MEDIA_TYPE_GSM_EFR:
572                 add_trace("speech", "version", "EFR given");
573                 mode->lchan_mode = 0x21; /* GSM V2 */
574                 break;
575         case MEDIA_TYPE_AMR:
576                 add_trace("speech", "version", "AMR given");
577                 mode->lchan_mode = 0x41; /* GSM V3 */
578                 break;
579         default:
580                 add_trace("speech", "version", "Full/Half Rate given");
581                 mode->lchan_mode = 0x01; /* GSM V1 */
582         }
583         mode->lchan_type = 0x02; /* FIXME: unused */
584         add_trace("mode", NULL, "0x%02x", mode->lchan_mode);
585         end_trace();
586         send_and_free_mncc(p_g_lcr_gsm, mode->msg_type, mode);
587 }
588
589 /* CALL PROCEEDING INDICATION (from network) */
590 void Pgsm::call_proc_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
591 {
592         struct lcr_msg *message;
593         struct gsm_mncc *frame;
594
595         gsm_trace_header(p_interface_name, this, msg_type, DIRECTION_IN);
596         end_trace();
597
598         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_PROCEEDING);
599         message_put(message);
600
601         new_state(PORT_STATE_OUT_PROCEEDING);
602
603         if (p_g_earlyb && !p_g_tch_connected) { /* only if ... */
604                 gsm_trace_header(p_interface_name, this, MNCC_FRAME_RECV, DIRECTION_OUT);
605                 end_trace();
606                 frame = create_mncc(MNCC_FRAME_RECV, p_g_callref);
607                 send_and_free_mncc(p_g_lcr_gsm, frame->msg_type, frame);
608                 p_g_tch_connected = 1;
609         }
610
611         /* modify to GSM FR (this is GSM user side only, so there is FR supported only) */
612         modify_lchan(MEDIA_TYPE_GSM);
613 }
614
615 /* ALERTING INDICATION */
616 void Pgsm::alert_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
617 {
618         struct lcr_msg *message;
619         struct gsm_mncc *frame;
620
621         gsm_trace_header(p_interface_name, this, msg_type, DIRECTION_IN);
622         end_trace();
623
624         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_ALERTING);
625         message_put(message);
626
627         new_state(PORT_STATE_OUT_ALERTING);
628
629         if (p_g_earlyb && !p_g_tch_connected) { /* only if ... */
630                 gsm_trace_header(p_interface_name, this, MNCC_FRAME_RECV, DIRECTION_OUT);
631                 end_trace();
632                 frame = create_mncc(MNCC_FRAME_RECV, p_g_callref);
633                 send_and_free_mncc(p_g_lcr_gsm, frame->msg_type, frame);
634                 p_g_tch_connected = 1;
635         }
636
637         /* modify to GSM FR, if not already */
638         if (!p_g_media_type) {
639                 modify_lchan(MEDIA_TYPE_GSM);
640         }
641 }
642
643 /* CONNECT INDICATION */
644 void Pgsm::setup_cnf(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
645 {
646         struct gsm_mncc *resp, *frame;
647         struct lcr_msg *message;
648
649         SCPY(p_connectinfo.id, mncc->connected.number);
650         SCPY(p_connectinfo.imsi, mncc->imsi);
651         p_connectinfo.present = INFO_PRESENT_ALLOWED;
652         p_connectinfo.screen = INFO_SCREEN_NETWORK;
653         p_connectinfo.ntype = INFO_NTYPE_UNKNOWN;
654         SCPY(p_connectinfo.interface, p_interface_name);
655
656         gsm_trace_header(p_interface_name, this, msg_type, DIRECTION_IN);
657         if (p_connectinfo.id[0])
658                 add_trace("connect", "number", "%s", p_connectinfo.id);
659         else if (mncc->imsi[0])
660                 SPRINT(p_connectinfo.id, "imsi-%s", p_connectinfo.imsi);
661         if (mncc->imsi[0])
662                 add_trace("connect", "imsi", "%s", p_connectinfo.imsi);
663         end_trace();
664
665         /* send resp */
666         gsm_trace_header(p_interface_name, this, MNCC_SETUP_COMPL_REQ, DIRECTION_OUT);
667         resp = create_mncc(MNCC_SETUP_COMPL_REQ, p_g_callref);
668         end_trace();
669         send_and_free_mncc(p_g_lcr_gsm, resp->msg_type, resp);
670
671         new_state(PORT_STATE_CONNECT);
672
673         if (!p_g_tch_connected) { /* only if ... */
674                 gsm_trace_header(p_interface_name, this, MNCC_FRAME_RECV, DIRECTION_OUT);
675                 end_trace();
676                 frame = create_mncc(MNCC_FRAME_RECV, p_g_callref);
677                 send_and_free_mncc(p_g_lcr_gsm, frame->msg_type, frame);
678                 p_g_tch_connected = 1;
679         }
680
681         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CONNECT);
682         memcpy(&message->param.connectinfo, &p_connectinfo, sizeof(struct connect_info));
683
684         /* if we have a bridge, but not yet modified, the phone accepts out requested payload.
685          * we force the first in list */
686         if (p_g_rtp_bridge) {
687                 if (!p_g_media_type) {
688                         /* modify to first given type */
689                         modify_lchan(p_g_rtp_media_types[0]);
690                         /* also set payload type */
691                         p_g_payload_type = p_g_rtp_payload_types[0];
692                 }
693                 message->param.connectinfo.rtpinfo.media_types[0] = p_g_media_type;
694                 message->param.connectinfo.rtpinfo.payload_types[0] = p_g_payload_type;
695                 message->param.connectinfo.rtpinfo.payloads = 1;
696         } else {
697                 /* modify to GSM FR, if not already
698                 * for network side, this should have been already happened */
699                 if (!p_g_media_type)
700                         modify_lchan(MEDIA_TYPE_GSM);
701         }
702
703
704         if (p_g_rtp_bridge) {
705                 struct gsm_mncc_rtp *rtp;
706
707                 PDEBUG(DEBUG_GSM, "Request RTP peer info, before forwarding connect msg\n");
708                 p_g_connect_pending = message;
709                 rtp = (struct gsm_mncc_rtp *) create_mncc(MNCC_RTP_CREATE, p_g_callref);
710                 send_and_free_mncc(p_g_lcr_gsm, rtp->msg_type, rtp);
711         } else
712                 message_put(message);
713 }
714
715 /* CONNECT ACK INDICATION */
716 void Pgsm::setup_compl_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
717 {
718         struct gsm_mncc *frame;
719
720         gsm_trace_header(p_interface_name, this, msg_type, DIRECTION_IN);
721         end_trace();
722
723         new_state(PORT_STATE_CONNECT);
724
725         if (!p_g_tch_connected) { /* only if ... */
726                 gsm_trace_header(p_interface_name, this, MNCC_FRAME_RECV, DIRECTION_OUT);
727                 end_trace();
728                 frame = create_mncc(MNCC_FRAME_RECV, p_g_callref);
729                 send_and_free_mncc(p_g_lcr_gsm, frame->msg_type, frame);
730                 p_g_tch_connected = 1;
731         }
732
733         /* modify to GSM FR, if not already */
734         if (!p_g_media_type) {
735                 modify_lchan(MEDIA_TYPE_GSM);
736         }
737 }
738
739 /* DISCONNECT INDICATION */
740 void Pgsm::disc_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
741 {
742         struct lcr_msg *message;
743         int cause = 16, location = 0;
744         struct gsm_mncc *resp;
745
746         gsm_trace_header(p_interface_name, this, msg_type, DIRECTION_IN);
747         if (mncc->fields & MNCC_F_CAUSE) {
748                 location = mncc->cause.location;
749                 cause = mncc->cause.value;
750                 add_trace("cause", "coding", "%d", mncc->cause.coding);
751                 add_trace("cause", "location", "%d", location);
752                 add_trace("cause", "value", "%d", cause);
753         }
754         end_trace();
755
756         /* send release */
757         resp = create_mncc(MNCC_REL_REQ, p_g_callref);
758         gsm_trace_header(p_interface_name, this, MNCC_REL_REQ, DIRECTION_OUT);
759 #if 0
760         resp->fields |= MNCC_F_CAUSE;
761         resp->cause.coding = 3;
762         resp->cause.location = 1;
763         resp->cause.value = cause;
764         add_trace("cause", "coding", "%d", resp->cause.coding);
765         add_trace("cause", "location", "%d", resp->cause.location);
766         add_trace("cause", "value", "%d", resp->cause.value);
767 #endif
768         end_trace();
769         send_and_free_mncc(p_g_lcr_gsm, resp->msg_type, resp);
770
771         /* sending release to endpoint */
772         while(p_epointlist) {
773                 message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
774                 message->param.disconnectinfo.cause = cause;
775                 message->param.disconnectinfo.location = location;
776                 message_put(message);
777                 /* remove epoint */
778                 free_epointlist(p_epointlist);
779         }
780         new_state(PORT_STATE_RELEASE);
781         trigger_work(&p_g_delete);
782 }
783
784 /* CC_RELEASE INDICATION */
785 void Pgsm::rel_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
786 {
787         int location = 0, cause = 16;
788         struct lcr_msg *message;
789
790         gsm_trace_header(p_interface_name, this, msg_type, DIRECTION_IN);
791         if (mncc->fields & MNCC_F_CAUSE) {
792                 location = mncc->cause.location;
793                 cause = mncc->cause.value;
794                 add_trace("cause", "coding", "%d", mncc->cause.coding);
795                 add_trace("cause", "location", "%d", mncc->cause.location);
796                 add_trace("cause", "value", "%d", mncc->cause.value);
797         }
798         end_trace();
799
800         /* sending release to endpoint */
801         while(p_epointlist) {
802                 message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
803                 message->param.disconnectinfo.cause = cause;
804                 message->param.disconnectinfo.location = location;
805                 message_put(message);
806                 /* remove epoint */
807                 free_epointlist(p_epointlist);
808         }
809         new_state(PORT_STATE_RELEASE);
810         trigger_work(&p_g_delete);
811 }
812
813 /* NOTIFY INDICATION */
814 void Pgsm::notify_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
815 {
816         struct lcr_msg *message;
817
818         gsm_trace_header(p_interface_name, this, msg_type, DIRECTION_IN);
819         add_trace("notify", NULL, "%d", mncc->notify);
820         end_trace();
821
822         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_NOTIFY);
823         message->param.notifyinfo.notify = mncc->notify;
824         message_put(message);
825 }
826
827 /* MESSAGE_NOTIFY */
828 void Pgsm::message_notify(unsigned int epoint_id, int message_id, union parameter *param)
829 {
830         struct gsm_mncc *mncc;
831         int notify;
832
833 //      printf("if = %d\n", param->notifyinfo.notify);
834         if (param->notifyinfo.notify>INFO_NOTIFY_NONE) {
835                 notify = param->notifyinfo.notify & 0x7f;
836                 if (p_state!=PORT_STATE_CONNECT /*&& p_state!=PORT_STATE_IN_PROCEEDING*/ && p_state!=PORT_STATE_IN_ALERTING) {
837                         /* queue notification */
838                         if (p_g_notify_pending)
839                                 message_free(p_g_notify_pending);
840                         p_g_notify_pending = message_create(ACTIVE_EPOINT(p_epointlist), p_serial, EPOINT_TO_PORT, message_id);
841                         memcpy(&p_g_notify_pending->param, param, sizeof(union parameter));
842                 } else {
843                         /* sending notification */
844                         gsm_trace_header(p_interface_name, this, MNCC_NOTIFY_REQ, DIRECTION_OUT);
845                         add_trace("notify", NULL, "%d", notify);
846                         end_trace();
847                         mncc = create_mncc(MNCC_NOTIFY_REQ, p_g_callref);
848                         mncc->notify = notify;
849                         send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
850                 }
851         }
852 }
853
854 /* RTP create indication */
855 void Pgsm::rtp_create_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
856 {
857         struct gsm_mncc_rtp *rtp = (struct gsm_mncc_rtp *) mncc;
858
859         /* send queued setup, as we received remote RTP info */
860         if (p_g_setup_pending) {
861                 struct lcr_msg *message;
862
863                 message = p_g_setup_pending;
864                 PDEBUG(DEBUG_GSM, "Got RTP peer info (%08x,%d) forwarding setup\n", rtp->ip, rtp->port);
865                 message->param.setup.rtpinfo.ip = rtp->ip;
866                 message->param.setup.rtpinfo.port = rtp->port;
867                 message_put(message);
868                 p_g_setup_pending = NULL;
869         }
870         if (p_g_connect_pending) {
871                 PDEBUG(DEBUG_GSM, "Got RTP peer info (%08x,%d) connecting RTP... \n", rtp->ip, rtp->port);
872                 send_mncc_rtp_connect();
873         }
874 }
875
876 /* RTP connect indication */
877 void Pgsm::rtp_connect_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
878 {
879         struct lcr_msg *message;
880         struct gsm_mncc_rtp *rtp = (struct gsm_mncc_rtp *) mncc;
881
882         if (p_g_connect_pending) {
883                 message = p_g_connect_pending;
884                 PDEBUG(DEBUG_GSM, "Got RTP peer info (%08x,%d) forwarding connect\n", rtp->ip, rtp->port);
885                 message->param.connectinfo.rtpinfo.ip = rtp->ip;
886                 message->param.connectinfo.rtpinfo.port = rtp->port;
887                 message_put(message);
888                 p_g_connect_pending = NULL;
889         }
890 }
891
892 /* MESSAGE_PROGRESS */
893 void Pgsm::message_progress(unsigned int epoint_id, int message_id, union parameter *param)
894 {
895         if (param->progressinfo.progress == 8) {
896                 PDEBUG(DEBUG_GSM, "Remote provides tones for us\n");
897                 p_g_tones = 1;
898         }
899
900         if (param->progressinfo.rtpinfo.port) {
901                 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]);
902
903                 /* modify channel to givne type, also sets media type */
904                 modify_lchan(param->progressinfo.rtpinfo.media_types[0]);
905
906                 /* connect RTP */
907                 p_g_rtp_ip_remote = param->progressinfo.rtpinfo.ip;
908                 p_g_rtp_port_remote = param->progressinfo.rtpinfo.port;
909                 /* p_g_media_type is already set by modify_lchan() */
910                 p_g_payload_type = param->progressinfo.rtpinfo.payload_types[0];
911                 send_mncc_rtp_connect();
912         }
913 }
914
915 /* MESSAGE_ALERTING */
916 void Pgsm::message_alerting(unsigned int epoint_id, int message_id, union parameter *param)
917 {
918         struct gsm_mncc *mncc;
919
920         /* send alert */
921         gsm_trace_header(p_interface_name, this, MNCC_ALERT_REQ, DIRECTION_OUT);
922         mncc = create_mncc(MNCC_ALERT_REQ, p_g_callref);
923         if (p_g_tones) {
924                 mncc->fields |= MNCC_F_PROGRESS;
925                 mncc->progress.coding = 3; /* GSM */
926                 mncc->progress.location = 1;
927                 mncc->progress.descr = 8;
928                 add_trace("progress", "coding", "%d", mncc->progress.coding);
929                 add_trace("progress", "location", "%d", mncc->progress.location);
930                 add_trace("progress", "descr", "%d", mncc->progress.descr);
931         }
932         end_trace();
933         send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
934
935         new_state(PORT_STATE_IN_ALERTING);
936
937         if (p_g_tones && !p_g_tch_connected) { /* only if ... */
938                 gsm_trace_header(p_interface_name, this, MNCC_FRAME_RECV, DIRECTION_OUT);
939                 end_trace();
940                 mncc = create_mncc(MNCC_FRAME_RECV, p_g_callref);
941                 send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
942                 p_g_tch_connected = 1;
943         }
944
945         /* modify to GSM FR, if not already */
946         if (!p_g_media_type) {
947                 modify_lchan(MEDIA_TYPE_GSM);
948         }
949 }
950
951 /* MESSAGE_CONNECT */
952 void Pgsm::message_connect(unsigned int epoint_id, int message_id, union parameter *param)
953 {
954         struct gsm_mncc *mncc;
955
956         /* copy connected information */
957         memcpy(&p_connectinfo, &param->connectinfo, sizeof(p_connectinfo));
958         /* screen outgoing caller id */
959         do_screen(1, p_connectinfo.id, sizeof(p_connectinfo.id), &p_connectinfo.ntype, &p_connectinfo.present, p_interface_name);
960
961         /* send connect */
962         mncc = create_mncc(MNCC_SETUP_RSP, p_g_callref);
963         gsm_trace_header(p_interface_name, this, MNCC_SETUP_RSP, DIRECTION_OUT);
964         /* caller information */
965         mncc->fields |= MNCC_F_CONNECTED;
966         mncc->connected.plan = 1;
967         switch (p_callerinfo.ntype) {
968                 case INFO_NTYPE_UNKNOWN:
969                 mncc->connected.type = 0x0;
970                 break;
971                 case INFO_NTYPE_INTERNATIONAL:
972                 mncc->connected.type = 0x1;
973                 break;
974                 case INFO_NTYPE_NATIONAL:
975                 mncc->connected.type = 0x2;
976                 break;
977                 case INFO_NTYPE_SUBSCRIBER:
978                 mncc->connected.type = 0x4;
979                 break;
980                 default: /* INFO_NTYPE_NOTPRESENT */
981                 mncc->fields &= ~MNCC_F_CONNECTED;
982                 break;
983         }
984         switch (p_callerinfo.screen) {
985                 case INFO_SCREEN_USER:
986                 mncc->connected.screen = 0;
987                 break;
988                 default: /* INFO_SCREEN_NETWORK */
989                 mncc->connected.screen = 3;
990                 break;
991         }
992         switch (p_callerinfo.present) {
993                 case INFO_PRESENT_ALLOWED:
994                 mncc->connected.present = 0;
995                 break;
996                 case INFO_PRESENT_RESTRICTED:
997                 mncc->connected.present = 1;
998                 break;
999                 default: /* INFO_PRESENT_NOTAVAIL */
1000                 mncc->connected.present = 2;
1001                 break;
1002         }
1003         if (mncc->fields & MNCC_F_CONNECTED) {
1004                 SCPY(mncc->connected.number, p_connectinfo.id);
1005                 add_trace("connected", "type", "%d", mncc->connected.type);
1006                 add_trace("connected", "plan", "%d", mncc->connected.plan);
1007                 add_trace("connected", "present", "%d", mncc->connected.present);
1008                 add_trace("connected", "screen", "%d", mncc->connected.screen);
1009                 add_trace("connected", "number", "%s", mncc->connected.number);
1010         }
1011         end_trace();
1012         send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
1013
1014         new_state(PORT_STATE_CONNECT_WAITING);
1015
1016         if (param->connectinfo.rtpinfo.port) {
1017                 PDEBUG(DEBUG_GSM, "CONNECT with RTP peer info, sent to BSC (%08x,%d)\n", param->connectinfo.rtpinfo.ip, param->connectinfo.rtpinfo.port);
1018
1019                 /* modify channel to givne type, also sets media type */
1020                 modify_lchan(param->connectinfo.rtpinfo.media_types[0]);
1021
1022                 /* connect RTP */
1023                 p_g_rtp_ip_remote = param->connectinfo.rtpinfo.ip;
1024                 p_g_rtp_port_remote = param->connectinfo.rtpinfo.port;
1025                 /* p_g_media_type is already set by modify_lchan() */
1026                 p_g_payload_type = param->connectinfo.rtpinfo.payload_types[0];
1027                 send_mncc_rtp_connect();
1028         }
1029 }
1030
1031 /* MESSAGE_DISCONNECT */
1032 void Pgsm::message_disconnect(unsigned int epoint_id, int message_id, union parameter *param)
1033 {
1034         struct gsm_mncc *mncc;
1035
1036         /* send disconnect */
1037         mncc = create_mncc(MNCC_DISC_REQ, p_g_callref);
1038         gsm_trace_header(p_interface_name, this, MNCC_DISC_REQ, DIRECTION_OUT);
1039         if (p_g_tones) {
1040                 mncc->fields |= MNCC_F_PROGRESS;
1041                 mncc->progress.coding = 3; /* GSM */
1042                 mncc->progress.location = 1;
1043                 mncc->progress.descr = 8;
1044                 add_trace("progress", "coding", "%d", mncc->progress.coding);
1045                 add_trace("progress", "location", "%d", mncc->progress.location);
1046                 add_trace("progress", "descr", "%d", mncc->progress.descr);
1047         }
1048         mncc->fields |= MNCC_F_CAUSE;
1049         mncc->cause.coding = 3;
1050         mncc->cause.location = param->disconnectinfo.location;
1051         mncc->cause.value = param->disconnectinfo.cause;
1052         add_trace("cause", "coding", "%d", mncc->cause.coding);
1053         add_trace("cause", "location", "%d", mncc->cause.location);
1054         add_trace("cause", "value", "%d", mncc->cause.value);
1055         end_trace();
1056         send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
1057
1058         new_state(PORT_STATE_OUT_DISCONNECT);
1059
1060         if (p_g_tones && !p_g_tch_connected) { /* only if ... */
1061                 gsm_trace_header(p_interface_name, this, MNCC_FRAME_RECV, DIRECTION_OUT);
1062                 end_trace();
1063                 mncc = create_mncc(MNCC_FRAME_RECV, p_g_callref);
1064                 send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
1065                 p_g_tch_connected = 1;
1066         }
1067 }
1068
1069
1070 /* MESSAGE_RELEASE */
1071 void Pgsm::message_release(unsigned int epoint_id, int message_id, union parameter *param)
1072 {
1073         struct gsm_mncc *mncc;
1074
1075         /* send release */
1076         mncc = create_mncc(MNCC_REL_REQ, p_g_callref);
1077         gsm_trace_header(p_interface_name, this, MNCC_REL_REQ, DIRECTION_OUT);
1078         mncc->fields |= MNCC_F_CAUSE;
1079         mncc->cause.coding = 3;
1080         mncc->cause.location = param->disconnectinfo.location;
1081         mncc->cause.value = param->disconnectinfo.cause;
1082         add_trace("cause", "coding", "%d", mncc->cause.coding);
1083         add_trace("cause", "location", "%d", mncc->cause.location);
1084         add_trace("cause", "value", "%d", mncc->cause.value);
1085         end_trace();
1086         send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
1087
1088         new_state(PORT_STATE_RELEASE);
1089         trigger_work(&p_g_delete);
1090         return;
1091 }
1092
1093 /*
1094  * endpoint sends messages to the port
1095  */
1096 int Pgsm::message_epoint(unsigned int epoint_id, int message_id, union parameter *param)
1097 {
1098         int ret = 0;
1099
1100         if (Port::message_epoint(epoint_id, message_id, param))
1101                 return 1;
1102
1103         switch(message_id) {
1104                 case MESSAGE_NOTIFY: /* display and notifications */
1105                 ret = 1;
1106                 message_notify(epoint_id, message_id, param);
1107                 break;
1108
1109 //              case MESSAGE_FACILITY: /* facility message */
1110 //              message_facility(epoint_id, message_id, param);
1111 //              break;
1112
1113                 case MESSAGE_PROCEEDING: /* message not handles */
1114                 ret = 1;
1115                 break;
1116
1117                 case MESSAGE_PROGRESS:
1118                 ret = 1;
1119                 message_progress(epoint_id, message_id, param);
1120                 break;
1121
1122                 case MESSAGE_ALERTING: /* call of endpoint is ringing */
1123                 ret = 1;
1124                 if (p_state!=PORT_STATE_IN_PROCEEDING)
1125                         break;
1126                 message_alerting(epoint_id, message_id, param);
1127                 if (p_g_notify_pending) {
1128                         /* send pending notify message during connect */
1129                         message_notify(ACTIVE_EPOINT(p_epointlist), p_g_notify_pending->type, &p_g_notify_pending->param);
1130                         message_free(p_g_notify_pending);
1131                         p_g_notify_pending = NULL;
1132                 }
1133                 break;
1134
1135                 case MESSAGE_CONNECT: /* call of endpoint is connected */
1136                 ret = 1;
1137                 if (p_state!=PORT_STATE_IN_PROCEEDING
1138                  && p_state!=PORT_STATE_IN_ALERTING)
1139                         break;
1140                 message_connect(epoint_id, message_id, param);
1141                 if (p_g_notify_pending) {
1142                         /* send pending notify message during connect */
1143                         message_notify(ACTIVE_EPOINT(p_epointlist), p_g_notify_pending->type, &p_g_notify_pending->param);
1144                         message_free(p_g_notify_pending);
1145                         p_g_notify_pending = NULL;
1146                 }
1147                 break;
1148
1149                 case MESSAGE_DISCONNECT: /* call has been disconnected */
1150                 ret = 1;
1151                 if (p_state!=PORT_STATE_IN_PROCEEDING
1152                  && p_state!=PORT_STATE_IN_ALERTING
1153                  && p_state!=PORT_STATE_OUT_SETUP
1154                  && p_state!=PORT_STATE_OUT_OVERLAP
1155                  && p_state!=PORT_STATE_OUT_PROCEEDING
1156                  && p_state!=PORT_STATE_OUT_ALERTING
1157                  && p_state!=PORT_STATE_CONNECT
1158                  && p_state!=PORT_STATE_CONNECT_WAITING)
1159                         break;
1160                 message_disconnect(epoint_id, message_id, param);
1161                 break;
1162
1163                 case MESSAGE_RELEASE: /* release isdn port */
1164                 ret = 1;
1165                 if (p_state==PORT_STATE_RELEASE)
1166                         break;
1167                 message_release(epoint_id, message_id, param);
1168                 break;
1169
1170         }
1171
1172         return ret;
1173 }
1174
1175 /* deletes only if l3id is release, otherwhise it will be triggered then */
1176 static int delete_event(struct lcr_work *work, void *instance, int index)
1177 {
1178         class Pgsm *gsmport = (class Pgsm *)instance;
1179
1180         delete gsmport;
1181
1182         return 0;
1183 }
1184
1185 int gsm_exit(int rc)
1186 {
1187         return(rc);
1188 }
1189
1190 int gsm_init(void)
1191 {
1192         /* seed the PRNG */
1193         srand(time(NULL));
1194
1195         return 0;
1196 }
1197
1198 /*
1199  * MNCC interface
1200  */
1201
1202 static int mncc_q_enqueue(struct lcr_gsm *lcr_gsm, struct gsm_mncc *mncc, unsigned int len)
1203 {
1204         struct mncc_q_entry *qe;
1205
1206         qe = (struct mncc_q_entry *) MALLOC(sizeof(*qe)+sizeof(*mncc)+len);
1207         if (!qe)
1208                 return -ENOMEM;
1209
1210         qe->next = NULL;
1211         qe->len = len;
1212         memcpy(qe->data, mncc, len);
1213
1214         /* in case of empty list ... */
1215         if (!lcr_gsm->mncc_q_hd && !lcr_gsm->mncc_q_tail) {
1216                 /* the list head and tail both point to the new qe */
1217                 lcr_gsm->mncc_q_hd = lcr_gsm->mncc_q_tail = qe;
1218         } else {
1219                 /* append to tail of list */
1220                 lcr_gsm->mncc_q_tail->next = qe;
1221                 lcr_gsm->mncc_q_tail = qe;
1222         }
1223
1224         lcr_gsm->mncc_lfd.when |= LCR_FD_WRITE;
1225
1226         return 0;
1227 }
1228
1229 static struct mncc_q_entry *mncc_q_dequeue(struct lcr_gsm *lcr_gsm)
1230 {
1231         struct mncc_q_entry *qe = lcr_gsm->mncc_q_hd;
1232         if (!qe)
1233                 return NULL;
1234
1235         /* dequeue the successfully sent message */
1236         lcr_gsm->mncc_q_hd = qe->next;
1237         if (!qe)
1238                 return NULL;
1239         if (qe == lcr_gsm->mncc_q_tail)
1240                 lcr_gsm->mncc_q_tail = NULL;
1241
1242         return qe;
1243 }
1244
1245 /* routine called by LCR code if it wants to send a message to OpenBSC */
1246 static int mncc_send(struct lcr_gsm *lcr_gsm, int msg_type, void *data)
1247 {
1248         int len = 0;
1249
1250         /* FIXME: the caller should provide this */
1251         switch (msg_type) {
1252         case GSM_TCHF_FRAME:
1253                 len = sizeof(struct gsm_data_frame) + 33;
1254                 break;
1255         default:
1256                 len = sizeof(struct gsm_mncc);
1257                 break;
1258         }
1259                 
1260         return mncc_q_enqueue(lcr_gsm, (struct gsm_mncc *)data, len);
1261 }
1262
1263 /* close MNCC socket */
1264 static int mncc_fd_close(struct lcr_gsm *lcr_gsm, struct lcr_fd *lfd)
1265 {
1266         class Port *port;
1267         class Pgsm *pgsm = NULL;
1268         struct lcr_msg *message;
1269
1270         PERROR("Lost MNCC socket, retrying in %u seconds\n", SOCKET_RETRY_TIMER);
1271         close(lfd->fd);
1272         unregister_fd(lfd);
1273         lfd->fd = -1;
1274
1275         /* free all the calls that were running through the MNCC interface */
1276         port = port_first;
1277         while(port) {
1278                 if ((port->p_type & PORT_CLASS_mISDN_MASK) == PORT_CLASS_GSM) {
1279                         pgsm = (class Pgsm *)port;
1280                         if (pgsm->p_g_lcr_gsm == lcr_gsm) {
1281                                 message = message_create(pgsm->p_serial, ACTIVE_EPOINT(pgsm->p_epointlist), PORT_TO_EPOINT, MESSAGE_RELEASE);
1282                                 message->param.disconnectinfo.cause = 27; // temp. unavail.
1283                                 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1284                                 message_put(message);
1285                                 pgsm->new_state(PORT_STATE_RELEASE);
1286                                 trigger_work(&pgsm->p_g_delete);
1287                         }
1288                 }
1289                 port = port->next;
1290         }
1291
1292         /* flush the queue */
1293         while (mncc_q_dequeue(lcr_gsm))
1294                 ;
1295
1296         /* start the re-connect timer */
1297         schedule_timer(&lcr_gsm->socket_retry, SOCKET_RETRY_TIMER, 0);
1298
1299         return 0;
1300 }
1301
1302 /* write to OpenBSC via MNCC socket */
1303 static int mncc_fd_write(struct lcr_fd *lfd, void *inst, int idx)
1304 {
1305         struct lcr_gsm *lcr_gsm = (struct lcr_gsm *) inst;
1306         struct mncc_q_entry *qe, *qe2;
1307         int rc;
1308
1309         while (1) {
1310                 qe = lcr_gsm->mncc_q_hd;
1311                 if (!qe) {
1312                         lfd->when &= ~LCR_FD_WRITE;
1313                         break;
1314                 }
1315                 rc = write(lfd->fd, qe->data, qe->len);
1316                 if (rc == 0)
1317                         return mncc_fd_close(lcr_gsm, lfd);
1318                 if (rc < 0)
1319                         return rc;
1320                 if (rc < (int)qe->len)
1321                         return -1;
1322                 /* dequeue the successfully sent message */
1323                 qe2 = mncc_q_dequeue(lcr_gsm);
1324                 assert(qe == qe2);
1325                 free(qe);
1326         }
1327         return 0;
1328 }
1329
1330 /* read from OpenBSC via MNCC socket */
1331 static int mncc_fd_read(struct lcr_fd *lfd, void *inst, int idx)
1332 {
1333         struct lcr_gsm *lcr_gsm = (struct lcr_gsm *) inst;
1334         int rc;
1335         static char buf[sizeof(struct gsm_mncc)+1024];
1336         struct gsm_mncc *mncc_prim = (struct gsm_mncc *) buf;
1337
1338         memset(buf, 0, sizeof(buf));
1339         rc = recv(lfd->fd, buf, sizeof(buf), 0);
1340         if (rc == 0)
1341                 return mncc_fd_close(lcr_gsm, lfd);
1342         if (rc < 0)
1343                 return rc;
1344
1345         /* Hand the MNCC message into LCR */
1346         switch (lcr_gsm->type) {
1347 #ifdef WITH_GSM_BS
1348         case LCR_GSM_TYPE_NETWORK:
1349                 return message_bsc(lcr_gsm, mncc_prim->msg_type, mncc_prim);
1350 #endif
1351 #ifdef WITH_GSM_MS
1352         case LCR_GSM_TYPE_MS:
1353                 return message_ms(lcr_gsm, mncc_prim->msg_type, mncc_prim);
1354 #endif
1355         default:
1356                 return 0;
1357         }
1358 }
1359
1360 /* file descriptor callback if we can read or write form MNCC socket */
1361 static int mncc_fd_cb(struct lcr_fd *lfd, unsigned int what, void *inst, int idx)
1362 {
1363         int rc = 0;
1364
1365         if (what & LCR_FD_READ)
1366                 rc = mncc_fd_read(lfd, inst, idx);
1367         if (rc < 0)
1368                 return rc;
1369
1370         if (what & LCR_FD_WRITE)
1371                 rc = mncc_fd_write(lfd, inst, idx);
1372
1373         return rc;
1374 }
1375
1376 int mncc_socket_retry_cb(struct lcr_timer *timer, void *inst, int index)
1377 {
1378         struct lcr_gsm *lcr_gsm = (struct lcr_gsm *) inst;
1379         int fd, rc;
1380
1381         lcr_gsm->mncc_lfd.fd = -1;
1382
1383         fd = socket(PF_UNIX, SOCK_SEQPACKET, 0);
1384         if (fd < 0) {
1385                 PERROR("Cannot create SEQPACKET socket, giving up!\n");
1386                 return fd;
1387         }
1388
1389         rc = connect(fd, (struct sockaddr *) &lcr_gsm->sun,
1390                      sizeof(lcr_gsm->sun));
1391         if (rc < 0) {
1392                 PERROR("Could not connect to MNCC socket %s, "
1393                         "retrying in %u seconds\n", lcr_gsm->sun.sun_path,
1394                         SOCKET_RETRY_TIMER);
1395                 close(fd);
1396                 schedule_timer(&lcr_gsm->socket_retry, SOCKET_RETRY_TIMER, 0);
1397         } else {
1398                 PDEBUG(DEBUG_GSM, "Connected to MNCC socket %s!\n", lcr_gsm->sun.sun_path);
1399                 lcr_gsm->mncc_lfd.fd = fd;
1400                 register_fd(&lcr_gsm->mncc_lfd, LCR_FD_READ, &mncc_fd_cb, lcr_gsm, 0);
1401         }
1402
1403         return 0;
1404 }
1405