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