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