77ec79131f890574c3b864d6bc900830fd40b371
[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         mode = create_mncc(MNCC_LCHAN_MODIFY, p_m_g_callref);
619         mode->lchan_mode = 0x01; /* GSM V1 */
620         add_trace("mode", NULL, "0x%02x", mode->lchan_mode);
621         send_and_free_mncc(gsm->network, mode->msg_type, mode);
622         end_trace();
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                 case MNCC_REJ_IND:
931                 pgsm->rel_ind(msg_type, callref, mncc);
932                 break;
933
934                 case MNCC_NOTIFY_IND:
935                 pgsm->notify_ind(msg_type, callref, mncc);
936                 break;
937
938                 case MNCC_HOLD_IND:
939                 pgsm->hold_ind(msg_type, callref, mncc);
940                 break;
941
942                 case MNCC_RETRIEVE_IND:
943                 pgsm->retr_ind(msg_type, callref, mncc);
944                 break;
945
946                 default:
947                 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);
948         }
949         return(0);
950 }
951
952 /* MESSAGE_SETUP */
953 void Pgsm::message_setup(unsigned int epoint_id, int message_id, union parameter *param)
954 {
955         struct lcr_msg *message;
956         int ret;
957         struct epoint_list *epointlist;
958         struct gsm_mncc *mncc;
959         int channel;
960
961         /* copy setup infos to port */
962         memcpy(&p_callerinfo, &param->setup.callerinfo, sizeof(p_callerinfo));
963         memcpy(&p_dialinginfo, &param->setup.dialinginfo, sizeof(p_dialinginfo));
964         memcpy(&p_capainfo, &param->setup.capainfo, sizeof(p_capainfo));
965         memcpy(&p_redirinfo, &param->setup.redirinfo, sizeof(p_redirinfo));
966
967         /* no number */
968         if (!p_dialinginfo.id[0]) {
969                 gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
970                 add_trace("failure", NULL, "No dialed subscriber given.");
971                 end_trace();
972                 message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
973                 message->param.disconnectinfo.cause = 28;
974                 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
975                 message_put(message);
976                 new_state(PORT_STATE_RELEASE);
977                 p_m_delete = 1;
978                 return;
979         }
980         
981         /* release if port is blocked */
982         if (p_m_mISDNport->ifport->block) {
983                 gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
984                 add_trace("failure", NULL, "Port blocked.");
985                 end_trace();
986                 message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
987                 message->param.disconnectinfo.cause = 27; // temp. unavail.
988                 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
989                 message_put(message);
990                 new_state(PORT_STATE_RELEASE);
991                 p_m_delete = 1;
992                 return;
993         }
994
995         /* hunt channel */
996         ret = channel = hunt_bchannel();
997         if (ret < 0)
998                 goto no_channel;
999         /* open channel */
1000         ret = seize_bchannel(channel, 1);
1001         if (ret < 0) {
1002                 no_channel:
1003                 gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
1004                 add_trace("failure", NULL, "No internal audio channel available.");
1005                 end_trace();
1006                 message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
1007                 message->param.disconnectinfo.cause = 34;
1008                 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1009                 message_put(message);
1010                 new_state(PORT_STATE_RELEASE);
1011                 p_m_delete = 1;
1012                 return;
1013         }
1014         bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE);
1015         if (bchannel_open(p_m_b_index))
1016                 goto no_channel;
1017
1018 //              SCPY(&p_m_tones_dir, param->setup.ext.tones_dir);
1019         /* screen outgoing caller id */
1020         do_screen(1, p_callerinfo.id, sizeof(p_callerinfo.id), &p_callerinfo.ntype, &p_callerinfo.present, p_m_mISDNport->ifport->interface);
1021         do_screen(1, p_callerinfo.id2, sizeof(p_callerinfo.id2), &p_callerinfo.ntype2, &p_callerinfo.present2, p_m_mISDNport->ifport->interface);
1022
1023         /* attach only if not already */
1024         epointlist = p_epointlist;
1025         while(epointlist) {
1026                 if (epointlist->epoint_id == epoint_id)
1027                         break;
1028                 epointlist = epointlist->next;
1029         }
1030         if (!epointlist)
1031                 epointlist_new(epoint_id);
1032
1033         /* creating l3id */
1034         l1l2l3_trace_header(p_m_mISDNport, this, L3_NEW_L3ID_REQ, DIRECTION_OUT);
1035         p_m_g_callref = new_callref++;
1036         add_trace("callref", "new", "0x%x", p_m_g_callref);
1037         end_trace();
1038
1039         gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
1040         mncc = create_mncc(MNCC_SETUP_REQ, p_m_g_callref);
1041         /* caller information */
1042         mncc->calling = 1;
1043         mncc->calling_plan = 1;
1044         switch (p_callerinfo.ntype) {
1045                 case INFO_NTYPE_UNKNOWN:
1046                 mncc->calling_type = 0x0;
1047                 break;
1048                 case INFO_NTYPE_INTERNATIONAL:
1049                 mncc->calling_type = 0x1;
1050                 break;
1051                 case INFO_NTYPE_NATIONAL:
1052                 mncc->calling_type = 0x2;
1053                 break;
1054                 case INFO_NTYPE_SUBSCRIBER:
1055                 mncc->calling_type = 0x4;
1056                 break;
1057                 default: /* INFO_NTYPE_NOTPRESENT */
1058                 mncc->calling = 0;
1059                 break;
1060         }
1061         switch (p_callerinfo.screen) {
1062                 case INFO_SCREEN_USER:
1063                 mncc->calling_screen = 0;
1064                 break;
1065                 default: /* INFO_SCREEN_NETWORK */
1066                 mncc->calling_screen = 3;
1067                 break;
1068         }
1069         switch (p_callerinfo.present) {
1070                 case INFO_PRESENT_ALLOWED:
1071                 mncc->calling_present = 0;
1072                 break;
1073                 case INFO_PRESENT_RESTRICTED:
1074                 mncc->calling_present = 1;
1075                 break;
1076                 default: /* INFO_PRESENT_NOTAVAIL */
1077                 mncc->calling_present = 2;
1078                 break;
1079         }
1080         if (mncc->calling) {
1081                 SCPY(mncc->calling_number, p_callerinfo.id);
1082                 add_trace("calling", "type", "%d", mncc->calling_type);
1083                 add_trace("calling", "plan", "%d", mncc->calling_plan);
1084                 add_trace("calling", "present", "%d", mncc->calling_present);
1085                 add_trace("calling", "screen", "%d", mncc->calling_screen);
1086                 add_trace("calling", "number", "%s", mncc->calling_number);
1087         }
1088         /* dialing information */
1089         mncc->called = 1;
1090         SCPY(mncc->called_number, p_dialinginfo.id);
1091         add_trace("dialing", "number", "%s", mncc->calling_number);
1092         
1093         /* sending user-user */
1094
1095         /* redirecting number */
1096         mncc->redirecting = 1;
1097         mncc->redirecting_plan = 1;
1098         switch (p_redirinfo.ntype) {
1099                 case INFO_NTYPE_UNKNOWN:
1100                 mncc->redirecting_type = 0x0;
1101                 break;
1102                 case INFO_NTYPE_INTERNATIONAL:
1103                 mncc->redirecting_type = 0x1;
1104                 break;
1105                 case INFO_NTYPE_NATIONAL:
1106                 mncc->redirecting_type = 0x2;
1107                 break;
1108                 case INFO_NTYPE_SUBSCRIBER:
1109                 mncc->redirecting_type = 0x4;
1110                 break;
1111                 default: /* INFO_NTYPE_NOTPRESENT */
1112                 mncc->redirecting = 0;
1113                 break;
1114         }
1115         switch (p_redirinfo.screen) {
1116                 case INFO_SCREEN_USER:
1117                 mncc->redirecting_screen = 0;
1118                 break;
1119                 default: /* INFO_SCREE_NETWORK */
1120                 mncc->redirecting_screen = 3;
1121                 break;
1122         }
1123         switch (p_redirinfo.present) {
1124                 case INFO_PRESENT_ALLOWED:
1125                 mncc->redirecting_present = 0;
1126                 break;
1127                 case INFO_PRESENT_RESTRICTED:
1128                 mncc->redirecting_present = 1;
1129                 break;
1130                 default: /* INFO_PRESENT_NOTAVAIL */
1131                 mncc->redirecting_present = 2;
1132                 break;
1133         }
1134         /* sending redirecting number only in ntmode */
1135         if (mncc->redirecting) {
1136                 SCPY(mncc->redirecting_number, p_redirinfo.id);
1137                 add_trace("redir", "type", "%d", mncc->redirecting_type);
1138                 add_trace("redir", "plan", "%d", mncc->redirecting_plan);
1139                 add_trace("redir", "present", "%d", mncc->redirecting_present);
1140                 add_trace("redir", "screen", "%d", mncc->redirecting_screen);
1141                 add_trace("redir", "number", "%s", mncc->redirecting_number);
1142         }
1143         /* bearer capability */
1144         //todo
1145
1146         send_and_free_mncc(gsm->network, mncc->msg_type, mncc);
1147         end_trace();
1148
1149         new_state(PORT_STATE_OUT_SETUP);
1150
1151         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_PROCEEDING);
1152         message_put(message);
1153
1154         new_state(PORT_STATE_OUT_PROCEEDING);
1155 }
1156
1157 /* MESSAGE_NOTIFY */
1158 void Pgsm::message_notify(unsigned int epoint_id, int message_id, union parameter *param)
1159 {
1160         struct gsm_mncc *mncc;
1161         int notify;
1162
1163         printf("if = %d\n", param->notifyinfo.notify);
1164         if (param->notifyinfo.notify>INFO_NOTIFY_NONE) {
1165                 notify = param->notifyinfo.notify & 0x7f;
1166                 if (p_state!=PORT_STATE_CONNECT /*&& p_state!=PORT_STATE_IN_PROCEEDING*/ && p_state!=PORT_STATE_IN_ALERTING) {
1167                         /* queue notification */
1168                         if (p_m_g_notify_pending)
1169                                 message_free(p_m_g_notify_pending);
1170                         p_m_g_notify_pending = message_create(ACTIVE_EPOINT(p_epointlist), p_serial, EPOINT_TO_PORT, message_id);
1171                         memcpy(&p_m_g_notify_pending->param, param, sizeof(union parameter));
1172                 } else {
1173                         /* sending notification */
1174                         gsm_trace_header(p_m_mISDNport, this, MNCC_NOTIFY_REQ, DIRECTION_OUT);
1175                         add_trace("notify", NULL, "%d", notify);
1176                         end_trace();
1177                         mncc = create_mncc(MNCC_NOTIFY_REQ, p_m_g_callref);
1178                         mncc->notify = notify;
1179                         send_and_free_mncc(gsm->network, mncc->msg_type, mncc);
1180                 }
1181         }
1182 }
1183
1184 /* MESSAGE_ALERTING */
1185 void Pgsm::message_alerting(unsigned int epoint_id, int message_id, union parameter *param)
1186 {
1187         struct gsm_mncc *mncc;
1188
1189         /* send alert */
1190         gsm_trace_header(p_m_mISDNport, this, MNCC_ALERT_REQ, DIRECTION_OUT);
1191         mncc = create_mncc(MNCC_ALERT_REQ, p_m_g_callref);
1192         if (p_m_mISDNport->tones) {
1193                 mncc->progress = 1;
1194                 mncc->progress_coding = 3; /* GSM */
1195                 mncc->progress_location = 1;
1196                 mncc->progress_descr = 8;
1197                 add_trace("progress", "coding", "%d", mncc->progress_coding);
1198                 add_trace("progress", "location", "%d", mncc->progress_location);
1199                 add_trace("progress", "descr", "%d", mncc->progress_descr);
1200         }
1201         send_and_free_mncc(gsm->network, mncc->msg_type, mncc);
1202         end_trace();
1203
1204         new_state(PORT_STATE_IN_ALERTING);
1205
1206         if (p_m_mISDNport->tones && !p_m_g_tch_connected) { /* only if ... */
1207                 gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
1208                 end_trace();
1209                 mncc = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
1210                 send_and_free_mncc(gsm->network, mncc->msg_type, mncc);
1211                 p_m_g_tch_connected = 1;
1212         }
1213 }
1214
1215 /* MESSAGE_CONNECT */
1216 void Pgsm::message_connect(unsigned int epoint_id, int message_id, union parameter *param)
1217 {
1218         struct gsm_mncc *mncc;
1219
1220         /* copy connected information */
1221         memcpy(&p_connectinfo, &param->connectinfo, sizeof(p_connectinfo));
1222         /* screen outgoing caller id */
1223         do_screen(1, p_connectinfo.id, sizeof(p_connectinfo.id), &p_connectinfo.ntype, &p_connectinfo.present, p_m_mISDNport->ifport->interface);
1224
1225         /* send connect */
1226         mncc = create_mncc(MNCC_SETUP_RSP, p_m_g_callref);
1227         gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_RSP, DIRECTION_OUT);
1228         /* caller information */
1229         mncc->connected = 1;
1230         mncc->connected_plan = 1;
1231         switch (p_callerinfo.ntype) {
1232                 case INFO_NTYPE_UNKNOWN:
1233                 mncc->connected_type = 0x0;
1234                 break;
1235                 case INFO_NTYPE_INTERNATIONAL:
1236                 mncc->connected_type = 0x1;
1237                 break;
1238                 case INFO_NTYPE_NATIONAL:
1239                 mncc->connected_type = 0x2;
1240                 break;
1241                 case INFO_NTYPE_SUBSCRIBER:
1242                 mncc->connected_type = 0x4;
1243                 break;
1244                 default: /* INFO_NTYPE_NOTPRESENT */
1245                 mncc->connected = 0;
1246                 break;
1247         }
1248         switch (p_callerinfo.screen) {
1249                 case INFO_SCREEN_USER:
1250                 mncc->connected_screen = 0;
1251                 break;
1252                 default: /* INFO_SCREEN_NETWORK */
1253                 mncc->connected_screen = 3;
1254                 break;
1255         }
1256         switch (p_callerinfo.present) {
1257                 case INFO_PRESENT_ALLOWED:
1258                 mncc->connected_present = 0;
1259                 break;
1260                 case INFO_PRESENT_RESTRICTED:
1261                 mncc->connected_present = 1;
1262                 break;
1263                 default: /* INFO_PRESENT_NOTAVAIL */
1264                 mncc->connected_present = 2;
1265                 break;
1266         }
1267         if (mncc->connected) {
1268                 SCPY(mncc->connected_number, p_connectinfo.id);
1269                 add_trace("connected", "type", "%d", mncc->connected_type);
1270                 add_trace("connected", "plan", "%d", mncc->connected_plan);
1271                 add_trace("connected", "present", "%d", mncc->connected_present);
1272                 add_trace("connected", "screen", "%d", mncc->connected_screen);
1273                 add_trace("connected", "number", "%s", mncc->connected_number);
1274         }
1275         end_trace();
1276         send_and_free_mncc(gsm->network, mncc->msg_type, mncc);
1277
1278         new_state(PORT_STATE_CONNECT_WAITING);
1279 }
1280
1281 /* MESSAGE_DISCONNECT */
1282 void Pgsm::message_disconnect(unsigned int epoint_id, int message_id, union parameter *param)
1283 {
1284         struct gsm_mncc *mncc;
1285
1286         /* send disconnect */
1287         mncc = create_mncc(MNCC_DISC_REQ, p_m_g_callref);
1288         gsm_trace_header(p_m_mISDNport, this, MNCC_DISC_REQ, DIRECTION_OUT);
1289         if (p_m_mISDNport->tones) {
1290                 mncc->progress = 1;
1291                 mncc->progress_coding = 3; /* GSM */
1292                 mncc->progress_location = 1;
1293                 mncc->progress_descr = 8;
1294                 add_trace("progress", "coding", "%d", mncc->progress_coding);
1295                 add_trace("progress", "location", "%d", mncc->progress_location);
1296                 add_trace("progress", "descr", "%d", mncc->progress_descr);
1297         }
1298         mncc->cause = 1;
1299         mncc->cause_location = param->disconnectinfo.location;
1300         mncc->cause_value = param->disconnectinfo.cause;
1301         add_trace("cause", "location", "%d", mncc->cause_location);
1302         add_trace("cause", "value", "%d", mncc->cause_value);
1303         end_trace();
1304         send_and_free_mncc(gsm->network, mncc->msg_type, mncc);
1305
1306         new_state(PORT_STATE_OUT_DISCONNECT);
1307
1308         if (p_m_mISDNport->tones && !p_m_g_tch_connected) { /* only if ... */
1309                 gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
1310                 end_trace();
1311                 mncc = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
1312                 send_and_free_mncc(gsm->network, mncc->msg_type, mncc);
1313                 p_m_g_tch_connected = 1;
1314         }
1315 }
1316
1317
1318 /* MESSAGE_RELEASE */
1319 void Pgsm::message_release(unsigned int epoint_id, int message_id, union parameter *param)
1320 {
1321         struct gsm_mncc *mncc;
1322
1323         /* send release */
1324         mncc = create_mncc(MNCC_REL_REQ, p_m_g_callref);
1325         gsm_trace_header(p_m_mISDNport, this, MNCC_REL_REQ, DIRECTION_OUT);
1326         mncc->cause = 1;
1327         mncc->cause_location = param->disconnectinfo.location;
1328         mncc->cause_value = param->disconnectinfo.cause;
1329         add_trace("cause", "location", "%d", mncc->cause_location);
1330         add_trace("cause", "value", "%d", mncc->cause_value);
1331         end_trace();
1332         send_and_free_mncc(gsm->network, mncc->msg_type, mncc);
1333
1334         new_state(PORT_STATE_RELEASE);
1335         p_m_delete = 1;
1336         return;
1337 }
1338
1339
1340 /*
1341  * endpoint sends messages to the port
1342  */
1343 int Pgsm::message_epoint(unsigned int epoint_id, int message_id, union parameter *param)
1344 {
1345         if (PmISDN::message_epoint(epoint_id, message_id, param))
1346                 return(1);
1347
1348         switch(message_id) {
1349                 case MESSAGE_SETUP: /* dial-out command received from epoint */
1350                 if (p_state!=PORT_STATE_IDLE)
1351                         break;
1352                 message_setup(epoint_id, message_id, param);
1353                 break;
1354
1355                 case MESSAGE_NOTIFY: /* display and notifications */
1356                 message_notify(epoint_id, message_id, param);
1357                 break;
1358
1359 //              case MESSAGE_FACILITY: /* facility message */
1360 //              message_facility(epoint_id, message_id, param);
1361 //              break;
1362
1363                 case MESSAGE_PROCEEDING: /* message not handles */
1364                 break;
1365
1366                 case MESSAGE_ALERTING: /* call of endpoint is ringing */
1367                 if (p_state!=PORT_STATE_IN_PROCEEDING)
1368                         break;
1369                 message_alerting(epoint_id, message_id, param);
1370                 if (p_m_g_notify_pending) {
1371                         /* send pending notify message during connect */
1372                         message_notify(ACTIVE_EPOINT(p_epointlist), p_m_g_notify_pending->type, &p_m_g_notify_pending->param);
1373                         message_free(p_m_g_notify_pending);
1374                         p_m_g_notify_pending = NULL;
1375                 }
1376                 break;
1377
1378                 case MESSAGE_CONNECT: /* call of endpoint is connected */
1379                 if (p_state!=PORT_STATE_IN_PROCEEDING
1380                  && p_state!=PORT_STATE_IN_ALERTING)
1381                         break;
1382                 message_connect(epoint_id, message_id, param);
1383                 if (p_m_g_notify_pending) {
1384                         /* send pending notify message during connect */
1385                         message_notify(ACTIVE_EPOINT(p_epointlist), p_m_g_notify_pending->type, &p_m_g_notify_pending->param);
1386                         message_free(p_m_g_notify_pending);
1387                         p_m_g_notify_pending = NULL;
1388                 }
1389                 break;
1390
1391                 case MESSAGE_DISCONNECT: /* call has been disconnected */
1392                 if (p_state!=PORT_STATE_IN_PROCEEDING
1393                  && p_state!=PORT_STATE_IN_ALERTING
1394                  && p_state!=PORT_STATE_OUT_SETUP
1395                  && p_state!=PORT_STATE_OUT_OVERLAP
1396                  && p_state!=PORT_STATE_OUT_PROCEEDING
1397                  && p_state!=PORT_STATE_OUT_ALERTING
1398                  && p_state!=PORT_STATE_CONNECT
1399                  && p_state!=PORT_STATE_CONNECT_WAITING)
1400                         break;
1401                 message_disconnect(epoint_id, message_id, param);
1402                 break;
1403
1404                 case MESSAGE_RELEASE: /* release isdn port */
1405                 if (p_state==PORT_STATE_RELEASE)
1406                         break;
1407                 message_release(epoint_id, message_id, param);
1408                 break;
1409
1410                 default:
1411                 PDEBUG(DEBUG_GSM, "Pgsm(%s) gsm port with (caller id %s) received unhandled nessage: %d\n", p_name, p_callerinfo.id, message_id);
1412         }
1413
1414         return(1);
1415 }
1416
1417
1418 /*
1419  * handler
1420  */
1421 int Pgsm::handler(void)
1422 {
1423         int ret;
1424         int work = 0;
1425         unsigned char buffer[2048+MISDN_HEADER_LEN];
1426         struct mISDNhead *hh = (struct mISDNhead *)buffer;
1427
1428         if ((ret = PmISDN::handler()))
1429                 return(ret);
1430
1431         /* handle destruction */
1432         if (p_m_delete) {
1433                 delete this;
1434                 return(-1);
1435         }
1436
1437         /* handle message from bchannel */
1438         if (p_m_g_gsm_b_sock > -1) {
1439                 ret = recv(p_m_g_gsm_b_sock, buffer, sizeof(buffer), 0);
1440                 if (ret >= (int)MISDN_HEADER_LEN) {
1441                         switch(hh->prim) {
1442                                 /* we don't care about confirms, we use rx data to sync tx */
1443                                 case PH_DATA_CNF:
1444                                 break;
1445                                 /* we receive audio data, we respond to it AND we send tones */
1446                                 case PH_DATA_IND:
1447                                 bchannel_receive(hh, buffer+MISDN_HEADER_LEN, ret-MISDN_HEADER_LEN);
1448                                 break;
1449                                 case PH_ACTIVATE_IND:
1450                                 p_m_g_gsm_b_active = 1;
1451                                 break;
1452                                 case PH_DEACTIVATE_IND:
1453                                 p_m_g_gsm_b_active = 0;
1454                                 break;
1455                         }
1456                         work = 1;
1457                 } else {
1458                         if (ret < 0 && errno != EWOULDBLOCK)
1459                                 PERROR("Read from GSM port, index %d failed with return code %d\n", ret);
1460                 }
1461         }
1462
1463         return(work);
1464 }
1465
1466
1467 /*
1468  * handles bsc select function within LCR's main loop
1469  */
1470 int handle_gsm(void)
1471 {
1472         int ret1, ret2;
1473
1474         ret1 = bsc_upqueue(gsm->network);
1475         ret2 = bsc_select_main(1); /* polling */
1476         if (ret1 || ret2)
1477                 return 1;
1478         return 0;
1479 }
1480
1481 static void gsm_sock_close(void)
1482 {
1483         if (gsm->gsm_sock > -1)
1484                 close(gsm->gsm_sock);
1485         gsm->gsm_sock = -1;
1486 }
1487
1488 static int gsm_sock_open(char *portname)
1489 {
1490         int ret;
1491         int cnt;
1492         unsigned long on = 1;
1493         struct sockaddr_mISDN addr;
1494         struct mISDN_devinfo devinfo;
1495         int pri, bri;
1496
1497         /* check port counts */
1498         ret = ioctl(mISDNsocket, IMGETCOUNT, &cnt);
1499         if (ret < 0) {
1500                 fprintf(stderr, "Cannot get number of mISDN devices. (ioctl IMGETCOUNT failed ret=%d)\n", ret);
1501                 return(ret);
1502         }
1503
1504         if (cnt <= 0) {
1505                 PERROR_RUNTIME("Found no card. Please be sure to load card drivers.\n");
1506                 return -EIO;
1507         }
1508         gsm->gsm_port = mISDN_getportbyname(mISDNsocket, cnt, portname);
1509         if (gsm->gsm_port < 0) {
1510                 PERROR_RUNTIME("Port name '%s' not found, did you load loopback interface for GSM?.\n", portname);
1511                 return gsm->gsm_port;
1512         }
1513         /* get protocol */
1514         bri = pri = 0;
1515         devinfo.id = gsm->gsm_port;
1516         ret = ioctl(mISDNsocket, IMGETDEVINFO, &devinfo);
1517         if (ret < 0) {
1518                 PERROR_RUNTIME("Cannot get device information for port %d. (ioctl IMGETDEVINFO failed ret=%d)\n", gsm->gsm_port, ret);
1519                 return ret;
1520         }
1521         if (devinfo.Dprotocols & (1 << ISDN_P_TE_S0)) {
1522                 bri = 1;
1523         }
1524         if (devinfo.Dprotocols & (1 << ISDN_P_TE_E1)) {
1525                 pri = 1;
1526         }
1527         if (!pri && !pri) {
1528                 PERROR_RUNTIME("GSM port %d does not support TE PRI or TE BRI.\n", gsm->gsm_port);
1529         }
1530         /* open socket */
1531         if ((gsm->gsm_sock = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_TE_S0)) < 0) {
1532                 PERROR_RUNTIME("GSM port %d failed to open socket.\n", gsm->gsm_port);
1533                 gsm_sock_close();
1534                 return gsm->gsm_sock;
1535         }
1536         /* set nonblocking io */
1537         if ((ret = ioctl(gsm->gsm_sock, FIONBIO, &on)) < 0) {
1538                 PERROR_RUNTIME("GSM port %d failed to set socket into nonblocking io.\n", gsm->gsm_port);
1539                 gsm_sock_close();
1540                 return ret;
1541         }
1542         /* bind socket to dchannel */
1543         memset(&addr, 0, sizeof(addr));
1544         addr.family = AF_ISDN;
1545         addr.dev = gsm->gsm_port;
1546         addr.channel = 0;
1547         if ((ret = bind(gsm->gsm_sock, (struct sockaddr *)&addr, sizeof(addr))) < 0) {
1548                 PERROR_RUNTIME("GSM port %d failed to bind socket. (name = %s errno=%d)\n", gsm->gsm_port, portname, errno);
1549                 gsm_sock_close();
1550                 return (ret);
1551         }
1552
1553         return 0;
1554 }
1555
1556
1557 int gsm_exit(int rc)
1558 {
1559         /* free gsm instance */
1560         if (gsm) {
1561                 if (gsm->gsm_sock > -1)
1562                         gsm_sock_close();
1563                 /* shutdown network */
1564                 if (gsm->network)
1565                         shutdown_net(gsm->network);
1566                 /* free network */
1567                 if (gsm->network) {
1568                         free(gsm->network); /* TBD */
1569                 }
1570                 free(gsm);
1571                 gsm = NULL;
1572         }
1573
1574         return(rc);
1575 }
1576
1577 int gsm_init(void)
1578 {
1579         char hlr[128];
1580
1581         /* create gsm instance */
1582         gsm = (struct lcr_gsm *)MALLOC(sizeof(struct lcr_gsm));
1583         gsm->gsm_sock = -1;
1584
1585         /* parse options */
1586         if (!gsm_conf(&gsm->conf)) {
1587                 PERROR("%s", gsm_conf_error);
1588                 return gsm_exit(-EINVAL);
1589         }
1590
1591         /* init database */
1592         if (gsm->conf.hlr[0] == '/')
1593                 SCPY(hlr, gsm->conf.hlr);
1594         else
1595                 SPRINT(hlr, "%s/%s", CONFIG_DATA, gsm->conf.hlr);
1596
1597         // TODO multiple base stations
1598         if (gsm->conf.numbts < 1 || gsm->conf.numbts > 1) {
1599                 PERROR("Expecting exactly one BTS. You defined %d.\n", gsm->conf.numbts);
1600                 return gsm_exit(-1);
1601         }
1602         /* bootstrap network */
1603         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);
1604         if (!gsm->network) {
1605                 PERROR("Failed to bootstrap GSM network.\n");
1606                 return gsm_exit(-1);
1607         }
1608         /* open gsm loop interface */
1609         if (gsm_sock_open(gsm->conf.interface_bsc)) {
1610                 return gsm_exit(-1);
1611         }
1612
1613         return 0;
1614 }
1615