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