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