- Debug option now works for GSM.
[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                 mncc = create_mncc(MNCC_REJ_REQ, callref);
395                 gsm_trace_header(p_m_mISDNport, this, MNCC_REJ_REQ, DIRECTION_OUT);
396                 mncc->cause = 1;
397                 mncc->cause_coding = 3;
398                 mncc->cause_location = 1;
399                 mncc->cause_value = 47;
400                 add_trace("cause", "coding", "%d", mncc->cause_coding);
401                 add_trace("cause", "location", "%d", mncc->cause_location);
402                 add_trace("cause", "value", "%d", mncc->cause_value);
403                 add_trace("reason", NULL, "callref already in use");
404                 end_trace();
405                 send_and_free_mncc(gsm->network, mncc->msg_type, mncc);
406                 new_state(PORT_STATE_RELEASE);
407                 p_m_delete = 1;
408                 return;
409         }
410         p_m_g_callref = callref;
411         end_trace();
412
413         /* if blocked, release call with MT_RELEASE_COMPLETE */
414         if (p_m_mISDNport->ifport->block) {
415                 mncc = create_mncc(MNCC_REJ_REQ, p_m_g_callref);
416                 gsm_trace_header(p_m_mISDNport, this, MNCC_REJ_REQ, DIRECTION_OUT);
417                 mncc->cause = 1;
418                 mncc->cause_coding = 3;
419                 mncc->cause_location = 1;
420                 mncc->cause_value = 27;
421                 add_trace("cause", "coding", "%d", mncc->cause_coding);
422                 add_trace("cause", "location", "%d", mncc->cause_location);
423                 add_trace("cause", "value", "%d", mncc->cause_value);
424                 add_trace("reason", NULL, "port is blocked");
425                 end_trace();
426                 send_and_free_mncc(gsm->network, mncc->msg_type, mncc);
427                 new_state(PORT_STATE_RELEASE);
428                 p_m_delete = 1;
429                 return;
430         }
431
432         /* caller info */
433         if (mncc->clir_inv)
434                 p_callerinfo.present = INFO_PRESENT_RESTRICTED;
435         else
436                 p_callerinfo.present = INFO_PRESENT_ALLOWED;
437         if (mncc->calling_number[0])
438                 SCPY(p_callerinfo.id, mncc->calling_number);
439         else
440                 p_callerinfo.present = INFO_PRESENT_NOTAVAIL;
441         p_callerinfo.screen = INFO_SCREEN_NETWORK;
442         p_callerinfo.ntype = INFO_NTYPE_UNKNOWN;
443         p_callerinfo.isdn_port = p_m_portnum;
444         SCPY(p_callerinfo.interface, p_m_mISDNport->ifport->interface->name);
445
446         /* dialing information */
447         SCAT(p_dialinginfo.id, mncc->called_number);
448         switch (mncc->called_type) {
449                 case 0x1:
450                 p_dialinginfo.ntype = INFO_NTYPE_INTERNATIONAL;
451                 break;
452                 case 0x2:
453                 p_dialinginfo.ntype = INFO_NTYPE_NATIONAL;
454                 break;
455                 case 0x4:
456                 p_dialinginfo.ntype = INFO_NTYPE_SUBSCRIBER;
457                 break;
458                 default:
459                 p_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
460                 break;
461         }
462         if (mncc->emergency) {
463                 SCPY(p_dialinginfo.id, "emergency");
464         }
465         p_dialinginfo.sending_complete = 1;
466
467         /* bearer capability */
468         // todo
469         p_capainfo.bearer_capa = INFO_BC_SPEECH;
470         p_capainfo.bearer_info1 = (options.law=='a')?3:2;
471         p_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
472         p_capainfo.source_mode = B_MODE_TRANSPARENT;
473         p_m_g_mode = p_capainfo.source_mode;
474
475         /* useruser */
476
477         /* hunt channel */
478         ret = channel = hunt_bchannel();
479         if (ret < 0)
480                 goto no_channel;
481
482         /* open channel */
483         ret = seize_bchannel(channel, 1);
484         if (ret < 0) {
485                 no_channel:
486                 mncc = create_mncc(MNCC_REJ_REQ, p_m_g_callref);
487                 gsm_trace_header(p_m_mISDNport, this, MNCC_REJ_REQ, DIRECTION_OUT);
488                 mncc->cause = 1;
489                 mncc->cause_coding = 3;
490                 mncc->cause_location = 1;
491                 mncc->cause_value = 34;
492                 add_trace("cause", "coding", "%d", mncc->cause_coding);
493                 add_trace("cause", "location", "%d", mncc->cause_location);
494                 add_trace("cause", "value", "%d", mncc->cause_value);
495                 add_trace("reason", NULL, "no channel");
496                 end_trace();
497                 send_and_free_mncc(gsm->network, mncc->msg_type, mncc);
498                 new_state(PORT_STATE_RELEASE);
499                 p_m_delete = 1;
500                 return;
501         }
502         bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE);
503         if (bchannel_open(p_m_b_index))
504                 goto no_channel;
505
506         /* what infos did we got ... */
507         gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
508         add_trace("subscr", "number", "%s", p_callerinfo.id);
509         add_trace("dialing", "number", "%s", p_dialinginfo.id);
510         end_trace();
511
512         /* create endpoint */
513         if (p_epointlist)
514                 FATAL("Incoming call but already got an endpoint.\n");
515         if (!(epoint = new Endpoint(p_serial, 0)))
516                 FATAL("No memory for Endpoint instance\n");
517         if (!(epoint->ep_app = new DEFAULT_ENDPOINT_APP(epoint, 0))) //incoming
518                 FATAL("No memory for Endpoint Application instance\n");
519         epointlist_new(epoint->ep_serial);
520
521         /* modify lchan to GSM codec V1 */
522         gsm_trace_header(p_m_mISDNport, this, MNCC_LCHAN_MODIFY, DIRECTION_OUT);
523         mode = create_mncc(MNCC_LCHAN_MODIFY, p_m_g_callref);
524         mode->lchan_mode = 0x01; /* GSM V1 */
525         add_trace("mode", NULL, "0x%02x", mode->lchan_mode);
526         end_trace();
527         send_and_free_mncc(gsm->network, mode->msg_type, mode);
528
529         /* send call proceeding */
530         gsm_trace_header(p_m_mISDNport, this, MNCC_CALL_PROC_REQ, DIRECTION_OUT);
531         proceeding = create_mncc(MNCC_CALL_PROC_REQ, p_m_g_callref);
532         if (p_m_mISDNport->tones) {
533                 proceeding->progress = 1;
534                 proceeding->progress_coding = 3; /* GSM */
535                 proceeding->progress_location = 1;
536                 proceeding->progress_descr = 8;
537                 add_trace("progress", "coding", "%d", proceeding->progress_coding);
538                 add_trace("progress", "location", "%d", proceeding->progress_location);
539                 add_trace("progress", "descr", "%d", proceeding->progress_descr);
540         }
541         end_trace();
542         send_and_free_mncc(gsm->network, proceeding->msg_type, proceeding);
543
544         new_state(PORT_STATE_IN_PROCEEDING);
545
546         if (p_m_mISDNport->tones && !p_m_g_tch_connected) { /* only if ... */
547                 gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
548                 end_trace();
549                 frame = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
550                 send_and_free_mncc(gsm->network, frame->msg_type, frame);
551                 p_m_g_tch_connected = 1;
552         }
553
554         /* send setup message to endpoit */
555         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_SETUP);
556         message->param.setup.isdn_port = p_m_portnum;
557         message->param.setup.port_type = p_type;
558 //      message->param.setup.dtmf = 0;
559         memcpy(&message->param.setup.dialinginfo, &p_dialinginfo, sizeof(struct dialing_info));
560         memcpy(&message->param.setup.callerinfo, &p_callerinfo, sizeof(struct caller_info));
561         memcpy(&message->param.setup.capainfo, &p_capainfo, sizeof(struct capa_info));
562         SCPY((char *)message->param.setup.useruser.data, (char *)mncc->useruser_info);
563         message->param.setup.useruser.len = strlen(mncc->useruser_info);
564         message->param.setup.useruser.protocol = mncc->useruser_proto;
565         message_put(message);
566 }
567
568 /* DTMF INDICATION */
569 void Pgsm::start_dtmf_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
570 {
571         struct lcr_msg *message;
572         struct gsm_mncc *resp;
573
574         gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
575         add_trace("keypad", NULL, "%c", mncc->keypad);
576         end_trace();
577         SPRINT(p_dialinginfo.id, "%c", mncc->keypad);
578         p_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
579
580         /* send resp */
581         gsm_trace_header(p_m_mISDNport, this, MNCC_START_DTMF_RSP, DIRECTION_OUT);
582         add_trace("keypad", NULL, "%c", mncc->keypad);
583         end_trace();
584         resp = create_mncc(MNCC_START_DTMF_RSP, p_m_g_callref);
585         resp->keypad = mncc->keypad;
586         send_and_free_mncc(gsm->network, resp->msg_type, resp);
587
588         /* send dialing information */
589         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_INFORMATION);
590         memcpy(&message->param.information, &p_dialinginfo, sizeof(struct dialing_info));
591         message_put(message);
592 }
593 void Pgsm::stop_dtmf_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
594 {
595         struct gsm_mncc *resp;
596
597         gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
598         add_trace("keypad", NULL, "%c", mncc->keypad);
599         end_trace();
600
601         /* send resp */
602         gsm_trace_header(p_m_mISDNport, this, MNCC_STOP_DTMF_RSP, DIRECTION_OUT);
603         add_trace("keypad", NULL, "%c", mncc->keypad);
604         end_trace();
605         resp = create_mncc(MNCC_STOP_DTMF_RSP, p_m_g_callref);
606         resp->keypad = mncc->keypad;
607         send_and_free_mncc(gsm->network, resp->msg_type, resp);
608 }
609
610 /* PROCEEDING INDICATION */
611 void Pgsm::call_conf_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
612 {
613         struct gsm_mncc *mode;
614
615         gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
616         if (mncc->cause) {
617                 add_trace("cause", "coding", "%d", mncc->cause_coding);
618                 add_trace("cause", "location", "%", mncc->cause_location);
619                 add_trace("cause", "value", "%", mncc->cause_value);
620         }
621         end_trace();
622
623         /* modify lchan to GSM codec V1 */
624         gsm_trace_header(p_m_mISDNport, this, MNCC_LCHAN_MODIFY, DIRECTION_OUT);
625         mode = create_mncc(MNCC_LCHAN_MODIFY, p_m_g_callref);
626         mode->lchan_mode = 0x01; /* GSM V1 */
627         add_trace("mode", NULL, "0x%02x", mode->lchan_mode);
628         end_trace();
629         send_and_free_mncc(gsm->network, mode->msg_type, mode);
630
631 }
632
633 /* ALERTING INDICATION */
634 void Pgsm::alert_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
635 {
636         struct lcr_msg *message;
637
638         gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
639         end_trace();
640
641         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_ALERTING);
642         message_put(message);
643
644         new_state(PORT_STATE_OUT_ALERTING);
645
646 }
647
648 /* CONNECT INDICATION */
649 void Pgsm::setup_cnf(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
650 {
651         struct gsm_mncc *resp, *frame;
652         struct lcr_msg *message;
653
654         gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
655         end_trace();
656
657         /* send resp */
658         gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_COMPL_REQ, DIRECTION_OUT);
659         resp = create_mncc(MNCC_SETUP_COMPL_REQ, p_m_g_callref);
660         end_trace();
661         send_and_free_mncc(gsm->network, resp->msg_type, resp);
662
663         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CONNECT);
664         message_put(message);
665
666         new_state(PORT_STATE_CONNECT);
667
668         if (!p_m_g_tch_connected) { /* only if ... */
669                 gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
670                 end_trace();
671                 frame = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
672                 send_and_free_mncc(gsm->network, frame->msg_type, frame);
673                 p_m_g_tch_connected = 1;
674         }
675 }
676
677 /* CONNECT ACK INDICATION */
678 void Pgsm::setup_compl_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
679 {
680         struct gsm_mncc *frame;
681
682         gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
683         end_trace();
684
685         new_state(PORT_STATE_CONNECT);
686
687         if (!p_m_g_tch_connected) { /* only if ... */
688                 gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
689                 end_trace();
690                 frame = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
691                 send_and_free_mncc(gsm->network, frame->msg_type, frame);
692                 p_m_g_tch_connected = 1;
693         }
694 }
695
696 /* DISCONNECT INDICATION */
697 void Pgsm::disc_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
698 {
699         struct lcr_msg *message;
700         int cause = 16, location = 0;
701         struct gsm_mncc *resp;
702
703         gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
704         if (mncc->cause) {
705                 location = mncc->cause_location;
706                 cause = mncc->cause_value;
707                 add_trace("cause", "coding", "%d", mncc->cause_coding);
708                 add_trace("cause", "location", "%d", location);
709                 add_trace("cause", "value", "%d", cause);
710         }
711         end_trace();
712
713         /* send release */
714         resp = create_mncc(MNCC_REL_REQ, p_m_g_callref);
715         gsm_trace_header(p_m_mISDNport, this, MNCC_REL_REQ, DIRECTION_OUT);
716 #if 0
717         resp->cause = 1;
718         resp->cause_coding = 3;
719         resp->cause_location = 1;
720         resp->cause_value = cause;
721         add_trace("cause", "coding", "%d", resp->cause_coding);
722         add_trace("cause", "location", "%d", resp->cause_location);
723         add_trace("cause", "value", "%d", resp->cause_value);
724 #endif
725         end_trace();
726         send_and_free_mncc(gsm->network, resp->msg_type, resp);
727
728         /* sending release to endpoint */
729         while(p_epointlist) {
730                 message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
731                 message->param.disconnectinfo.cause = cause;
732                 message->param.disconnectinfo.location = location;
733                 message_put(message);
734                 /* remove epoint */
735                 free_epointlist(p_epointlist);
736         }
737         new_state(PORT_STATE_RELEASE);
738         p_m_delete = 1;
739 }
740
741 /* CC_RELEASE INDICATION */
742 void Pgsm::rel_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
743 {
744         int location = 0, cause = 16;
745         struct lcr_msg *message;
746
747         gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
748         if (mncc->cause) {
749                 location = mncc->cause_location;
750                 cause = mncc->cause_value;
751                 add_trace("cause", "coding", "%d", mncc->cause_coding);
752                 add_trace("cause", "location", "%d", mncc->cause_location);
753                 add_trace("cause", "value", "%d", mncc->cause_value);
754         }
755         end_trace();
756
757         /* sending release to endpoint */
758         while(p_epointlist) {
759                 message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
760                 message->param.disconnectinfo.cause = cause;
761                 message->param.disconnectinfo.location = location;
762                 message_put(message);
763                 /* remove epoint */
764                 free_epointlist(p_epointlist);
765         }
766         new_state(PORT_STATE_RELEASE);
767         p_m_delete = 1;
768 }
769
770 /* NOTIFY INDICATION */
771 void Pgsm::notify_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
772 {
773         gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
774         end_trace();
775 }
776
777
778 /* HOLD INDICATION */
779 void Pgsm::hold_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
780 {
781         struct lcr_msg *message;
782         struct gsm_mncc *resp, *frame;
783
784         gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
785         end_trace();
786
787         /* notify the hold of call */
788         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_NOTIFY);
789         message->param.notifyinfo.notify = INFO_NOTIFY_REMOTE_HOLD;
790         message->param.notifyinfo.local = 1; /* call is held by supplementary service */
791         message_put(message);
792
793         /* acknowledge hold */
794         gsm_trace_header(p_m_mISDNport, this, MNCC_HOLD_CNF, DIRECTION_OUT);
795         end_trace();
796         resp = create_mncc(MNCC_HOLD_CNF, p_m_g_callref);
797         send_and_free_mncc(gsm->network, resp->msg_type, resp);
798
799         /* disable audio */
800         if (p_m_g_tch_connected) { /* it should be true */
801                 gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_DROP, DIRECTION_OUT);
802                 end_trace();
803                 frame = create_mncc(MNCC_FRAME_DROP, p_m_g_callref);
804                 send_and_free_mncc(gsm->network, frame->msg_type, frame);
805                 p_m_g_tch_connected = 0;
806         }
807 }
808
809
810 /* RETRIEVE INDICATION */
811 void Pgsm::retr_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
812 {
813         struct lcr_msg *message;
814         struct gsm_mncc *resp, *frame;
815
816         gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
817         end_trace();
818
819         /* notify the retrieve of call */
820         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_NOTIFY);
821         message->param.notifyinfo.notify = INFO_NOTIFY_REMOTE_RETRIEVAL;
822         message->param.notifyinfo.local = 1; /* call is retrieved by supplementary service */
823         message_put(message);
824
825         /* acknowledge retr */
826         gsm_trace_header(p_m_mISDNport, this, MNCC_RETRIEVE_CNF, DIRECTION_OUT);
827         end_trace();
828         resp = create_mncc(MNCC_RETRIEVE_CNF, p_m_g_callref);
829         send_and_free_mncc(gsm->network, resp->msg_type, resp);
830
831         /* enable audio */
832         if (!p_m_g_tch_connected) { /* it should be true */
833                 gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
834                 end_trace();
835                 frame = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
836                 send_and_free_mncc(gsm->network, frame->msg_type, frame);
837                 p_m_g_tch_connected = 1;
838         }
839 }
840
841 /*
842  * BSC sends message to port
843  */
844 static int message_bcs(void *net, int msg_type, void *arg)
845 {
846         struct gsm_mncc *mncc = (struct gsm_mncc *)arg;
847         unsigned int callref = mncc->callref;
848         class Port *port;
849         class Pgsm *pgsm = NULL;
850         char name[64];
851         struct mISDNport *mISDNport;
852
853         /* Special messages */
854         switch(msg_type) {
855         }
856
857         /* find callref */
858         callref = mncc->callref;
859         port = port_first;
860         while(port) {
861                 if ((port->p_type & PORT_CLASS_mISDN_MASK) == PORT_CLASS_mISDN_GSM) {
862                         pgsm = (class Pgsm *)port;
863                         if (pgsm->p_m_g_callref == callref) {
864                                 break;
865                         }
866                 }
867                 port = port->next;
868         }
869
870         if (msg_type == GSM_TRAU_FRAME) {
871                 if (port)
872                         pgsm->trau_receive((struct gsm_trau_frame *)arg);
873                 return 0;
874         }
875
876         if (!port) {
877                 if (msg_type != MNCC_SETUP_IND)
878                         return(0);
879                 /* find gsm port */
880                 mISDNport = mISDNport_first;
881                 while(mISDNport) {
882                         if (mISDNport->gsm)
883                                 break;
884                         mISDNport = mISDNport->next;
885                 }
886                 if (!mISDNport) {
887                         struct gsm_mncc *rej;
888
889                         rej = create_mncc(MNCC_REJ_REQ, callref);
890                         rej->cause = 1;
891                         rej->cause_coding = 3;
892                         rej->cause_location = 1;
893                         rej->cause_value = 27;
894                         gsm_trace_header(NULL, NULL, MNCC_REJ_REQ, DIRECTION_OUT);
895                         add_trace("cause", "coding", "%d", rej->cause_coding);
896                         add_trace("cause", "location", "%d", rej->cause_location);
897                         add_trace("cause", "value", "%d", rej->cause_value);
898                         end_trace();
899                         send_and_free_mncc(gsm->network, rej->msg_type, rej);
900                         return 0;
901                 }
902                 /* creating port object, transparent until setup with hdlc */
903                 SPRINT(name, "%s-%d-in", mISDNport->ifport->interface->name, mISDNport->portnum);
904                 if (!(pgsm = new Pgsm(PORT_TYPE_GSM_IN, mISDNport, name, NULL, 0, 0, B_MODE_TRANSPARENT)))
905
906                         FATAL("Cannot create Port instance.\n");
907         }
908
909         switch(msg_type) {
910                 case MNCC_SETUP_IND:
911                 pgsm->setup_ind(msg_type, callref, mncc);
912                 break;
913
914                 case MNCC_START_DTMF_IND:
915                 pgsm->start_dtmf_ind(msg_type, callref, mncc);
916                 break;
917
918                 case MNCC_STOP_DTMF_IND:
919                 pgsm->stop_dtmf_ind(msg_type, callref, mncc);
920                 break;
921
922                 case MNCC_CALL_CONF_IND:
923                 pgsm->call_conf_ind(msg_type, callref, mncc);
924                 break;
925
926                 case MNCC_ALERT_IND:
927                 pgsm->alert_ind(msg_type, callref, mncc);
928                 break;
929
930                 case MNCC_SETUP_CNF:
931                 pgsm->setup_cnf(msg_type, callref, mncc);
932                 break;
933
934                 case MNCC_SETUP_COMPL_IND:
935                 pgsm->setup_compl_ind(msg_type, callref, mncc);
936                 break;
937
938                 case MNCC_DISC_IND:
939                 pgsm->disc_ind(msg_type, callref, mncc);
940                 break;
941
942                 case MNCC_REL_IND:
943                 case MNCC_REL_CNF:
944                 case MNCC_REJ_IND:
945                 pgsm->rel_ind(msg_type, callref, mncc);
946                 break;
947
948                 case MNCC_NOTIFY_IND:
949                 pgsm->notify_ind(msg_type, callref, mncc);
950                 break;
951
952                 case MNCC_HOLD_IND:
953                 pgsm->hold_ind(msg_type, callref, mncc);
954                 break;
955
956                 case MNCC_RETRIEVE_IND:
957                 pgsm->retr_ind(msg_type, callref, mncc);
958                 break;
959
960                 default:
961                 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);
962         }
963         return(0);
964 }
965
966 /* MESSAGE_SETUP */
967 void Pgsm::message_setup(unsigned int epoint_id, int message_id, union parameter *param)
968 {
969         struct lcr_msg *message;
970         int ret;
971         struct epoint_list *epointlist;
972         struct gsm_mncc *mncc;
973         int channel;
974
975         /* copy setup infos to port */
976         memcpy(&p_callerinfo, &param->setup.callerinfo, sizeof(p_callerinfo));
977         memcpy(&p_dialinginfo, &param->setup.dialinginfo, sizeof(p_dialinginfo));
978         memcpy(&p_capainfo, &param->setup.capainfo, sizeof(p_capainfo));
979         memcpy(&p_redirinfo, &param->setup.redirinfo, sizeof(p_redirinfo));
980
981         /* no number */
982         if (!p_dialinginfo.id[0]) {
983                 gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
984                 add_trace("failure", NULL, "No dialed subscriber given.");
985                 end_trace();
986                 message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
987                 message->param.disconnectinfo.cause = 28;
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         /* release if port is blocked */
996         if (p_m_mISDNport->ifport->block) {
997                 gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
998                 add_trace("failure", NULL, "Port blocked.");
999                 end_trace();
1000                 message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
1001                 message->param.disconnectinfo.cause = 27; // temp. unavail.
1002                 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1003                 message_put(message);
1004                 new_state(PORT_STATE_RELEASE);
1005                 p_m_delete = 1;
1006                 return;
1007         }
1008
1009         /* hunt channel */
1010         ret = channel = hunt_bchannel();
1011         if (ret < 0)
1012                 goto no_channel;
1013         /* open channel */
1014         ret = seize_bchannel(channel, 1);
1015         if (ret < 0) {
1016                 no_channel:
1017                 gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
1018                 add_trace("failure", NULL, "No internal audio channel available.");
1019                 end_trace();
1020                 message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
1021                 message->param.disconnectinfo.cause = 34;
1022                 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1023                 message_put(message);
1024                 new_state(PORT_STATE_RELEASE);
1025                 p_m_delete = 1;
1026                 return;
1027         }
1028         bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE);
1029         if (bchannel_open(p_m_b_index))
1030                 goto no_channel;
1031
1032 //              SCPY(&p_m_tones_dir, param->setup.ext.tones_dir);
1033         /* screen outgoing caller id */
1034         do_screen(1, p_callerinfo.id, sizeof(p_callerinfo.id), &p_callerinfo.ntype, &p_callerinfo.present, p_m_mISDNport->ifport->interface);
1035
1036         /* attach only if not already */
1037         epointlist = p_epointlist;
1038         while(epointlist) {
1039                 if (epointlist->epoint_id == epoint_id)
1040                         break;
1041                 epointlist = epointlist->next;
1042         }
1043         if (!epointlist)
1044                 epointlist_new(epoint_id);
1045
1046         /* creating l3id */
1047         l1l2l3_trace_header(p_m_mISDNport, this, L3_NEW_L3ID_REQ, DIRECTION_OUT);
1048         p_m_g_callref = new_callref++;
1049         add_trace("callref", "new", "0x%x", p_m_g_callref);
1050         end_trace();
1051
1052         gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
1053         mncc = create_mncc(MNCC_SETUP_REQ, p_m_g_callref);
1054         /* caller information */
1055         mncc->calling = 1;
1056         mncc->calling_plan = 1;
1057         switch (p_callerinfo.ntype) {
1058                 case INFO_NTYPE_UNKNOWN:
1059                 mncc->calling_type = 0x0;
1060                 break;
1061                 case INFO_NTYPE_INTERNATIONAL:
1062                 mncc->calling_type = 0x1;
1063                 break;
1064                 case INFO_NTYPE_NATIONAL:
1065                 mncc->calling_type = 0x2;
1066                 break;
1067                 case INFO_NTYPE_SUBSCRIBER:
1068                 mncc->calling_type = 0x4;
1069                 break;
1070                 default: /* INFO_NTYPE_NOTPRESENT */
1071                 mncc->calling = 0;
1072                 break;
1073         }
1074         switch (p_callerinfo.screen) {
1075                 case INFO_SCREEN_USER:
1076                 mncc->calling_screen = 0;
1077                 break;
1078                 default: /* INFO_SCREEN_NETWORK */
1079                 mncc->calling_screen = 3;
1080                 break;
1081         }
1082         switch (p_callerinfo.present) {
1083                 case INFO_PRESENT_ALLOWED:
1084                 mncc->calling_present = 0;
1085                 break;
1086                 case INFO_PRESENT_RESTRICTED:
1087                 mncc->calling_present = 1;
1088                 break;
1089                 default: /* INFO_PRESENT_NOTAVAIL */
1090                 mncc->calling_present = 2;
1091                 break;
1092         }
1093         if (mncc->calling) {
1094                 SCPY(mncc->calling_number, p_callerinfo.id);
1095                 add_trace("calling", "type", "%d", mncc->calling_type);
1096                 add_trace("calling", "plan", "%d", mncc->calling_plan);
1097                 add_trace("calling", "present", "%d", mncc->calling_present);
1098                 add_trace("calling", "screen", "%d", mncc->calling_screen);
1099                 add_trace("calling", "number", "%s", mncc->calling_number);
1100         }
1101         /* dialing information */
1102         mncc->called = 1;
1103         SCPY(mncc->called_number, p_dialinginfo.id);
1104         add_trace("dialing", "number", "%s", mncc->called_number);
1105         
1106         /* sending user-user */
1107
1108         /* redirecting number */
1109         mncc->redirecting = 1;
1110         mncc->redirecting_plan = 1;
1111         switch (p_redirinfo.ntype) {
1112                 case INFO_NTYPE_UNKNOWN:
1113                 mncc->redirecting_type = 0x0;
1114                 break;
1115                 case INFO_NTYPE_INTERNATIONAL:
1116                 mncc->redirecting_type = 0x1;
1117                 break;
1118                 case INFO_NTYPE_NATIONAL:
1119                 mncc->redirecting_type = 0x2;
1120                 break;
1121                 case INFO_NTYPE_SUBSCRIBER:
1122                 mncc->redirecting_type = 0x4;
1123                 break;
1124                 default: /* INFO_NTYPE_NOTPRESENT */
1125                 mncc->redirecting = 0;
1126                 break;
1127         }
1128         switch (p_redirinfo.screen) {
1129                 case INFO_SCREEN_USER:
1130                 mncc->redirecting_screen = 0;
1131                 break;
1132                 default: /* INFO_SCREE_NETWORK */
1133                 mncc->redirecting_screen = 3;
1134                 break;
1135         }
1136         switch (p_redirinfo.present) {
1137                 case INFO_PRESENT_ALLOWED:
1138                 mncc->redirecting_present = 0;
1139                 break;
1140                 case INFO_PRESENT_RESTRICTED:
1141                 mncc->redirecting_present = 1;
1142                 break;
1143                 default: /* INFO_PRESENT_NOTAVAIL */
1144                 mncc->redirecting_present = 2;
1145                 break;
1146         }
1147         /* sending redirecting number only in ntmode */
1148         if (mncc->redirecting) {
1149                 SCPY(mncc->redirecting_number, p_redirinfo.id);
1150                 add_trace("redir", "type", "%d", mncc->redirecting_type);
1151                 add_trace("redir", "plan", "%d", mncc->redirecting_plan);
1152                 add_trace("redir", "present", "%d", mncc->redirecting_present);
1153                 add_trace("redir", "screen", "%d", mncc->redirecting_screen);
1154                 add_trace("redir", "number", "%s", mncc->redirecting_number);
1155         }
1156         /* bearer capability */
1157         //todo
1158
1159         end_trace();
1160         send_and_free_mncc(gsm->network, mncc->msg_type, mncc);
1161
1162         new_state(PORT_STATE_OUT_SETUP);
1163
1164         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_PROCEEDING);
1165         message_put(message);
1166
1167         new_state(PORT_STATE_OUT_PROCEEDING);
1168 }
1169
1170 /* MESSAGE_NOTIFY */
1171 void Pgsm::message_notify(unsigned int epoint_id, int message_id, union parameter *param)
1172 {
1173         struct gsm_mncc *mncc;
1174         int notify;
1175
1176         printf("if = %d\n", param->notifyinfo.notify);
1177         if (param->notifyinfo.notify>INFO_NOTIFY_NONE) {
1178                 notify = param->notifyinfo.notify & 0x7f;
1179                 if (p_state!=PORT_STATE_CONNECT /*&& p_state!=PORT_STATE_IN_PROCEEDING*/ && p_state!=PORT_STATE_IN_ALERTING) {
1180                         /* queue notification */
1181                         if (p_m_g_notify_pending)
1182                                 message_free(p_m_g_notify_pending);
1183                         p_m_g_notify_pending = message_create(ACTIVE_EPOINT(p_epointlist), p_serial, EPOINT_TO_PORT, message_id);
1184                         memcpy(&p_m_g_notify_pending->param, param, sizeof(union parameter));
1185                 } else {
1186                         /* sending notification */
1187                         gsm_trace_header(p_m_mISDNport, this, MNCC_NOTIFY_REQ, DIRECTION_OUT);
1188                         add_trace("notify", NULL, "%d", notify);
1189                         end_trace();
1190                         mncc = create_mncc(MNCC_NOTIFY_REQ, p_m_g_callref);
1191                         mncc->notify = notify;
1192                         send_and_free_mncc(gsm->network, mncc->msg_type, mncc);
1193                 }
1194         }
1195 }
1196
1197 /* MESSAGE_ALERTING */
1198 void Pgsm::message_alerting(unsigned int epoint_id, int message_id, union parameter *param)
1199 {
1200         struct gsm_mncc *mncc;
1201
1202         /* send alert */
1203         gsm_trace_header(p_m_mISDNport, this, MNCC_ALERT_REQ, DIRECTION_OUT);
1204         mncc = create_mncc(MNCC_ALERT_REQ, p_m_g_callref);
1205         if (p_m_mISDNport->tones) {
1206                 mncc->progress = 1;
1207                 mncc->progress_coding = 3; /* GSM */
1208                 mncc->progress_location = 1;
1209                 mncc->progress_descr = 8;
1210                 add_trace("progress", "coding", "%d", mncc->progress_coding);
1211                 add_trace("progress", "location", "%d", mncc->progress_location);
1212                 add_trace("progress", "descr", "%d", mncc->progress_descr);
1213         }
1214         end_trace();
1215         send_and_free_mncc(gsm->network, mncc->msg_type, mncc);
1216
1217         new_state(PORT_STATE_IN_ALERTING);
1218
1219         if (p_m_mISDNport->tones && !p_m_g_tch_connected) { /* only if ... */
1220                 gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
1221                 end_trace();
1222                 mncc = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
1223                 send_and_free_mncc(gsm->network, mncc->msg_type, mncc);
1224                 p_m_g_tch_connected = 1;
1225         }
1226 }
1227
1228 /* MESSAGE_CONNECT */
1229 void Pgsm::message_connect(unsigned int epoint_id, int message_id, union parameter *param)
1230 {
1231         struct gsm_mncc *mncc;
1232
1233         /* copy connected information */
1234         memcpy(&p_connectinfo, &param->connectinfo, sizeof(p_connectinfo));
1235         /* screen outgoing caller id */
1236         do_screen(1, p_connectinfo.id, sizeof(p_connectinfo.id), &p_connectinfo.ntype, &p_connectinfo.present, p_m_mISDNport->ifport->interface);
1237
1238         /* send connect */
1239         mncc = create_mncc(MNCC_SETUP_RSP, p_m_g_callref);
1240         gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_RSP, DIRECTION_OUT);
1241         /* caller information */
1242         mncc->connected = 1;
1243         mncc->connected_plan = 1;
1244         switch (p_callerinfo.ntype) {
1245                 case INFO_NTYPE_UNKNOWN:
1246                 mncc->connected_type = 0x0;
1247                 break;
1248                 case INFO_NTYPE_INTERNATIONAL:
1249                 mncc->connected_type = 0x1;
1250                 break;
1251                 case INFO_NTYPE_NATIONAL:
1252                 mncc->connected_type = 0x2;
1253                 break;
1254                 case INFO_NTYPE_SUBSCRIBER:
1255                 mncc->connected_type = 0x4;
1256                 break;
1257                 default: /* INFO_NTYPE_NOTPRESENT */
1258                 mncc->connected = 0;
1259                 break;
1260         }
1261         switch (p_callerinfo.screen) {
1262                 case INFO_SCREEN_USER:
1263                 mncc->connected_screen = 0;
1264                 break;
1265                 default: /* INFO_SCREEN_NETWORK */
1266                 mncc->connected_screen = 3;
1267                 break;
1268         }
1269         switch (p_callerinfo.present) {
1270                 case INFO_PRESENT_ALLOWED:
1271                 mncc->connected_present = 0;
1272                 break;
1273                 case INFO_PRESENT_RESTRICTED:
1274                 mncc->connected_present = 1;
1275                 break;
1276                 default: /* INFO_PRESENT_NOTAVAIL */
1277                 mncc->connected_present = 2;
1278                 break;
1279         }
1280         if (mncc->connected) {
1281                 SCPY(mncc->connected_number, p_connectinfo.id);
1282                 add_trace("connected", "type", "%d", mncc->connected_type);
1283                 add_trace("connected", "plan", "%d", mncc->connected_plan);
1284                 add_trace("connected", "present", "%d", mncc->connected_present);
1285                 add_trace("connected", "screen", "%d", mncc->connected_screen);
1286                 add_trace("connected", "number", "%s", mncc->connected_number);
1287         }
1288         end_trace();
1289         send_and_free_mncc(gsm->network, mncc->msg_type, mncc);
1290
1291         new_state(PORT_STATE_CONNECT_WAITING);
1292 }
1293
1294 /* MESSAGE_DISCONNECT */
1295 void Pgsm::message_disconnect(unsigned int epoint_id, int message_id, union parameter *param)
1296 {
1297         struct gsm_mncc *mncc;
1298
1299         /* send disconnect */
1300         mncc = create_mncc(MNCC_DISC_REQ, p_m_g_callref);
1301         gsm_trace_header(p_m_mISDNport, this, MNCC_DISC_REQ, DIRECTION_OUT);
1302         if (p_m_mISDNport->tones) {
1303                 mncc->progress = 1;
1304                 mncc->progress_coding = 3; /* GSM */
1305                 mncc->progress_location = 1;
1306                 mncc->progress_descr = 8;
1307                 add_trace("progress", "coding", "%d", mncc->progress_coding);
1308                 add_trace("progress", "location", "%d", mncc->progress_location);
1309                 add_trace("progress", "descr", "%d", mncc->progress_descr);
1310         }
1311         mncc->cause = 1;
1312         mncc->cause_coding = 3;
1313         mncc->cause_location = param->disconnectinfo.location;
1314         mncc->cause_value = param->disconnectinfo.cause;
1315         add_trace("cause", "coding", "%d", mncc->cause_coding);
1316         add_trace("cause", "location", "%d", mncc->cause_location);
1317         add_trace("cause", "value", "%d", mncc->cause_value);
1318         end_trace();
1319         send_and_free_mncc(gsm->network, mncc->msg_type, mncc);
1320
1321         new_state(PORT_STATE_OUT_DISCONNECT);
1322
1323         if (p_m_mISDNport->tones && !p_m_g_tch_connected) { /* only if ... */
1324                 gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
1325                 end_trace();
1326                 mncc = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
1327                 send_and_free_mncc(gsm->network, mncc->msg_type, mncc);
1328                 p_m_g_tch_connected = 1;
1329         }
1330 }
1331
1332
1333 /* MESSAGE_RELEASE */
1334 void Pgsm::message_release(unsigned int epoint_id, int message_id, union parameter *param)
1335 {
1336         struct gsm_mncc *mncc;
1337
1338         /* send release */
1339         mncc = create_mncc(MNCC_REL_REQ, p_m_g_callref);
1340         gsm_trace_header(p_m_mISDNport, this, MNCC_REL_REQ, DIRECTION_OUT);
1341         mncc->cause = 1;
1342         mncc->cause_coding = 3;
1343         mncc->cause_location = param->disconnectinfo.location;
1344         mncc->cause_value = param->disconnectinfo.cause;
1345         add_trace("cause", "coding", "%d", mncc->cause_coding);
1346         add_trace("cause", "location", "%d", mncc->cause_location);
1347         add_trace("cause", "value", "%d", mncc->cause_value);
1348         end_trace();
1349         send_and_free_mncc(gsm->network, mncc->msg_type, mncc);
1350
1351         new_state(PORT_STATE_RELEASE);
1352         p_m_delete = 1;
1353         return;
1354 }
1355
1356
1357 /*
1358  * endpoint sends messages to the port
1359  */
1360 int Pgsm::message_epoint(unsigned int epoint_id, int message_id, union parameter *param)
1361 {
1362         if (PmISDN::message_epoint(epoint_id, message_id, param))
1363                 return(1);
1364
1365         switch(message_id) {
1366                 case MESSAGE_SETUP: /* dial-out command received from epoint */
1367                 if (p_state!=PORT_STATE_IDLE)
1368                         break;
1369                 message_setup(epoint_id, message_id, param);
1370                 break;
1371
1372                 case MESSAGE_NOTIFY: /* display and notifications */
1373                 message_notify(epoint_id, message_id, param);
1374                 break;
1375
1376 //              case MESSAGE_FACILITY: /* facility message */
1377 //              message_facility(epoint_id, message_id, param);
1378 //              break;
1379
1380                 case MESSAGE_PROCEEDING: /* message not handles */
1381                 break;
1382
1383                 case MESSAGE_ALERTING: /* call of endpoint is ringing */
1384                 if (p_state!=PORT_STATE_IN_PROCEEDING)
1385                         break;
1386                 message_alerting(epoint_id, message_id, param);
1387                 if (p_m_g_notify_pending) {
1388                         /* send pending notify message during connect */
1389                         message_notify(ACTIVE_EPOINT(p_epointlist), p_m_g_notify_pending->type, &p_m_g_notify_pending->param);
1390                         message_free(p_m_g_notify_pending);
1391                         p_m_g_notify_pending = NULL;
1392                 }
1393                 break;
1394
1395                 case MESSAGE_CONNECT: /* call of endpoint is connected */
1396                 if (p_state!=PORT_STATE_IN_PROCEEDING
1397                  && p_state!=PORT_STATE_IN_ALERTING)
1398                         break;
1399                 message_connect(epoint_id, message_id, param);
1400                 if (p_m_g_notify_pending) {
1401                         /* send pending notify message during connect */
1402                         message_notify(ACTIVE_EPOINT(p_epointlist), p_m_g_notify_pending->type, &p_m_g_notify_pending->param);
1403                         message_free(p_m_g_notify_pending);
1404                         p_m_g_notify_pending = NULL;
1405                 }
1406                 break;
1407
1408                 case MESSAGE_DISCONNECT: /* call has been disconnected */
1409                 if (p_state!=PORT_STATE_IN_PROCEEDING
1410                  && p_state!=PORT_STATE_IN_ALERTING
1411                  && p_state!=PORT_STATE_OUT_SETUP
1412                  && p_state!=PORT_STATE_OUT_OVERLAP
1413                  && p_state!=PORT_STATE_OUT_PROCEEDING
1414                  && p_state!=PORT_STATE_OUT_ALERTING
1415                  && p_state!=PORT_STATE_CONNECT
1416                  && p_state!=PORT_STATE_CONNECT_WAITING)
1417                         break;
1418                 message_disconnect(epoint_id, message_id, param);
1419                 break;
1420
1421                 case MESSAGE_RELEASE: /* release isdn port */
1422                 if (p_state==PORT_STATE_RELEASE)
1423                         break;
1424                 message_release(epoint_id, message_id, param);
1425                 break;
1426
1427                 default:
1428                 PDEBUG(DEBUG_GSM, "Pgsm(%s) gsm port with (caller id %s) received unhandled nessage: %d\n", p_name, p_callerinfo.id, message_id);
1429         }
1430
1431         return(1);
1432 }
1433
1434
1435 /*
1436  * handler
1437  */
1438 int Pgsm::handler(void)
1439 {
1440         int ret;
1441         int work = 0;
1442         unsigned char buffer[2048+MISDN_HEADER_LEN];
1443         struct mISDNhead *hh = (struct mISDNhead *)buffer;
1444
1445         if ((ret = PmISDN::handler()))
1446                 return(ret);
1447
1448         /* handle destruction */
1449         if (p_m_delete) {
1450                 delete this;
1451                 return(-1);
1452         }
1453
1454         /* handle message from bchannel */
1455         if (p_m_g_gsm_b_sock > -1) {
1456                 ret = recv(p_m_g_gsm_b_sock, buffer, sizeof(buffer), 0);
1457                 if (ret >= (int)MISDN_HEADER_LEN) {
1458                         switch(hh->prim) {
1459                                 /* we don't care about confirms, we use rx data to sync tx */
1460                                 case PH_DATA_CNF:
1461                                 break;
1462                                 /* we receive audio data, we respond to it AND we send tones */
1463                                 case PH_DATA_IND:
1464                                 bchannel_receive(hh, buffer+MISDN_HEADER_LEN, ret-MISDN_HEADER_LEN);
1465                                 break;
1466                                 case PH_ACTIVATE_IND:
1467                                 p_m_g_gsm_b_active = 1;
1468                                 break;
1469                                 case PH_DEACTIVATE_IND:
1470                                 p_m_g_gsm_b_active = 0;
1471                                 break;
1472                         }
1473                         work = 1;
1474                 } else {
1475                         if (ret < 0 && errno != EWOULDBLOCK)
1476                                 PERROR("Read from GSM port, index %d failed with return code %d\n", ret);
1477                 }
1478         }
1479
1480         return(work);
1481 }
1482
1483
1484 /*
1485  * handles bsc select function within LCR's main loop
1486  */
1487 int handle_gsm(void)
1488 {
1489         int ret1, ret2;
1490
1491         ret1 = bsc_upqueue(gsm->network);
1492         ret2 = bsc_select_main(1); /* polling */
1493         if (ret1 || ret2)
1494                 return 1;
1495         return 0;
1496 }
1497
1498 static void gsm_sock_close(void)
1499 {
1500         if (gsm->gsm_sock > -1)
1501                 close(gsm->gsm_sock);
1502         gsm->gsm_sock = -1;
1503 }
1504
1505 static int gsm_sock_open(char *portname)
1506 {
1507         int ret;
1508         int cnt;
1509         unsigned long on = 1;
1510         struct sockaddr_mISDN addr;
1511         struct mISDN_devinfo devinfo;
1512         int pri, bri;
1513
1514         /* check port counts */
1515         ret = ioctl(mISDNsocket, IMGETCOUNT, &cnt);
1516         if (ret < 0) {
1517                 fprintf(stderr, "Cannot get number of mISDN devices. (ioctl IMGETCOUNT failed ret=%d)\n", ret);
1518                 return(ret);
1519         }
1520
1521         if (cnt <= 0) {
1522                 PERROR_RUNTIME("Found no card. Please be sure to load card drivers.\n");
1523                 return -EIO;
1524         }
1525         gsm->gsm_port = mISDN_getportbyname(mISDNsocket, cnt, portname);
1526         if (gsm->gsm_port < 0) {
1527                 PERROR_RUNTIME("Port name '%s' not found, did you load loopback interface for GSM?.\n", portname);
1528                 return gsm->gsm_port;
1529         }
1530         /* get protocol */
1531         bri = pri = 0;
1532         devinfo.id = gsm->gsm_port;
1533         ret = ioctl(mISDNsocket, IMGETDEVINFO, &devinfo);
1534         if (ret < 0) {
1535                 PERROR_RUNTIME("Cannot get device information for port %d. (ioctl IMGETDEVINFO failed ret=%d)\n", gsm->gsm_port, ret);
1536                 return ret;
1537         }
1538         if (devinfo.Dprotocols & (1 << ISDN_P_TE_S0)) {
1539                 bri = 1;
1540         }
1541         if (devinfo.Dprotocols & (1 << ISDN_P_TE_E1)) {
1542                 pri = 1;
1543         }
1544         if (!pri && !pri) {
1545                 PERROR_RUNTIME("GSM port %d does not support TE PRI or TE BRI.\n", gsm->gsm_port);
1546         }
1547         /* open socket */
1548         if ((gsm->gsm_sock = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_TE_S0)) < 0) {
1549                 PERROR_RUNTIME("GSM port %d failed to open socket.\n", gsm->gsm_port);
1550                 gsm_sock_close();
1551                 return gsm->gsm_sock;
1552         }
1553         /* set nonblocking io */
1554         if ((ret = ioctl(gsm->gsm_sock, FIONBIO, &on)) < 0) {
1555                 PERROR_RUNTIME("GSM port %d failed to set socket into nonblocking io.\n", gsm->gsm_port);
1556                 gsm_sock_close();
1557                 return ret;
1558         }
1559         /* bind socket to dchannel */
1560         memset(&addr, 0, sizeof(addr));
1561         addr.family = AF_ISDN;
1562         addr.dev = gsm->gsm_port;
1563         addr.channel = 0;
1564         if ((ret = bind(gsm->gsm_sock, (struct sockaddr *)&addr, sizeof(addr))) < 0) {
1565                 PERROR_RUNTIME("GSM port %d failed to bind socket. (name = %s errno=%d)\n", gsm->gsm_port, portname, errno);
1566                 gsm_sock_close();
1567                 return (ret);
1568         }
1569
1570         return 0;
1571 }
1572
1573
1574 int gsm_exit(int rc)
1575 {
1576         /* free gsm instance */
1577         if (gsm) {
1578                 if (gsm->gsm_sock > -1)
1579                         gsm_sock_close();
1580                 /* shutdown network */
1581                 if (gsm->network)
1582                         shutdown_net(gsm->network);
1583                 /* free network */
1584                 if (gsm->network) {
1585                         free(gsm->network); /* TBD */
1586                 }
1587                 free(gsm);
1588                 gsm = NULL;
1589         }
1590
1591         return(rc);
1592 }
1593
1594 int gsm_init(void)
1595 {
1596         char hlr[128];
1597
1598         /* create gsm instance */
1599         gsm = (struct lcr_gsm *)MALLOC(sizeof(struct lcr_gsm));
1600         gsm->gsm_sock = -1;
1601
1602         /* parse options */
1603         if (!gsm_conf(&gsm->conf)) {
1604                 PERROR("%s", gsm_conf_error);
1605                 return gsm_exit(-EINVAL);
1606         }
1607
1608         /* set debug */
1609         debug_parse_category_mask(gsm->conf.debug);
1610
1611         /* init database */
1612         if (gsm->conf.hlr[0] == '/')
1613                 SCPY(hlr, gsm->conf.hlr);
1614         else
1615                 SPRINT(hlr, "%s/%s", CONFIG_DATA, gsm->conf.hlr);
1616
1617         // TODO multiple base stations
1618         if (gsm->conf.numbts < 1 || gsm->conf.numbts > 1) {
1619                 PERROR("Expecting exactly one BTS. You defined %d.\n", gsm->conf.numbts);
1620                 return gsm_exit(-1);
1621         }
1622         /* bootstrap network */
1623         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);
1624         if (!gsm->network) {
1625                 PERROR("Failed to bootstrap GSM network.\n");
1626                 return gsm_exit(-1);
1627         }
1628         /* open gsm loop interface */
1629         if (gsm_sock_open(gsm->conf.interface_bsc)) {
1630                 return gsm_exit(-1);
1631         }
1632
1633         return 0;
1634 }
1635