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