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