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