e747ff01a36e34786289c50517b3295a0a5929c8
[lcr.git] / gsm.cpp
1 /*****************************************************************************\
2 **                                                                           **
3 ** LCR                                                                       **
4 **                                                                           **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg                                              **
7 **                                                                           **
8 ** mISDN gsm                                                                 **
9 **                                                                           **
10 \*****************************************************************************/ 
11
12 #include "main.h"
13
14 #ifndef _GNU_SOURCE
15 #define _GNU_SOURCE
16 #endif
17 extern "C" {
18 #include <getopt.h>
19
20 #include <openbsc/db.h>
21 #include <openbsc/select.h>
22 #include <openbsc/debug.h>
23 #include <openbsc/e1_input.h>
24 #include <openbsc/talloc.h>
25 #include <openbsc/mncc.h>
26 #include <openbsc/trau_frame.h>
27 struct gsm_network *bsc_gsmnet = 0;
28 extern int ipacc_rtp_direct;
29 extern int bsc_bootstrap_network(int (*mmc_rev)(struct gsm_network *, int, void *),
30                                  const char *cfg_file);
31 extern int bsc_shutdown_net(struct gsm_network *net);
32 void talloc_ctx_init(void);
33 void on_dso_load_token(void);
34 void on_dso_load_rrlp(void);
35 static struct debug_target *stderr_target;
36
37 #include "gsm_audio.h"
38
39 #undef AF_ISDN
40 #undef PF_ISDN
41 extern  int     AF_ISDN;
42 #define PF_ISDN AF_ISDN
43 }
44
45
46 struct lcr_gsm *gsm = NULL;
47
48 static unsigned int new_callref = 1;
49
50
51 /*
52  * create and send mncc message
53  */
54 static struct gsm_mncc *create_mncc(int msg_type, unsigned int callref)
55 {
56         struct gsm_mncc *mncc;
57
58         mncc = (struct gsm_mncc *)MALLOC(sizeof(struct gsm_mncc));
59         mncc->msg_type = msg_type;
60         mncc->callref = callref;
61         return (mncc);
62 }
63 static int send_and_free_mncc(struct gsm_network *net, unsigned int msg_type, void *data)
64 {
65         int ret;
66
67         ret = mncc_send(net, msg_type, data);
68         free(data);
69
70         return ret;
71 }
72
73
74 /*
75  * constructor
76  */
77 Pgsm::Pgsm(int type, struct mISDNport *mISDNport, char *portname, struct port_settings *settings, int channel, int exclusive, int mode) : PmISDN(type, mISDNport, portname, settings, channel, exclusive, mode)
78 {
79         p_callerinfo.itype = (mISDNport->ifport->interface->extension)?INFO_ITYPE_ISDN_EXTENSION:INFO_ITYPE_ISDN;
80         p_m_g_callref = 0;
81         p_m_g_mode = 0;
82         p_m_g_gsm_b_sock = -1;
83         p_m_g_gsm_b_index = -1;
84         p_m_g_gsm_b_active = 0;
85         p_m_g_notify_pending = NULL;
86         p_m_g_decoder = gsm_audio_create();
87         p_m_g_encoder = gsm_audio_create();
88         if (!p_m_g_encoder || !p_m_g_decoder) {
89                 PERROR("Failed to create GSM audio codec instance\n");
90                 p_m_delete = 1;
91         }
92         p_m_g_rxpos = 0;
93         p_m_g_tch_connected = 0;
94
95         PDEBUG(DEBUG_GSM, "Created new mISDNPort(%s).\n", portname);
96 }
97
98 /*
99  * destructor
100  */
101 Pgsm::~Pgsm()
102 {
103         PDEBUG(DEBUG_GSM, "Destroyed GSM process(%s).\n", p_name);
104
105         /* remove queued message */
106         if (p_m_g_notify_pending)
107                 message_free(p_m_g_notify_pending);
108
109         /* close audio transfer socket */
110         if (p_m_g_gsm_b_sock > -1)
111                 bchannel_close();
112
113         /* close codec */
114         if (p_m_g_encoder)
115                 gsm_audio_destroy(p_m_g_encoder);
116         if (p_m_g_decoder)
117                 gsm_audio_destroy(p_m_g_decoder);
118 }
119
120
121 /* close bsc side bchannel */
122 void Pgsm::bchannel_close(void)
123 {
124         if (p_m_g_gsm_b_sock > -1)
125                 close(p_m_g_gsm_b_sock);
126         p_m_g_gsm_b_sock = -1;
127         p_m_g_gsm_b_index = -1;
128         p_m_g_gsm_b_active = 0;
129 }
130
131 /* open bsc side bchannel */
132 int Pgsm::bchannel_open(int index)
133 {
134         int ret;
135         unsigned int on = 1;
136         struct sockaddr_mISDN addr;
137         struct mISDNhead act;
138
139         if (p_m_g_gsm_b_sock > -1) {
140                 PERROR("Socket already created for index %d\n", index);
141                 return(-EIO);
142         }
143
144         /* open socket */
145         ret = p_m_g_gsm_b_sock = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_B_RAW);
146         if (ret < 0) {
147                 PERROR("Failed to open bchannel-socket for index %d\n", index);
148                 bchannel_close();
149                 return(ret);
150         }
151         
152         /* set nonblocking io */
153         ret = ioctl(p_m_g_gsm_b_sock, FIONBIO, &on);
154         if (ret < 0) {
155                 PERROR("Failed to set bchannel-socket index %d into nonblocking IO\n", index);
156                 bchannel_close();
157                 return(ret);
158         }
159
160         /* bind socket to bchannel */
161         addr.family = AF_ISDN;
162         addr.dev = gsm->gsm_port;
163         addr.channel = index+1+(index>15);
164         ret = bind(p_m_g_gsm_b_sock, (struct sockaddr *)&addr, sizeof(addr));
165         if (ret < 0) {
166                 PERROR("Failed to bind bchannel-socket for index %d\n", index);
167                 bchannel_close();
168                 return(ret);
169         }
170         /* activate bchannel */
171         PDEBUG(DEBUG_GSM, "Activating GSM side channel index %i.\n", index);
172         act.prim = PH_ACTIVATE_REQ; 
173         act.id = 0;
174         ret = sendto(p_m_g_gsm_b_sock, &act, MISDN_HEADER_LEN, 0, NULL, 0);
175         if (ret < 0) {
176                 PERROR("Failed to activate index %d\n", index);
177                 bchannel_close();
178                 return(ret);
179         }
180
181         p_m_g_gsm_b_index = index;
182
183         return(0);
184 }
185
186 /* receive from bchannel */
187 void Pgsm::bchannel_receive(struct mISDNhead *hh, unsigned char *data, int len)
188 {
189         unsigned char frame[33];
190
191         /* encoder init failed */
192         if (!p_m_g_encoder)
193                 return;
194
195         /* (currently) not connected, so don't flood tch! */
196         if (!p_m_g_tch_connected)
197                 return;
198
199         /* write to rx buffer */
200         while(len--) {
201                 p_m_g_rxdata[p_m_g_rxpos++] = audio_law_to_s32[*data++];
202                 if (p_m_g_rxpos == 160) {
203                         p_m_g_rxpos = 0;
204
205                         /* encode data */
206                         gsm_audio_encode(p_m_g_encoder, p_m_g_rxdata, frame);
207                         frame_send(frame);
208                 }
209         }
210 }
211
212 /* transmit to bchannel */
213 void Pgsm::bchannel_send(unsigned int prim, unsigned int id, unsigned char *data, int len)
214 {
215         unsigned char buf[MISDN_HEADER_LEN+len];
216         struct mISDNhead *hh = (struct mISDNhead *)buf;
217         int ret;
218
219         if (!p_m_g_gsm_b_active)
220                 return;
221
222         /* make and send frame */
223         hh->prim = PH_DATA_REQ;
224         hh->id = 0;
225         memcpy(buf+MISDN_HEADER_LEN, data, len);
226         ret = sendto(p_m_g_gsm_b_sock, buf, MISDN_HEADER_LEN+len, 0, NULL, 0);
227         if (ret <= 0)
228                 PERROR("Failed to send to socket index %d\n", index);
229 }
230
231 void Pgsm::frame_send(void *_frame)
232 {
233         unsigned char buffer[sizeof(struct gsm_data_frame) + 33];
234         struct gsm_data_frame *frame = (struct gsm_data_frame *)buffer;
235         
236         frame->msg_type = GSM_TCHF_FRAME;
237         frame->callref = p_m_g_callref;
238         memcpy(frame->data, _frame, 33);
239         mncc_send((struct gsm_network *)gsm->network, frame->msg_type, frame);
240 }
241
242
243 void Pgsm::frame_receive(void *_frame)
244 {
245         struct gsm_data_frame *frame = (struct gsm_data_frame *)_frame;
246         signed short samples[160];
247         unsigned char data[160];
248         int i;
249
250         if (!p_m_g_decoder)
251                 return;
252
253         if ((frame->data[0]>>4) != 0xd)
254                 PERROR("received GSM frame with wrong magig 0x%x\n", frame->data[0]>>4);
255         
256         /* decode */
257         gsm_audio_decode(p_m_g_decoder, frame->data, samples);
258         for (i = 0; i < 160; i++) {
259                 data[i] = audio_s16_to_law[samples[i] & 0xffff];
260         }
261
262         /* send */
263         bchannel_send(PH_DATA_REQ, 0, data, 160);
264 }
265
266
267 /*
268  * create trace
269  **/
270 static void gsm_trace_header(struct mISDNport *mISDNport, class PmISDN *port, unsigned int msg_type, int direction)
271 {
272         char msgtext[64];
273
274         /* select message and primitive text */
275         SCPY(msgtext, get_mncc_name(msg_type));
276
277         /* add direction */
278         if (direction == DIRECTION_OUT)
279                 SCAT(msgtext, " MSC->BSC");
280         else
281                 SCAT(msgtext, " MSC<-BSC");
282
283         /* init trace with given values */
284         start_trace(mISDNport?mISDNport->portnum:-1,
285                     mISDNport?(mISDNport->ifport?mISDNport->ifport->interface:NULL):NULL,
286                     port?numberrize_callerinfo(port->p_callerinfo.id, port->p_callerinfo.ntype, options.national, options.international):NULL,
287                     port?port->p_dialinginfo.id:NULL,
288                     direction,
289                     CATEGORY_CH,
290                     port?port->p_serial:0,
291                     msgtext);
292 }
293
294
295
296 /* select bchannel */
297 int Pgsm::hunt_bchannel(void)
298 {
299         int channel;
300         int i;
301
302         chan_trace_header(p_m_mISDNport, this, "CHANNEL SELECTION (setup)", DIRECTION_NONE);
303         add_trace("channel", "reserved", "%d", p_m_mISDNport->b_reserved);
304         if (p_m_mISDNport->b_reserved >= p_m_mISDNport->b_num) { // of out chan..
305                 add_trace("conclusion", NULL, "all channels are reserved");
306                 end_trace();
307                 return(-34); // no channel
308         }
309         /* find channel */
310         i = 0;
311         channel = 0;
312         while(i < p_m_mISDNport->b_num) {
313                 if (p_m_mISDNport->b_port[i] == NULL) {
314                         channel = i+1+(i>=15);
315                         break;
316                 }
317                 i++;
318         }
319         if (!channel) {
320                 add_trace("conclusion", NULL, "no channel available");
321                 end_trace();
322                 return(-6); // channel unacceptable
323         }
324         add_trace("conclusion", NULL, "channel available");
325         add_trace("connect", "channel", "%d", channel);
326         end_trace();
327         return(channel);
328 }
329
330
331 /*
332  * handles all indications
333  */
334 /* SETUP INDICATION */
335 void Pgsm::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
336 {
337         int ret;
338         class Endpoint *epoint;
339         struct lcr_msg *message;
340         int channel;
341         struct gsm_mncc *mode, *proceeding, *frame;
342
343         /* emergency shutdown */
344         printf("%d %d\n", mncc->emergency, !gsm->conf.noemergshut);
345         if (mncc->emergency && !gsm->conf.noemergshut) {
346                 start_trace(p_m_mISDNport->portnum,
347                         p_m_mISDNport->ifport->interface,
348                         NULL,
349                         NULL,
350                         DIRECTION_NONE,
351                         CATEGORY_CH,
352                         0,
353                         "EMERGENCY SHUTDOWN (due to received emergency call)");
354                 end_trace();
355                 quit = 1;
356         }
357         /* process given callref */
358         l1l2l3_trace_header(p_m_mISDNport, this, L3_NEW_L3ID_IND, DIRECTION_IN);
359         add_trace("callref", "new", "0x%x", callref);
360         if (p_m_g_callref) {
361                 /* release in case the ID is already in use */
362                 add_trace("error", NULL, "callref already in use");
363                 end_trace();
364                 mncc = create_mncc(MNCC_REJ_REQ, callref);
365                 gsm_trace_header(p_m_mISDNport, this, MNCC_REJ_REQ, DIRECTION_OUT);
366                 mncc->fields |= MNCC_F_CAUSE;
367                 mncc->cause.coding = 3;
368                 mncc->cause.location = 1;
369                 mncc->cause.value = 47;
370                 add_trace("cause", "coding", "%d", mncc->cause.coding);
371                 add_trace("cause", "location", "%d", mncc->cause.location);
372                 add_trace("cause", "value", "%d", mncc->cause.value);
373                 add_trace("reason", NULL, "callref already in use");
374                 end_trace();
375                 send_and_free_mncc((struct gsm_network *)gsm->network, mncc->msg_type, mncc);
376                 new_state(PORT_STATE_RELEASE);
377                 p_m_delete = 1;
378                 return;
379         }
380         p_m_g_callref = callref;
381         end_trace();
382
383         /* if blocked, release call with MT_RELEASE_COMPLETE */
384         if (p_m_mISDNport->ifport->block) {
385                 mncc = create_mncc(MNCC_REJ_REQ, p_m_g_callref);
386                 gsm_trace_header(p_m_mISDNport, this, MNCC_REJ_REQ, DIRECTION_OUT);
387                 mncc->fields |= MNCC_F_CAUSE;
388                 mncc->cause.coding = 3;
389                 mncc->cause.location = 1;
390                 mncc->cause.value = 27;
391                 add_trace("cause", "coding", "%d", mncc->cause.coding);
392                 add_trace("cause", "location", "%d", mncc->cause.location);
393                 add_trace("cause", "value", "%d", mncc->cause.value);
394                 add_trace("reason", NULL, "port is blocked");
395                 end_trace();
396                 send_and_free_mncc((struct gsm_network *)gsm->network, mncc->msg_type, mncc);
397                 new_state(PORT_STATE_RELEASE);
398                 p_m_delete = 1;
399                 return;
400         }
401
402         /* caller info */
403         if (mncc->clir.inv)
404                 p_callerinfo.present = INFO_PRESENT_RESTRICTED;
405         else
406                 p_callerinfo.present = INFO_PRESENT_ALLOWED;
407         if (mncc->calling.number[0])
408                 SCPY(p_callerinfo.id, mncc->calling.number);
409         else
410                 p_callerinfo.present = INFO_PRESENT_NOTAVAIL;
411         SCPY(p_callerinfo.imsi, mncc->imsi);
412         p_callerinfo.screen = INFO_SCREEN_NETWORK;
413         p_callerinfo.ntype = INFO_NTYPE_UNKNOWN;
414         p_callerinfo.isdn_port = p_m_portnum;
415         SCPY(p_callerinfo.interface, p_m_mISDNport->ifport->interface->name);
416
417         /* dialing information */
418         SCAT(p_dialinginfo.id, mncc->called.number);
419         switch (mncc->called.type) {
420                 case 0x1:
421                 p_dialinginfo.ntype = INFO_NTYPE_INTERNATIONAL;
422                 break;
423                 case 0x2:
424                 p_dialinginfo.ntype = INFO_NTYPE_NATIONAL;
425                 break;
426                 case 0x4:
427                 p_dialinginfo.ntype = INFO_NTYPE_SUBSCRIBER;
428                 break;
429                 default:
430                 p_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
431                 break;
432         }
433         if (mncc->emergency) {
434                 SCPY(p_dialinginfo.id, "emergency");
435         }
436         p_dialinginfo.sending_complete = 1;
437
438         /* bearer capability */
439         // todo
440         p_capainfo.bearer_capa = INFO_BC_SPEECH;
441         p_capainfo.bearer_info1 = (options.law=='a')?3:2;
442         p_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
443         p_capainfo.source_mode = B_MODE_TRANSPARENT;
444         p_m_g_mode = p_capainfo.source_mode;
445
446         /* useruser */
447
448         /* hunt channel */
449         ret = channel = hunt_bchannel();
450         if (ret < 0)
451                 goto no_channel;
452
453         /* open channel */
454         ret = seize_bchannel(channel, 1);
455         if (ret < 0) {
456                 no_channel:
457                 mncc = create_mncc(MNCC_REJ_REQ, p_m_g_callref);
458                 gsm_trace_header(p_m_mISDNport, this, MNCC_REJ_REQ, DIRECTION_OUT);
459                 mncc->fields |= MNCC_F_CAUSE;
460                 mncc->cause.coding = 3;
461                 mncc->cause.location = 1;
462                 mncc->cause.value = 34;
463                 add_trace("cause", "coding", "%d", mncc->cause.coding);
464                 add_trace("cause", "location", "%d", mncc->cause.location);
465                 add_trace("cause", "value", "%d", mncc->cause.value);
466                 add_trace("reason", NULL, "no channel");
467                 end_trace();
468                 send_and_free_mncc((struct gsm_network *)gsm->network, mncc->msg_type, mncc);
469                 new_state(PORT_STATE_RELEASE);
470                 p_m_delete = 1;
471                 return;
472         }
473         bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE);
474         if (bchannel_open(p_m_b_index))
475                 goto no_channel;
476
477         /* what infos did we got ... */
478         gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
479         if (p_callerinfo.id[0])
480                 add_trace("calling", "number", "%s", p_callerinfo.id);
481         else
482                 SPRINT(p_callerinfo.id, "imsi-%s", p_callerinfo.imsi);
483         add_trace("calling", "imsi", "%s", p_callerinfo.imsi);
484         add_trace("dialing", "number", "%s", p_dialinginfo.id);
485         end_trace();
486
487         /* create endpoint */
488         if (p_epointlist)
489                 FATAL("Incoming call but already got an endpoint.\n");
490         if (!(epoint = new Endpoint(p_serial, 0)))
491                 FATAL("No memory for Endpoint instance\n");
492         if (!(epoint->ep_app = new DEFAULT_ENDPOINT_APP(epoint, 0))) //incoming
493                 FATAL("No memory for Endpoint Application instance\n");
494         epointlist_new(epoint->ep_serial);
495
496         /* modify lchan to GSM codec V1 */
497         gsm_trace_header(p_m_mISDNport, this, MNCC_LCHAN_MODIFY, DIRECTION_OUT);
498         mode = create_mncc(MNCC_LCHAN_MODIFY, p_m_g_callref);
499         mode->lchan_mode = 0x01; /* GSM V1 */
500         add_trace("mode", NULL, "0x%02x", mode->lchan_mode);
501         end_trace();
502         send_and_free_mncc((struct gsm_network *)gsm->network, mode->msg_type, mode);
503
504         /* send call proceeding */
505         gsm_trace_header(p_m_mISDNport, this, MNCC_CALL_PROC_REQ, DIRECTION_OUT);
506         proceeding = create_mncc(MNCC_CALL_PROC_REQ, p_m_g_callref);
507         if (p_m_mISDNport->tones) {
508                 proceeding->fields |= MNCC_F_PROGRESS;
509                 proceeding->progress.coding = 3; /* GSM */
510                 proceeding->progress.location = 1;
511                 proceeding->progress.descr = 8;
512                 add_trace("progress", "coding", "%d", proceeding->progress.coding);
513                 add_trace("progress", "location", "%d", proceeding->progress.location);
514                 add_trace("progress", "descr", "%d", proceeding->progress.descr);
515         }
516         end_trace();
517         send_and_free_mncc((struct gsm_network *)gsm->network, proceeding->msg_type, proceeding);
518
519         new_state(PORT_STATE_IN_PROCEEDING);
520
521         if (p_m_mISDNport->tones && !p_m_g_tch_connected) { /* only if ... */
522                 gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
523                 end_trace();
524                 frame = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
525                 send_and_free_mncc((struct gsm_network *)gsm->network, frame->msg_type, frame);
526                 p_m_g_tch_connected = 1;
527         }
528
529         /* send setup message to endpoit */
530         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_SETUP);
531         message->param.setup.isdn_port = p_m_portnum;
532         message->param.setup.port_type = p_type;
533 //      message->param.setup.dtmf = 0;
534         memcpy(&message->param.setup.dialinginfo, &p_dialinginfo, sizeof(struct dialing_info));
535         memcpy(&message->param.setup.callerinfo, &p_callerinfo, sizeof(struct caller_info));
536         memcpy(&message->param.setup.capainfo, &p_capainfo, sizeof(struct capa_info));
537         SCPY((char *)message->param.setup.useruser.data, (char *)mncc->useruser.info);
538         message->param.setup.useruser.len = strlen(mncc->useruser.info);
539         message->param.setup.useruser.protocol = mncc->useruser.proto;
540         message_put(message);
541 }
542
543 /* DTMF INDICATION */
544 void Pgsm::start_dtmf_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
545 {
546         struct lcr_msg *message;
547         struct gsm_mncc *resp;
548
549         gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
550         add_trace("keypad", NULL, "%c", mncc->keypad);
551         end_trace();
552         SPRINT(p_dialinginfo.id, "%c", mncc->keypad);
553         p_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
554
555         /* send resp */
556         gsm_trace_header(p_m_mISDNport, this, MNCC_START_DTMF_RSP, DIRECTION_OUT);
557         add_trace("keypad", NULL, "%c", mncc->keypad);
558         end_trace();
559         resp = create_mncc(MNCC_START_DTMF_RSP, p_m_g_callref);
560         resp->keypad = mncc->keypad;
561         send_and_free_mncc((struct gsm_network *)gsm->network, resp->msg_type, resp);
562
563         /* send dialing information */
564         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_INFORMATION);
565         memcpy(&message->param.information, &p_dialinginfo, sizeof(struct dialing_info));
566         message_put(message);
567 }
568 void Pgsm::stop_dtmf_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
569 {
570         struct gsm_mncc *resp;
571
572         gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
573         add_trace("keypad", NULL, "%c", mncc->keypad);
574         end_trace();
575
576         /* send resp */
577         gsm_trace_header(p_m_mISDNport, this, MNCC_STOP_DTMF_RSP, DIRECTION_OUT);
578         add_trace("keypad", NULL, "%c", mncc->keypad);
579         end_trace();
580         resp = create_mncc(MNCC_STOP_DTMF_RSP, p_m_g_callref);
581         resp->keypad = mncc->keypad;
582         send_and_free_mncc((struct gsm_network *)gsm->network, resp->msg_type, resp);
583 }
584
585 /* PROCEEDING INDICATION */
586 void Pgsm::call_conf_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
587 {
588         struct gsm_mncc *mode;
589
590         gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
591         if (mncc->fields & MNCC_F_CAUSE) {
592                 add_trace("cause", "coding", "%d", mncc->cause.coding);
593                 add_trace("cause", "location", "%", mncc->cause.location);
594                 add_trace("cause", "value", "%", mncc->cause.value);
595         }
596         end_trace();
597
598         /* modify lchan to GSM codec V1 */
599         gsm_trace_header(p_m_mISDNport, this, MNCC_LCHAN_MODIFY, DIRECTION_OUT);
600         mode = create_mncc(MNCC_LCHAN_MODIFY, p_m_g_callref);
601         mode->lchan_mode = 0x01; /* GSM V1 */
602         add_trace("mode", NULL, "0x%02x", mode->lchan_mode);
603         end_trace();
604         send_and_free_mncc((struct gsm_network *)gsm->network, mode->msg_type, mode);
605
606 }
607
608 /* ALERTING INDICATION */
609 void Pgsm::alert_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
610 {
611         struct lcr_msg *message;
612
613         gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
614         end_trace();
615
616         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_ALERTING);
617         message_put(message);
618
619         new_state(PORT_STATE_OUT_ALERTING);
620
621 }
622
623 /* CONNECT INDICATION */
624 void Pgsm::setup_cnf(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
625 {
626         struct gsm_mncc *resp, *frame;
627         struct lcr_msg *message;
628
629         SCPY(p_connectinfo.id, mncc->connected.number);
630         SCPY(p_connectinfo.imsi, mncc->imsi);
631         p_connectinfo.present = INFO_PRESENT_ALLOWED;
632         p_connectinfo.screen = INFO_SCREEN_NETWORK;
633         p_connectinfo.ntype = INFO_NTYPE_UNKNOWN;
634         p_connectinfo.isdn_port = p_m_portnum;
635         SCPY(p_connectinfo.interface, p_m_mISDNport->ifport->interface->name);
636
637         gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
638         if (p_connectinfo.id[0])
639                 add_trace("connect", "number", "%s", p_connectinfo.id);
640         else if (mncc->imsi[0])
641                 SPRINT(p_connectinfo.id, "imsi-%s", p_connectinfo.imsi);
642         if (mncc->imsi[0])
643                 add_trace("connect", "imsi", "%s", p_connectinfo.imsi);
644         end_trace();
645
646         /* send resp */
647         gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_COMPL_REQ, DIRECTION_OUT);
648         resp = create_mncc(MNCC_SETUP_COMPL_REQ, p_m_g_callref);
649         end_trace();
650         send_and_free_mncc((struct gsm_network *)gsm->network, resp->msg_type, resp);
651
652         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CONNECT);
653         memcpy(&message->param.connectinfo, &p_connectinfo, sizeof(struct connect_info));
654         message_put(message);
655
656         new_state(PORT_STATE_CONNECT);
657
658         if (!p_m_g_tch_connected) { /* only if ... */
659                 gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
660                 end_trace();
661                 frame = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
662                 send_and_free_mncc((struct gsm_network *)gsm->network, frame->msg_type, frame);
663                 p_m_g_tch_connected = 1;
664         }
665 }
666
667 /* CONNECT ACK INDICATION */
668 void Pgsm::setup_compl_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
669 {
670         struct gsm_mncc *frame;
671
672         gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
673         end_trace();
674
675         new_state(PORT_STATE_CONNECT);
676
677         if (!p_m_g_tch_connected) { /* only if ... */
678                 gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
679                 end_trace();
680                 frame = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
681                 send_and_free_mncc((struct gsm_network *)gsm->network, frame->msg_type, frame);
682                 p_m_g_tch_connected = 1;
683         }
684 }
685
686 /* DISCONNECT INDICATION */
687 void Pgsm::disc_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
688 {
689         struct lcr_msg *message;
690         int cause = 16, location = 0;
691         struct gsm_mncc *resp;
692
693         gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
694         if (mncc->fields & MNCC_F_CAUSE) {
695                 location = mncc->cause.location;
696                 cause = mncc->cause.value;
697                 add_trace("cause", "coding", "%d", mncc->cause.coding);
698                 add_trace("cause", "location", "%d", location);
699                 add_trace("cause", "value", "%d", cause);
700         }
701         end_trace();
702
703         /* send release */
704         resp = create_mncc(MNCC_REL_REQ, p_m_g_callref);
705         gsm_trace_header(p_m_mISDNport, this, MNCC_REL_REQ, DIRECTION_OUT);
706 #if 0
707         resp->fields |= MNCC_F_CAUSE;
708         resp->cause.coding = 3;
709         resp->cause.location = 1;
710         resp->cause.value = cause;
711         add_trace("cause", "coding", "%d", resp->cause.coding);
712         add_trace("cause", "location", "%d", resp->cause.location);
713         add_trace("cause", "value", "%d", resp->cause.value);
714 #endif
715         end_trace();
716         send_and_free_mncc((struct gsm_network *)gsm->network, resp->msg_type, resp);
717
718         /* sending release to endpoint */
719         while(p_epointlist) {
720                 message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
721                 message->param.disconnectinfo.cause = cause;
722                 message->param.disconnectinfo.location = location;
723                 message_put(message);
724                 /* remove epoint */
725                 free_epointlist(p_epointlist);
726         }
727         new_state(PORT_STATE_RELEASE);
728         p_m_delete = 1;
729 }
730
731 /* CC_RELEASE INDICATION */
732 void Pgsm::rel_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
733 {
734         int location = 0, cause = 16;
735         struct lcr_msg *message;
736
737         gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
738         if (mncc->fields & MNCC_F_CAUSE) {
739                 location = mncc->cause.location;
740                 cause = mncc->cause.value;
741                 add_trace("cause", "coding", "%d", mncc->cause.coding);
742                 add_trace("cause", "location", "%d", mncc->cause.location);
743                 add_trace("cause", "value", "%d", mncc->cause.value);
744         }
745         end_trace();
746
747         /* sending release to endpoint */
748         while(p_epointlist) {
749                 message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
750                 message->param.disconnectinfo.cause = cause;
751                 message->param.disconnectinfo.location = location;
752                 message_put(message);
753                 /* remove epoint */
754                 free_epointlist(p_epointlist);
755         }
756         new_state(PORT_STATE_RELEASE);
757         p_m_delete = 1;
758 }
759
760 /* NOTIFY INDICATION */
761 void Pgsm::notify_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
762 {
763         struct lcr_msg *message;
764
765         gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
766         add_trace("notify", NULL, "%d", mncc->notify);
767         end_trace();
768
769         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_NOTIFY);
770         message->param.notifyinfo.notify = mncc->notify;
771         message_put(message);
772 }
773
774
775 /* HOLD INDICATION */
776 void Pgsm::hold_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
777 {
778         struct lcr_msg *message;
779         struct gsm_mncc *resp, *frame;
780
781         gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
782         end_trace();
783
784         /* notify the hold of call */
785         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_NOTIFY);
786         message->param.notifyinfo.notify = INFO_NOTIFY_REMOTE_HOLD;
787         message->param.notifyinfo.local = 1; /* call is held by supplementary service */
788         message_put(message);
789
790         /* acknowledge hold */
791         gsm_trace_header(p_m_mISDNport, this, MNCC_HOLD_CNF, DIRECTION_OUT);
792         end_trace();
793         resp = create_mncc(MNCC_HOLD_CNF, p_m_g_callref);
794         send_and_free_mncc((struct gsm_network *)gsm->network, resp->msg_type, resp);
795
796         /* disable audio */
797         if (p_m_g_tch_connected) { /* it should be true */
798                 gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_DROP, DIRECTION_OUT);
799                 end_trace();
800                 frame = create_mncc(MNCC_FRAME_DROP, p_m_g_callref);
801                 send_and_free_mncc((struct gsm_network *)gsm->network, frame->msg_type, frame);
802                 p_m_g_tch_connected = 0;
803         }
804 }
805
806
807 /* RETRIEVE INDICATION */
808 void Pgsm::retr_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
809 {
810         struct lcr_msg *message;
811         struct gsm_mncc *resp, *frame;
812
813         gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
814         end_trace();
815
816         /* notify the retrieve of call */
817         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_NOTIFY);
818         message->param.notifyinfo.notify = INFO_NOTIFY_REMOTE_RETRIEVAL;
819         message->param.notifyinfo.local = 1; /* call is retrieved by supplementary service */
820         message_put(message);
821
822         /* acknowledge retr */
823         gsm_trace_header(p_m_mISDNport, this, MNCC_RETRIEVE_CNF, DIRECTION_OUT);
824         end_trace();
825         resp = create_mncc(MNCC_RETRIEVE_CNF, p_m_g_callref);
826         send_and_free_mncc((struct gsm_network *)gsm->network, resp->msg_type, resp);
827
828         /* enable audio */
829         if (!p_m_g_tch_connected) { /* it should be true */
830                 gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
831                 end_trace();
832                 frame = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
833                 send_and_free_mncc((struct gsm_network *)gsm->network, frame->msg_type, frame);
834                 p_m_g_tch_connected = 1;
835         }
836 }
837
838 /*
839  * BSC sends message to port
840  */
841 static int message_bsc(struct gsm_network *net, int msg_type, void *arg)
842 {
843         struct gsm_mncc *mncc = (struct gsm_mncc *)arg;
844         unsigned int callref = mncc->callref;
845         class Port *port;
846         class Pgsm *pgsm = NULL;
847         char name[64];
848         struct mISDNport *mISDNport;
849
850         /* Special messages */
851         switch(msg_type) {
852         }
853
854         /* find callref */
855         callref = mncc->callref;
856         port = port_first;
857         while(port) {
858                 if ((port->p_type & PORT_CLASS_mISDN_MASK) == PORT_CLASS_mISDN_GSM) {
859                         pgsm = (class Pgsm *)port;
860                         if (pgsm->p_m_g_callref == callref) {
861                                 break;
862                         }
863                 }
864                 port = port->next;
865         }
866
867         if (msg_type == GSM_TCHF_FRAME) {
868                 if (port)
869                         pgsm->frame_receive((struct gsm_trau_frame *)arg);
870                 return 0;
871         }
872
873         if (!port) {
874                 if (msg_type != MNCC_SETUP_IND)
875                         return(0);
876                 /* find gsm port */
877                 mISDNport = mISDNport_first;
878                 while(mISDNport) {
879                         if (mISDNport->gsm)
880                                 break;
881                         mISDNport = mISDNport->next;
882                 }
883                 if (!mISDNport) {
884                         struct gsm_mncc *rej;
885
886                         rej = create_mncc(MNCC_REJ_REQ, callref);
887                         rej->fields |= MNCC_F_CAUSE;
888                         rej->cause.coding = 3;
889                         rej->cause.location = 1;
890                         rej->cause.value = 27;
891                         gsm_trace_header(NULL, NULL, MNCC_REJ_REQ, DIRECTION_OUT);
892                         add_trace("cause", "coding", "%d", rej->cause.coding);
893                         add_trace("cause", "location", "%d", rej->cause.location);
894                         add_trace("cause", "value", "%d", rej->cause.value);
895                         end_trace();
896                         send_and_free_mncc((struct gsm_network *)gsm->network, rej->msg_type, rej);
897                         return 0;
898                 }
899                 /* creating port object, transparent until setup with hdlc */
900                 SPRINT(name, "%s-%d-in", mISDNport->ifport->interface->name, mISDNport->portnum);
901                 if (!(pgsm = new Pgsm(PORT_TYPE_GSM_IN, mISDNport, name, NULL, 0, 0, B_MODE_TRANSPARENT)))
902
903                         FATAL("Cannot create Port instance.\n");
904         }
905
906         switch(msg_type) {
907                 case MNCC_SETUP_IND:
908                 pgsm->setup_ind(msg_type, callref, mncc);
909                 break;
910
911                 case MNCC_START_DTMF_IND:
912                 pgsm->start_dtmf_ind(msg_type, callref, mncc);
913                 break;
914
915                 case MNCC_STOP_DTMF_IND:
916                 pgsm->stop_dtmf_ind(msg_type, callref, mncc);
917                 break;
918
919                 case MNCC_CALL_CONF_IND:
920                 pgsm->call_conf_ind(msg_type, callref, mncc);
921                 break;
922
923                 case MNCC_ALERT_IND:
924                 pgsm->alert_ind(msg_type, callref, mncc);
925                 break;
926
927                 case MNCC_SETUP_CNF:
928                 pgsm->setup_cnf(msg_type, callref, mncc);
929                 break;
930
931                 case MNCC_SETUP_COMPL_IND:
932                 pgsm->setup_compl_ind(msg_type, callref, mncc);
933                 break;
934
935                 case MNCC_DISC_IND:
936                 pgsm->disc_ind(msg_type, callref, mncc);
937                 break;
938
939                 case MNCC_REL_IND:
940                 case MNCC_REL_CNF:
941                 case MNCC_REJ_IND:
942                 pgsm->rel_ind(msg_type, callref, mncc);
943                 break;
944
945                 case MNCC_NOTIFY_IND:
946                 pgsm->notify_ind(msg_type, callref, mncc);
947                 break;
948
949                 case MNCC_HOLD_IND:
950                 pgsm->hold_ind(msg_type, callref, mncc);
951                 break;
952
953                 case MNCC_RETRIEVE_IND:
954                 pgsm->retr_ind(msg_type, callref, mncc);
955                 break;
956
957                 default:
958                 PDEBUG(DEBUG_GSM, "Pgsm(%s) gsm port with (caller id %s) received unhandled nessage: 0x%x\n", pgsm->p_name, pgsm->p_callerinfo.id, msg_type);
959         }
960         return(0);
961 }
962
963 /* MESSAGE_SETUP */
964 void Pgsm::message_setup(unsigned int epoint_id, int message_id, union parameter *param)
965 {
966         struct lcr_msg *message;
967         int ret;
968         struct epoint_list *epointlist;
969         struct gsm_mncc *mncc;
970         int channel;
971
972         /* copy setup infos to port */
973         memcpy(&p_callerinfo, &param->setup.callerinfo, sizeof(p_callerinfo));
974         memcpy(&p_dialinginfo, &param->setup.dialinginfo, sizeof(p_dialinginfo));
975         memcpy(&p_capainfo, &param->setup.capainfo, sizeof(p_capainfo));
976         memcpy(&p_redirinfo, &param->setup.redirinfo, sizeof(p_redirinfo));
977
978         /* no number */
979         if (!p_dialinginfo.id[0]) {
980                 gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
981                 add_trace("failure", NULL, "No dialed subscriber given.");
982                 end_trace();
983                 message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
984                 message->param.disconnectinfo.cause = 28;
985                 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
986                 message_put(message);
987                 new_state(PORT_STATE_RELEASE);
988                 p_m_delete = 1;
989                 return;
990         }
991         
992         /* release if port is blocked */
993         if (p_m_mISDNport->ifport->block) {
994                 gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
995                 add_trace("failure", NULL, "Port blocked.");
996                 end_trace();
997                 message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
998                 message->param.disconnectinfo.cause = 27; // temp. unavail.
999                 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1000                 message_put(message);
1001                 new_state(PORT_STATE_RELEASE);
1002                 p_m_delete = 1;
1003                 return;
1004         }
1005
1006         /* hunt channel */
1007         ret = channel = hunt_bchannel();
1008         if (ret < 0)
1009                 goto no_channel;
1010         /* open channel */
1011         ret = seize_bchannel(channel, 1);
1012         if (ret < 0) {
1013                 no_channel:
1014                 gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
1015                 add_trace("failure", NULL, "No internal audio channel available.");
1016                 end_trace();
1017                 message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
1018                 message->param.disconnectinfo.cause = 34;
1019                 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1020                 message_put(message);
1021                 new_state(PORT_STATE_RELEASE);
1022                 p_m_delete = 1;
1023                 return;
1024         }
1025         bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE);
1026         if (bchannel_open(p_m_b_index))
1027                 goto no_channel;
1028
1029 //              SCPY(&p_m_tones_dir, param->setup.ext.tones_dir);
1030         /* screen outgoing caller id */
1031         do_screen(1, p_callerinfo.id, sizeof(p_callerinfo.id), &p_callerinfo.ntype, &p_callerinfo.present, p_m_mISDNport->ifport->interface);
1032
1033         /* attach only if not already */
1034         epointlist = p_epointlist;
1035         while(epointlist) {
1036                 if (epointlist->epoint_id == epoint_id)
1037                         break;
1038                 epointlist = epointlist->next;
1039         }
1040         if (!epointlist)
1041                 epointlist_new(epoint_id);
1042
1043         /* creating l3id */
1044         l1l2l3_trace_header(p_m_mISDNport, this, L3_NEW_L3ID_REQ, DIRECTION_OUT);
1045         p_m_g_callref = new_callref++;
1046         add_trace("callref", "new", "0x%x", p_m_g_callref);
1047         end_trace();
1048
1049         gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
1050         mncc = create_mncc(MNCC_SETUP_REQ, p_m_g_callref);
1051         /* caller information */
1052         mncc->fields |= MNCC_F_CALLING;
1053         mncc->calling.plan = 1;
1054         switch (p_callerinfo.ntype) {
1055                 case INFO_NTYPE_UNKNOWN:
1056                 mncc->calling.type = 0x0;
1057                 break;
1058                 case INFO_NTYPE_INTERNATIONAL:
1059                 mncc->calling.type = 0x1;
1060                 break;
1061                 case INFO_NTYPE_NATIONAL:
1062                 mncc->calling.type = 0x2;
1063                 break;
1064                 case INFO_NTYPE_SUBSCRIBER:
1065                 mncc->calling.type = 0x4;
1066                 break;
1067                 default: /* INFO_NTYPE_NOTPRESENT */
1068                 mncc->fields &= ~MNCC_F_CALLING;
1069                 break;
1070         }
1071         switch (p_callerinfo.screen) {
1072                 case INFO_SCREEN_USER:
1073                 mncc->calling.screen = 0;
1074                 break;
1075                 default: /* INFO_SCREEN_NETWORK */
1076                 mncc->calling.screen = 3;
1077                 break;
1078         }
1079         switch (p_callerinfo.present) {
1080                 case INFO_PRESENT_ALLOWED:
1081                 mncc->calling.present = 0;
1082                 break;
1083                 case INFO_PRESENT_RESTRICTED:
1084                 mncc->calling.present = 1;
1085                 break;
1086                 default: /* INFO_PRESENT_NOTAVAIL */
1087                 mncc->calling.present = 2;
1088                 break;
1089         }
1090         if (mncc->fields & MNCC_F_CALLING) {
1091                 SCPY(mncc->calling.number, p_callerinfo.id);
1092                 add_trace("calling", "type", "%d", mncc->calling.type);
1093                 add_trace("calling", "plan", "%d", mncc->calling.plan);
1094                 add_trace("calling", "present", "%d", mncc->calling.present);
1095                 add_trace("calling", "screen", "%d", mncc->calling.screen);
1096                 add_trace("calling", "number", "%s", mncc->calling.number);
1097         }
1098         /* dialing information */
1099         mncc->fields |= MNCC_F_CALLED;
1100         if (!strncmp(p_dialinginfo.id, "imsi-", 5)) {
1101                 SCPY(mncc->imsi, p_dialinginfo.id+5);
1102                 add_trace("dialing", "imsi", "%s", mncc->imsi);
1103         } else {
1104                 SCPY(mncc->called.number, p_dialinginfo.id);
1105                 add_trace("dialing", "number", "%s", mncc->called.number);
1106         }
1107         
1108         /* sending user-user */
1109
1110         /* redirecting number */
1111         mncc->fields |= MNCC_F_REDIRECTING;
1112         mncc->redirecting.plan = 1;
1113         switch (p_redirinfo.ntype) {
1114                 case INFO_NTYPE_UNKNOWN:
1115                 mncc->redirecting.type = 0x0;
1116                 break;
1117                 case INFO_NTYPE_INTERNATIONAL:
1118                 mncc->redirecting.type = 0x1;
1119                 break;
1120                 case INFO_NTYPE_NATIONAL:
1121                 mncc->redirecting.type = 0x2;
1122                 break;
1123                 case INFO_NTYPE_SUBSCRIBER:
1124                 mncc->redirecting.type = 0x4;
1125                 break;
1126                 default: /* INFO_NTYPE_NOTPRESENT */
1127                 mncc->fields &= ~MNCC_F_REDIRECTING;
1128                 break;
1129         }
1130         switch (p_redirinfo.screen) {
1131                 case INFO_SCREEN_USER:
1132                 mncc->redirecting.screen = 0;
1133                 break;
1134                 default: /* INFO_SCREE_NETWORK */
1135                 mncc->redirecting.screen = 3;
1136                 break;
1137         }
1138         switch (p_redirinfo.present) {
1139                 case INFO_PRESENT_ALLOWED:
1140                 mncc->redirecting.present = 0;
1141                 break;
1142                 case INFO_PRESENT_RESTRICTED:
1143                 mncc->redirecting.present = 1;
1144                 break;
1145                 default: /* INFO_PRESENT_NOTAVAIL */
1146                 mncc->redirecting.present = 2;
1147                 break;
1148         }
1149         /* sending redirecting number only in ntmode */
1150         if (mncc->fields & MNCC_F_REDIRECTING) {
1151                 SCPY(mncc->redirecting.number, p_redirinfo.id);
1152                 add_trace("redir", "type", "%d", mncc->redirecting.type);
1153                 add_trace("redir", "plan", "%d", mncc->redirecting.plan);
1154                 add_trace("redir", "present", "%d", mncc->redirecting.present);
1155                 add_trace("redir", "screen", "%d", mncc->redirecting.screen);
1156                 add_trace("redir", "number", "%s", mncc->redirecting.number);
1157         }
1158         /* bearer capability */
1159         //todo
1160
1161         end_trace();
1162         send_and_free_mncc((struct gsm_network *)gsm->network, mncc->msg_type, mncc);
1163
1164         new_state(PORT_STATE_OUT_SETUP);
1165
1166         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_PROCEEDING);
1167         message_put(message);
1168
1169         new_state(PORT_STATE_OUT_PROCEEDING);
1170 }
1171
1172 /* MESSAGE_NOTIFY */
1173 void Pgsm::message_notify(unsigned int epoint_id, int message_id, union parameter *param)
1174 {
1175         struct gsm_mncc *mncc;
1176         int notify;
1177
1178 //      printf("if = %d\n", param->notifyinfo.notify);
1179         if (param->notifyinfo.notify>INFO_NOTIFY_NONE) {
1180                 notify = param->notifyinfo.notify & 0x7f;
1181                 if (p_state!=PORT_STATE_CONNECT /*&& p_state!=PORT_STATE_IN_PROCEEDING*/ && p_state!=PORT_STATE_IN_ALERTING) {
1182                         /* queue notification */
1183                         if (p_m_g_notify_pending)
1184                                 message_free(p_m_g_notify_pending);
1185                         p_m_g_notify_pending = message_create(ACTIVE_EPOINT(p_epointlist), p_serial, EPOINT_TO_PORT, message_id);
1186                         memcpy(&p_m_g_notify_pending->param, param, sizeof(union parameter));
1187                 } else {
1188                         /* sending notification */
1189                         gsm_trace_header(p_m_mISDNport, this, MNCC_NOTIFY_REQ, DIRECTION_OUT);
1190                         add_trace("notify", NULL, "%d", notify);
1191                         end_trace();
1192                         mncc = create_mncc(MNCC_NOTIFY_REQ, p_m_g_callref);
1193                         mncc->notify = notify;
1194                         send_and_free_mncc((struct gsm_network *)gsm->network, mncc->msg_type, mncc);
1195                 }
1196         }
1197 }
1198
1199 /* MESSAGE_ALERTING */
1200 void Pgsm::message_alerting(unsigned int epoint_id, int message_id, union parameter *param)
1201 {
1202         struct gsm_mncc *mncc;
1203
1204         /* send alert */
1205         gsm_trace_header(p_m_mISDNport, this, MNCC_ALERT_REQ, DIRECTION_OUT);
1206         mncc = create_mncc(MNCC_ALERT_REQ, p_m_g_callref);
1207         if (p_m_mISDNport->tones) {
1208                 mncc->fields |= MNCC_F_PROGRESS;
1209                 mncc->progress.coding = 3; /* GSM */
1210                 mncc->progress.location = 1;
1211                 mncc->progress.descr = 8;
1212                 add_trace("progress", "coding", "%d", mncc->progress.coding);
1213                 add_trace("progress", "location", "%d", mncc->progress.location);
1214                 add_trace("progress", "descr", "%d", mncc->progress.descr);
1215         }
1216         end_trace();
1217         send_and_free_mncc((struct gsm_network *)gsm->network, mncc->msg_type, mncc);
1218
1219         new_state(PORT_STATE_IN_ALERTING);
1220
1221         if (p_m_mISDNport->tones && !p_m_g_tch_connected) { /* only if ... */
1222                 gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
1223                 end_trace();
1224                 mncc = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
1225                 send_and_free_mncc((struct gsm_network *)gsm->network, mncc->msg_type, mncc);
1226                 p_m_g_tch_connected = 1;
1227         }
1228 }
1229
1230 /* MESSAGE_CONNECT */
1231 void Pgsm::message_connect(unsigned int epoint_id, int message_id, union parameter *param)
1232 {
1233         struct gsm_mncc *mncc;
1234
1235         /* copy connected information */
1236         memcpy(&p_connectinfo, &param->connectinfo, sizeof(p_connectinfo));
1237         /* screen outgoing caller id */
1238         do_screen(1, p_connectinfo.id, sizeof(p_connectinfo.id), &p_connectinfo.ntype, &p_connectinfo.present, p_m_mISDNport->ifport->interface);
1239
1240         /* send connect */
1241         mncc = create_mncc(MNCC_SETUP_RSP, p_m_g_callref);
1242         gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_RSP, DIRECTION_OUT);
1243         /* caller information */
1244         mncc->fields |= MNCC_F_CONNECTED;
1245         mncc->connected.plan = 1;
1246         switch (p_callerinfo.ntype) {
1247                 case INFO_NTYPE_UNKNOWN:
1248                 mncc->connected.type = 0x0;
1249                 break;
1250                 case INFO_NTYPE_INTERNATIONAL:
1251                 mncc->connected.type = 0x1;
1252                 break;
1253                 case INFO_NTYPE_NATIONAL:
1254                 mncc->connected.type = 0x2;
1255                 break;
1256                 case INFO_NTYPE_SUBSCRIBER:
1257                 mncc->connected.type = 0x4;
1258                 break;
1259                 default: /* INFO_NTYPE_NOTPRESENT */
1260                 mncc->fields &= ~MNCC_F_CONNECTED;
1261                 break;
1262         }
1263         switch (p_callerinfo.screen) {
1264                 case INFO_SCREEN_USER:
1265                 mncc->connected.screen = 0;
1266                 break;
1267                 default: /* INFO_SCREEN_NETWORK */
1268                 mncc->connected.screen = 3;
1269                 break;
1270         }
1271         switch (p_callerinfo.present) {
1272                 case INFO_PRESENT_ALLOWED:
1273                 mncc->connected.present = 0;
1274                 break;
1275                 case INFO_PRESENT_RESTRICTED:
1276                 mncc->connected.present = 1;
1277                 break;
1278                 default: /* INFO_PRESENT_NOTAVAIL */
1279                 mncc->connected.present = 2;
1280                 break;
1281         }
1282         if (mncc->fields & MNCC_F_CONNECTED) {
1283                 SCPY(mncc->connected.number, p_connectinfo.id);
1284                 add_trace("connected", "type", "%d", mncc->connected.type);
1285                 add_trace("connected", "plan", "%d", mncc->connected.plan);
1286                 add_trace("connected", "present", "%d", mncc->connected.present);
1287                 add_trace("connected", "screen", "%d", mncc->connected.screen);
1288                 add_trace("connected", "number", "%s", mncc->connected.number);
1289         }
1290         end_trace();
1291         send_and_free_mncc((struct gsm_network *)gsm->network, mncc->msg_type, mncc);
1292
1293         new_state(PORT_STATE_CONNECT_WAITING);
1294 }
1295
1296 /* MESSAGE_DISCONNECT */
1297 void Pgsm::message_disconnect(unsigned int epoint_id, int message_id, union parameter *param)
1298 {
1299         struct gsm_mncc *mncc;
1300
1301         /* send disconnect */
1302         mncc = create_mncc(MNCC_DISC_REQ, p_m_g_callref);
1303         gsm_trace_header(p_m_mISDNport, this, MNCC_DISC_REQ, DIRECTION_OUT);
1304         if (p_m_mISDNport->tones) {
1305                 mncc->fields |= MNCC_F_PROGRESS;
1306                 mncc->progress.coding = 3; /* GSM */
1307                 mncc->progress.location = 1;
1308                 mncc->progress.descr = 8;
1309                 add_trace("progress", "coding", "%d", mncc->progress.coding);
1310                 add_trace("progress", "location", "%d", mncc->progress.location);
1311                 add_trace("progress", "descr", "%d", mncc->progress.descr);
1312         }
1313         mncc->fields |= MNCC_F_CAUSE;
1314         mncc->cause.coding = 3;
1315         mncc->cause.location = param->disconnectinfo.location;
1316         mncc->cause.value = param->disconnectinfo.cause;
1317         add_trace("cause", "coding", "%d", mncc->cause.coding);
1318         add_trace("cause", "location", "%d", mncc->cause.location);
1319         add_trace("cause", "value", "%d", mncc->cause.value);
1320         end_trace();
1321         send_and_free_mncc((struct gsm_network *)gsm->network, mncc->msg_type, mncc);
1322
1323         new_state(PORT_STATE_OUT_DISCONNECT);
1324
1325         if (p_m_mISDNport->tones && !p_m_g_tch_connected) { /* only if ... */
1326                 gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
1327                 end_trace();
1328                 mncc = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
1329                 send_and_free_mncc((struct gsm_network *)gsm->network, mncc->msg_type, mncc);
1330                 p_m_g_tch_connected = 1;
1331         }
1332 }
1333
1334
1335 /* MESSAGE_RELEASE */
1336 void Pgsm::message_release(unsigned int epoint_id, int message_id, union parameter *param)
1337 {
1338         struct gsm_mncc *mncc;
1339
1340         /* send release */
1341         mncc = create_mncc(MNCC_REL_REQ, p_m_g_callref);
1342         gsm_trace_header(p_m_mISDNport, this, MNCC_REL_REQ, DIRECTION_OUT);
1343         mncc->fields |= MNCC_F_CAUSE;
1344         mncc->cause.coding = 3;
1345         mncc->cause.location = param->disconnectinfo.location;
1346         mncc->cause.value = param->disconnectinfo.cause;
1347         add_trace("cause", "coding", "%d", mncc->cause.coding);
1348         add_trace("cause", "location", "%d", mncc->cause.location);
1349         add_trace("cause", "value", "%d", mncc->cause.value);
1350         end_trace();
1351         send_and_free_mncc((struct gsm_network *)gsm->network, mncc->msg_type, mncc);
1352
1353         new_state(PORT_STATE_RELEASE);
1354         p_m_delete = 1;
1355         return;
1356 }
1357
1358
1359 /*
1360  * endpoint sends messages to the port
1361  */
1362 int Pgsm::message_epoint(unsigned int epoint_id, int message_id, union parameter *param)
1363 {
1364         if (PmISDN::message_epoint(epoint_id, message_id, param))
1365                 return(1);
1366
1367         switch(message_id) {
1368                 case MESSAGE_SETUP: /* dial-out command received from epoint */
1369                 if (p_state!=PORT_STATE_IDLE)
1370                         break;
1371                 message_setup(epoint_id, message_id, param);
1372                 break;
1373
1374                 case MESSAGE_NOTIFY: /* display and notifications */
1375                 message_notify(epoint_id, message_id, param);
1376                 break;
1377
1378 //              case MESSAGE_FACILITY: /* facility message */
1379 //              message_facility(epoint_id, message_id, param);
1380 //              break;
1381
1382                 case MESSAGE_PROCEEDING: /* message not handles */
1383                 break;
1384
1385                 case MESSAGE_ALERTING: /* call of endpoint is ringing */
1386                 if (p_state!=PORT_STATE_IN_PROCEEDING)
1387                         break;
1388                 message_alerting(epoint_id, message_id, param);
1389                 if (p_m_g_notify_pending) {
1390                         /* send pending notify message during connect */
1391                         message_notify(ACTIVE_EPOINT(p_epointlist), p_m_g_notify_pending->type, &p_m_g_notify_pending->param);
1392                         message_free(p_m_g_notify_pending);
1393                         p_m_g_notify_pending = NULL;
1394                 }
1395                 break;
1396
1397                 case MESSAGE_CONNECT: /* call of endpoint is connected */
1398                 if (p_state!=PORT_STATE_IN_PROCEEDING
1399                  && p_state!=PORT_STATE_IN_ALERTING)
1400                         break;
1401                 message_connect(epoint_id, message_id, param);
1402                 if (p_m_g_notify_pending) {
1403                         /* send pending notify message during connect */
1404                         message_notify(ACTIVE_EPOINT(p_epointlist), p_m_g_notify_pending->type, &p_m_g_notify_pending->param);
1405                         message_free(p_m_g_notify_pending);
1406                         p_m_g_notify_pending = NULL;
1407                 }
1408                 break;
1409
1410                 case MESSAGE_DISCONNECT: /* call has been disconnected */
1411                 if (p_state!=PORT_STATE_IN_PROCEEDING
1412                  && p_state!=PORT_STATE_IN_ALERTING
1413                  && p_state!=PORT_STATE_OUT_SETUP
1414                  && p_state!=PORT_STATE_OUT_OVERLAP
1415                  && p_state!=PORT_STATE_OUT_PROCEEDING
1416                  && p_state!=PORT_STATE_OUT_ALERTING
1417                  && p_state!=PORT_STATE_CONNECT
1418                  && p_state!=PORT_STATE_CONNECT_WAITING)
1419                         break;
1420                 message_disconnect(epoint_id, message_id, param);
1421                 break;
1422
1423                 case MESSAGE_RELEASE: /* release isdn port */
1424                 if (p_state==PORT_STATE_RELEASE)
1425                         break;
1426                 message_release(epoint_id, message_id, param);
1427                 break;
1428
1429                 default:
1430                 PDEBUG(DEBUG_GSM, "Pgsm(%s) gsm port with (caller id %s) received unhandled nessage: %d\n", p_name, p_callerinfo.id, message_id);
1431         }
1432
1433         return(1);
1434 }
1435
1436
1437 /*
1438  * handler
1439  */
1440 int Pgsm::handler(void)
1441 {
1442         int ret;
1443         int work = 0;
1444         unsigned char buffer[2048+MISDN_HEADER_LEN];
1445         struct mISDNhead *hh = (struct mISDNhead *)buffer;
1446
1447         if ((ret = PmISDN::handler()))
1448                 return(ret);
1449
1450         /* handle destruction */
1451         if (p_m_delete) {
1452                 delete this;
1453                 return(-1);
1454         }
1455
1456         /* handle message from bchannel */
1457         if (p_m_g_gsm_b_sock > -1) {
1458                 ret = recv(p_m_g_gsm_b_sock, buffer, sizeof(buffer), 0);
1459                 if (ret >= (int)MISDN_HEADER_LEN) {
1460                         switch(hh->prim) {
1461                                 /* we don't care about confirms, we use rx data to sync tx */
1462                                 case PH_DATA_CNF:
1463                                 break;
1464                                 /* we receive audio data, we respond to it AND we send tones */
1465                                 case PH_DATA_IND:
1466                                 bchannel_receive(hh, buffer+MISDN_HEADER_LEN, ret-MISDN_HEADER_LEN);
1467                                 break;
1468                                 case PH_ACTIVATE_IND:
1469                                 p_m_g_gsm_b_active = 1;
1470                                 break;
1471                                 case PH_DEACTIVATE_IND:
1472                                 p_m_g_gsm_b_active = 0;
1473                                 break;
1474                         }
1475                         work = 1;
1476                 } else {
1477                         if (ret < 0 && errno != EWOULDBLOCK)
1478                                 PERROR("Read from GSM port, index %d failed with return code %d\n", ret);
1479                 }
1480         }
1481
1482         return(work);
1483 }
1484
1485
1486 /*
1487  * handles bsc select function within LCR's main loop
1488  */
1489 int handle_gsm(void)
1490 {
1491         int ret1, ret2;
1492
1493         ret1 = bsc_upqueue((struct gsm_network *)gsm->network);
1494         ret2 = bsc_select_main(1); /* polling */
1495         if (ret1 || ret2)
1496                 return 1;
1497         return 0;
1498 }
1499
1500 static void gsm_sock_close(void)
1501 {
1502         if (gsm->gsm_sock > -1)
1503                 close(gsm->gsm_sock);
1504         gsm->gsm_sock = -1;
1505 }
1506
1507 static int gsm_sock_open(char *portname)
1508 {
1509         int ret;
1510         int cnt;
1511         unsigned long on = 1;
1512         struct sockaddr_mISDN addr;
1513         struct mISDN_devinfo devinfo;
1514         int pri, bri;
1515
1516         /* check port counts */
1517         ret = ioctl(mISDNsocket, IMGETCOUNT, &cnt);
1518         if (ret < 0) {
1519                 fprintf(stderr, "Cannot get number of mISDN devices. (ioctl IMGETCOUNT failed ret=%d)\n", ret);
1520                 return(ret);
1521         }
1522
1523         if (cnt <= 0) {
1524                 PERROR_RUNTIME("Found no card. Please be sure to load card drivers.\n");
1525                 return -EIO;
1526         }
1527         gsm->gsm_port = mISDN_getportbyname(mISDNsocket, cnt, portname);
1528         if (gsm->gsm_port < 0) {
1529                 PERROR_RUNTIME("Port name '%s' not found, did you load loopback interface for GSM?.\n", portname);
1530                 return gsm->gsm_port;
1531         }
1532         /* get protocol */
1533         bri = pri = 0;
1534         devinfo.id = gsm->gsm_port;
1535         ret = ioctl(mISDNsocket, IMGETDEVINFO, &devinfo);
1536         if (ret < 0) {
1537                 PERROR_RUNTIME("Cannot get device information for port %d. (ioctl IMGETDEVINFO failed ret=%d)\n", gsm->gsm_port, ret);
1538                 return ret;
1539         }
1540         if (devinfo.Dprotocols & (1 << ISDN_P_TE_S0)) {
1541                 bri = 1;
1542         }
1543         if (devinfo.Dprotocols & (1 << ISDN_P_TE_E1)) {
1544                 pri = 1;
1545         }
1546         if (!pri && !pri) {
1547                 PERROR_RUNTIME("GSM port %d does not support TE PRI or TE BRI.\n", gsm->gsm_port);
1548         }
1549         /* open socket */
1550         if ((gsm->gsm_sock = socket(PF_ISDN, SOCK_DGRAM, (pri)?ISDN_P_TE_E1:ISDN_P_TE_S0)) < 0) {
1551                 PERROR_RUNTIME("GSM port %d failed to open socket.\n", gsm->gsm_port);
1552                 gsm_sock_close();
1553                 return gsm->gsm_sock;
1554         }
1555         /* set nonblocking io */
1556         if ((ret = ioctl(gsm->gsm_sock, FIONBIO, &on)) < 0) {
1557                 PERROR_RUNTIME("GSM port %d failed to set socket into nonblocking io.\n", gsm->gsm_port);
1558                 gsm_sock_close();
1559                 return ret;
1560         }
1561         /* bind socket to dchannel */
1562         memset(&addr, 0, sizeof(addr));
1563         addr.family = AF_ISDN;
1564         addr.dev = gsm->gsm_port;
1565         addr.channel = 0;
1566         if ((ret = bind(gsm->gsm_sock, (struct sockaddr *)&addr, sizeof(addr))) < 0) {
1567                 PERROR_RUNTIME("GSM port %d failed to bind socket. (name = %s errno=%d)\n", gsm->gsm_port, portname, errno);
1568                 gsm_sock_close();
1569                 return (ret);
1570         }
1571
1572         return 0;
1573 }
1574
1575
1576 int gsm_exit(int rc)
1577 {
1578         /* free gsm instance */
1579         if (gsm) {
1580                 if (gsm->gsm_sock > -1)
1581                         gsm_sock_close();
1582                 /* shutdown network */
1583                 if (gsm->network)
1584                         bsc_shutdown_net((struct gsm_network *)gsm->network);
1585                 /* free network */
1586 //              if (gsm->network) {
1587 //                      free((struct gsm_network *)gsm->network); /* TBD */
1588 //              }
1589                 free(gsm);
1590                 gsm = NULL;
1591         }
1592
1593         return(rc);
1594 }
1595
1596 int gsm_init(void)
1597 {
1598         char hlr[128], cfg[128], filename[128];
1599         mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
1600         int pcapfd, rc;
1601
1602         tall_bsc_ctx = talloc_named_const(NULL, 1, "openbsc");
1603         talloc_ctx_init();
1604         on_dso_load_token();
1605         on_dso_load_rrlp();
1606
1607         /* seed the PRNG */
1608         srand(time(NULL));
1609
1610         /* create gsm instance */
1611         gsm = (struct lcr_gsm *)MALLOC(sizeof(struct lcr_gsm));
1612         gsm->gsm_sock = -1;
1613
1614         /* parse options */
1615         if (!gsm_conf(&gsm->conf)) {
1616                 PERROR("%s", gsm_conf_error);
1617                 return gsm_exit(-EINVAL);
1618         }
1619
1620         /* set debug */
1621         stderr_target = debug_target_create_stderr();
1622         if (gsm->conf.debug[0])
1623                 debug_parse_category_mask(stderr_target, gsm->conf.debug);
1624
1625         /* open pcap file */
1626         if (gsm->conf.pcapfile[0]) {
1627                 if (gsm->conf.pcapfile[0] == '/')
1628                         SCPY(filename, gsm->conf.pcapfile);
1629                 else
1630                         SPRINT(filename, "%s/%s", CONFIG_DATA, gsm->conf.pcapfile);
1631                 pcapfd = open(filename, O_WRONLY|O_TRUNC|O_CREAT, mode);
1632                 if (pcapfd < 0) {
1633                         PERROR("Failed to open file for pcap\n");
1634                         return gsm_exit(-1);
1635                 }
1636                 e1_set_pcap_fd(pcapfd);
1637         }
1638
1639         /* use RTP proxy for audio streaming */
1640         ipacc_rtp_direct = 0;
1641
1642         /* init database */
1643         if (gsm->conf.hlr[0] == '/')
1644                 SCPY(hlr, gsm->conf.hlr);
1645         else
1646                 SPRINT(hlr, "%s/%s", CONFIG_DATA, gsm->conf.hlr);
1647         if (db_init(hlr)) {
1648                 PERROR("GSM DB: Failed to init database '%s'. Please check the option settings.\n", hlr);
1649                 return gsm_exit(-1);
1650         }
1651         printf("DB: Database initialized.\n");
1652         if (db_prepare()) {
1653                 PERROR("GSM DB: Failed to prepare database.\n");
1654                 return gsm_exit(-1);
1655         }
1656         printf("DB: Database prepared.\n");
1657
1658         /* bootstrap network */
1659         if (gsm->conf.openbsc_cfg[0] == '/')
1660                 SCPY(cfg, gsm->conf.openbsc_cfg);
1661         else
1662                 SPRINT(cfg, "%s/%s", CONFIG_DATA, gsm->conf.openbsc_cfg);
1663         rc = bsc_bootstrap_network(&message_bsc, cfg);
1664         if (rc < 0) {
1665                 PERROR("Failed to bootstrap GSM network.\n");
1666                 return gsm_exit(-1);
1667         }
1668         gsm->network = bsc_gsmnet;
1669
1670         /* open gsm loop interface */
1671         if (gsm_sock_open(gsm->conf.interface_bsc)) {
1672                 return gsm_exit(-1);
1673         }
1674
1675         return 0;
1676 }
1677