[chan_lcr] Added second caller ID (ANI) in case the caller ID is user provided.
[lcr.git] / gsm_ms.cpp
1 /*****************************************************************************\
2 **                                                                           **
3 ** LCR                                                                       **
4 **                                                                           **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg                                              **
7 **                                                                           **
8 ** mISDN gsm (MS mode)                                                       **
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 <osmocore/select.h>
21 #include <osmocore/talloc.h>
22
23 #include <osmocom/osmocom_data.h>
24 #include <osmocom/logging.h>
25 #include <osmocom/l1l2_interface.h>
26 #include <osmocom/l23_app.h>
27 }
28
29 const char *openbsc_copyright = "";
30 short vty_port = 4247;
31
32 struct llist_head ms_list;
33 struct log_target *stderr_target;
34 void *l23_ctx = NULL;
35 int (*l23_app_work) (struct osmocom_ms *ms) = NULL;
36 int (*l23_app_exit) (struct osmocom_ms *ms) = NULL;
37
38 /*
39  * constructor
40  */
41 Pgsm_ms::Pgsm_ms(int type, struct mISDNport *mISDNport, char *portname, struct port_settings *settings, int channel, int exclusive, int mode) : Pgsm(type, mISDNport, portname, settings, channel, exclusive, mode)
42 {
43         struct osmocom_ms *ms = NULL;
44         char *ms_name = mISDNport->ifport->gsm_ms_name;
45
46         p_m_g_instance = NULL;
47
48         llist_for_each_entry(ms, &ms_list, entity) {
49                 if (!strcmp(ms->name, ms_name)) {
50                         p_m_g_instance = ms;
51                         break;
52                 }
53         }
54
55         if (!p_m_g_instance)
56                 FATAL("MS name %s does not exists. Please fix!");
57
58         PDEBUG(DEBUG_GSM, "Created new GSMMSPort(%s %s).\n", portname, ms_name);
59 }
60
61 /*
62  * destructor
63  */
64 Pgsm_ms::~Pgsm_ms()
65 {
66         PDEBUG(DEBUG_GSM, "Destroyed GSM MS process(%s).\n", p_name);
67 }
68
69 /*
70  * handles all indications
71  */
72 /* SETUP INDICATION */
73 void Pgsm_ms::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
74 {
75         int ret;
76         class Endpoint *epoint;
77         struct lcr_msg *message;
78         int channel;
79         struct gsm_mncc *mode, *proceeding, *frame;
80
81         /* process given callref */
82         l1l2l3_trace_header(p_m_mISDNport, this, L3_NEW_L3ID_IND, DIRECTION_IN);
83         add_trace("callref", "new", "0x%x", callref);
84         if (p_m_g_callref) {
85                 /* release in case the ID is already in use */
86                 add_trace("error", NULL, "callref already in use");
87                 end_trace();
88                 mncc = create_mncc(MNCC_REJ_REQ, callref);
89                 gsm_trace_header(p_m_mISDNport, this, MNCC_REJ_REQ, DIRECTION_OUT);
90                 mncc->fields |= MNCC_F_CAUSE;
91                 mncc->cause.coding = 3;
92                 mncc->cause.location = 1;
93                 mncc->cause.value = 47;
94                 add_trace("cause", "coding", "%d", mncc->cause.coding);
95                 add_trace("cause", "location", "%d", mncc->cause.location);
96                 add_trace("cause", "value", "%d", mncc->cause.value);
97                 add_trace("reason", NULL, "callref already in use");
98                 end_trace();
99                 send_and_free_mncc(p_m_g_instance, mncc->msg_type, mncc);
100                 new_state(PORT_STATE_RELEASE);
101                 trigger_work(&p_m_g_delete);
102                 return;
103         }
104         p_m_g_callref = callref;
105         end_trace();
106
107         /* if blocked, release call with MT_RELEASE_COMPLETE */
108         if (p_m_mISDNport->ifport->block) {
109                 mncc = create_mncc(MNCC_REJ_REQ, p_m_g_callref);
110                 gsm_trace_header(p_m_mISDNport, this, MNCC_REJ_REQ, DIRECTION_OUT);
111                 mncc->fields |= MNCC_F_CAUSE;
112                 mncc->cause.coding = 3;
113                 mncc->cause.location = 1;
114                 mncc->cause.value = 27;
115                 add_trace("cause", "coding", "%d", mncc->cause.coding);
116                 add_trace("cause", "location", "%d", mncc->cause.location);
117                 add_trace("cause", "value", "%d", mncc->cause.value);
118                 add_trace("reason", NULL, "port is blocked");
119                 end_trace();
120                 send_and_free_mncc(p_m_g_instance, mncc->msg_type, mncc);
121                 new_state(PORT_STATE_RELEASE);
122                 trigger_work(&p_m_g_delete);
123                 return;
124         }
125
126         l1l2l3_trace_header(p_m_mISDNport, this, MNCC_SETUP_IND, DIRECTION_IN);
127         /* caller information */
128         p_callerinfo.ntype = INFO_NTYPE_NOTPRESENT;
129         if (mncc->fields & MNCC_F_CALLING) {
130                 switch (mncc->calling.present) {
131                         case 1:
132                         p_callerinfo.present = INFO_PRESENT_RESTRICTED;
133                         break;
134                         case 2:
135                         p_callerinfo.present = INFO_PRESENT_NOTAVAIL;
136                         break;
137                         default:
138                         p_callerinfo.present = INFO_PRESENT_ALLOWED;
139                         break;
140                 }
141                 switch (mncc->calling.screen) {
142                         case 0:
143                         p_callerinfo.screen = INFO_SCREEN_USER;
144                         break;
145                         case 1:
146                         p_callerinfo.screen = INFO_SCREEN_USER_VERIFIED_PASSED;
147                         break;
148                         case 2:
149                         p_callerinfo.screen = INFO_SCREEN_USER_VERIFIED_FAILED;
150                         break;
151                         default:
152                         p_callerinfo.screen = INFO_SCREEN_NETWORK;
153                         break;
154                 }
155                 switch (mncc->calling.type) {
156                         case 0x0:
157                         p_callerinfo.ntype = INFO_NTYPE_UNKNOWN;
158                         break;
159                         case 0x1:
160                         p_callerinfo.ntype = INFO_NTYPE_INTERNATIONAL;
161                         break;
162                         case 0x2:
163                         p_callerinfo.ntype = INFO_NTYPE_NATIONAL;
164                         break;
165                         case 0x4:
166                         p_callerinfo.ntype = INFO_NTYPE_SUBSCRIBER;
167                         break;
168                         default:
169                         p_callerinfo.ntype = INFO_NTYPE_UNKNOWN;
170                         break;
171                 }
172                 SCPY(p_callerinfo.id, mncc->calling.number);
173                 add_trace("calling", "type", "%d", mncc->calling.type);
174                 add_trace("calling", "plan", "%d", mncc->calling.plan);
175                 add_trace("calling", "present", "%d", mncc->calling.present);
176                 add_trace("calling", "screen", "%d", mncc->calling.screen);
177                 add_trace("calling", "number", "%s", mncc->calling.number);
178         }
179         p_callerinfo.isdn_port = p_m_portnum;
180         SCPY(p_callerinfo.interface, p_m_mISDNport->ifport->interface->name);
181         /* dialing information */
182         if (mncc->fields & MNCC_F_CALLED) {
183                 SCAT(p_dialinginfo.id, mncc->called.number);
184                 switch (mncc->called.type) {
185                         case 0x1:
186                         p_dialinginfo.ntype = INFO_NTYPE_INTERNATIONAL;
187                         break;
188                         case 0x2:
189                         p_dialinginfo.ntype = INFO_NTYPE_NATIONAL;
190                         break;
191                         case 0x4:
192                         p_dialinginfo.ntype = INFO_NTYPE_SUBSCRIBER;
193                         break;
194                         default:
195                         p_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
196                         break;
197                 }
198                 add_trace("dialing", "type", "%d", mncc->called.type);
199                 add_trace("dialing", "plan", "%d", mncc->called.plan);
200                 add_trace("dialing", "number", "%s", mncc->called.number);
201         }
202         /* redir info */
203         p_redirinfo.ntype = INFO_NTYPE_NOTPRESENT;
204         if (mncc->fields & MNCC_F_REDIRECTING) {
205                 switch (mncc->redirecting.present) {
206                         case 1:
207                         p_redirinfo.present = INFO_PRESENT_RESTRICTED;
208                         break;
209                         case 2:
210                         p_redirinfo.present = INFO_PRESENT_NOTAVAIL;
211                         break;
212                         default:
213                         p_redirinfo.present = INFO_PRESENT_ALLOWED;
214                         break;
215                 }
216                 switch (mncc->redirecting.screen) {
217                         case 0:
218                         p_redirinfo.screen = INFO_SCREEN_USER;
219                         break;
220                         case 1:
221                         p_redirinfo.screen = INFO_SCREEN_USER_VERIFIED_PASSED;
222                         break;
223                         case 2:
224                         p_redirinfo.screen = INFO_SCREEN_USER_VERIFIED_FAILED;
225                         break;
226                         default:
227                         p_redirinfo.screen = INFO_SCREEN_NETWORK;
228                         break;
229                 }
230                 switch (mncc->redirecting.type) {
231                         case 0x0:
232                         p_redirinfo.ntype = INFO_NTYPE_UNKNOWN;
233                         break;
234                         case 0x1:
235                         p_redirinfo.ntype = INFO_NTYPE_INTERNATIONAL;
236                         break;
237                         case 0x2:
238                         p_redirinfo.ntype = INFO_NTYPE_NATIONAL;
239                         break;
240                         case 0x4:
241                         p_redirinfo.ntype = INFO_NTYPE_SUBSCRIBER;
242                         break;
243                         default:
244                         p_redirinfo.ntype = INFO_NTYPE_UNKNOWN;
245                         break;
246                 }
247                 SCPY(p_redirinfo.id, mncc->redirecting.number);
248                 add_trace("redir", "type", "%d", mncc->redirecting.type);
249                 add_trace("redir", "plan", "%d", mncc->redirecting.plan);
250                 add_trace("redir", "present", "%d", mncc->redirecting.present);
251                 add_trace("redir", "screen", "%d", mncc->redirecting.screen);
252                 add_trace("redir", "number", "%s", mncc->redirecting.number);
253                 p_redirinfo.isdn_port = p_m_portnum;
254         }
255         /* bearer capability */
256         if (mncc->fields & MNCC_F_BEARER_CAP) {
257                 switch (mncc->bearer_cap.transfer) {
258                         case 1:
259                         p_capainfo.bearer_capa = INFO_BC_DATAUNRESTRICTED;
260                         break;
261                         case 2:
262                         case 3:
263                         p_capainfo.bearer_capa = INFO_BC_AUDIO;
264                         p_capainfo.bearer_info1 = (options.law=='a')?3:2;
265                         break;
266                         default:
267                         p_capainfo.bearer_capa = INFO_BC_SPEECH;
268                         p_capainfo.bearer_info1 = (options.law=='a')?3:2;
269                         break;
270                 }
271                 switch (mncc->bearer_cap.mode) {
272                         case 1:
273                         p_capainfo.bearer_mode = INFO_BMODE_PACKET;
274                         break;
275                         default:
276                         p_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
277                         break;
278                 }
279                 add_trace("bearer", "transfer", "%d", mncc->bearer_cap.transfer);
280                 add_trace("bearer", "mode", "%d", mncc->bearer_cap.mode);
281         } else {
282                 p_capainfo.bearer_capa = INFO_BC_SPEECH;
283                 p_capainfo.bearer_info1 = (options.law=='a')?3:2;
284                 p_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
285         }
286         /* if packet mode works some day, see dss1.cpp for conditions */
287         p_capainfo.source_mode = B_MODE_TRANSPARENT;
288
289         end_trace();
290
291         /* hunt channel */
292         ret = channel = hunt_bchannel();
293         if (ret < 0)
294                 goto no_channel;
295
296         /* open channel */
297         ret = seize_bchannel(channel, 1);
298         if (ret < 0) {
299                 no_channel:
300                 mncc = create_mncc(MNCC_REJ_REQ, p_m_g_callref);
301                 gsm_trace_header(p_m_mISDNport, this, MNCC_REJ_REQ, DIRECTION_OUT);
302                 mncc->fields |= MNCC_F_CAUSE;
303                 mncc->cause.coding = 3;
304                 mncc->cause.location = 1;
305                 mncc->cause.value = 34;
306                 add_trace("cause", "coding", "%d", mncc->cause.coding);
307                 add_trace("cause", "location", "%d", mncc->cause.location);
308                 add_trace("cause", "value", "%d", mncc->cause.value);
309                 add_trace("reason", NULL, "no channel");
310                 end_trace();
311                 send_and_free_mncc(p_m_g_instance, mncc->msg_type, mncc);
312                 new_state(PORT_STATE_RELEASE);
313                 trigger_work(&p_m_g_delete);
314                 return;
315         }
316         bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE);
317         if (bchannel_open(p_m_b_index))
318                 goto no_channel;
319
320         /* what infos did we got ... */
321         gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
322         if (p_callerinfo.id[0])
323                 add_trace("calling", "number", "%s", p_callerinfo.id);
324         else
325                 SPRINT(p_callerinfo.id, "imsi-%s", p_callerinfo.imsi);
326         add_trace("calling", "imsi", "%s", p_callerinfo.imsi);
327         add_trace("dialing", "number", "%s", p_dialinginfo.id);
328         end_trace();
329
330         /* create endpoint */
331         if (p_epointlist)
332                 FATAL("Incoming call but already got an endpoint.\n");
333         if (!(epoint = new Endpoint(p_serial, 0)))
334                 FATAL("No memory for Endpoint instance\n");
335         if (!(epoint->ep_app = new DEFAULT_ENDPOINT_APP(epoint, 0))) //incoming
336                 FATAL("No memory for Endpoint Application instance\n");
337         epointlist_new(epoint->ep_serial);
338
339         /* modify lchan to GSM codec V1 */
340         gsm_trace_header(p_m_mISDNport, this, MNCC_LCHAN_MODIFY, DIRECTION_OUT);
341         mode = create_mncc(MNCC_LCHAN_MODIFY, p_m_g_callref);
342         mode->lchan_mode = 0x01; /* GSM V1 */
343         add_trace("mode", NULL, "0x%02x", mode->lchan_mode);
344         end_trace();
345         send_and_free_mncc(p_m_g_instance, mode->msg_type, mode);
346
347         /* send call proceeding */
348         gsm_trace_header(p_m_mISDNport, this, MNCC_CALL_PROC_REQ, DIRECTION_OUT);
349         proceeding = create_mncc(MNCC_CALL_PROC_REQ, p_m_g_callref);
350         if (p_m_mISDNport->tones) {
351                 proceeding->fields |= MNCC_F_PROGRESS;
352                 proceeding->progress.coding = 3; /* GSM */
353                 proceeding->progress.location = 1;
354                 proceeding->progress.descr = 8;
355                 add_trace("progress", "coding", "%d", proceeding->progress.coding);
356                 add_trace("progress", "location", "%d", proceeding->progress.location);
357                 add_trace("progress", "descr", "%d", proceeding->progress.descr);
358         }
359         end_trace();
360         send_and_free_mncc(p_m_g_instance, proceeding->msg_type, proceeding);
361
362         new_state(PORT_STATE_IN_PROCEEDING);
363
364         if (p_m_mISDNport->tones && !p_m_g_tch_connected) { /* only if ... */
365                 gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
366                 end_trace();
367                 frame = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
368                 send_and_free_mncc(p_m_g_instance, frame->msg_type, frame);
369                 p_m_g_tch_connected = 1;
370         }
371
372         /* send setup message to endpoit */
373         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_SETUP);
374         message->param.setup.isdn_port = p_m_portnum;
375         message->param.setup.port_type = p_type;
376 //      message->param.setup.dtmf = 0;
377         memcpy(&message->param.setup.dialinginfo, &p_dialinginfo, sizeof(struct dialing_info));
378         memcpy(&message->param.setup.callerinfo, &p_callerinfo, sizeof(struct caller_info));
379         memcpy(&message->param.setup.capainfo, &p_capainfo, sizeof(struct capa_info));
380         SCPY((char *)message->param.setup.useruser.data, (char *)mncc->useruser.info);
381         message->param.setup.useruser.len = strlen(mncc->useruser.info);
382         message->param.setup.useruser.protocol = mncc->useruser.proto;
383         message_put(message);
384 }
385
386 /*
387  * MS sends message to port
388  */
389 static int message_ms(struct osmocom_ms *ms, int msg_type, void *arg)
390 {
391         struct gsm_mncc *mncc = (struct gsm_mncc *)arg;
392         unsigned int callref = mncc->callref;
393         class Port *port;
394         class Pgsm_ms *pgsm_ms = NULL;
395         char name[64];
396         struct mISDNport *mISDNport;
397
398         /* Special messages */
399         if (msg_type) {
400         }
401
402         /* find callref */
403         callref = mncc->callref;
404         port = port_first;
405         while(port) {
406                 if ((port->p_type & PORT_CLASS_GSM_MASK) == PORT_CLASS_GSM_MS) {
407                         pgsm_ms = (class Pgsm_ms *)port;
408                         if (pgsm_ms->p_m_g_callref == callref) {
409                                 break;
410                         }
411                 }
412                 port = port->next;
413         }
414
415         if (msg_type == GSM_TCHF_FRAME) {
416                 if (port)
417                         pgsm_ms->frame_receive((struct gsm_trau_frame *)arg);
418                 return 0;
419         }
420
421         if (!port) {
422                 if (msg_type != MNCC_SETUP_IND)
423                         return(0);
424                 /* find gsm ms port */
425                 mISDNport = mISDNport_first;
426                 while(mISDNport) {
427                         if (mISDNport->gsm_ms && !strcmp(mISDNport->ifport->gsm_ms_name, ms->name))
428                                 break;
429                         mISDNport = mISDNport->next;
430                 }
431                 if (!mISDNport) {
432                         struct gsm_mncc *rej;
433
434                         rej = create_mncc(MNCC_REJ_REQ, callref);
435                         rej->fields |= MNCC_F_CAUSE;
436                         rej->cause.coding = 3;
437                         rej->cause.location = 1;
438                         rej->cause.value = 27;
439                         gsm_trace_header(NULL, NULL, MNCC_REJ_REQ, DIRECTION_OUT);
440                         add_trace("cause", "coding", "%d", rej->cause.coding);
441                         add_trace("cause", "location", "%d", rej->cause.location);
442                         add_trace("cause", "value", "%d", rej->cause.value);
443                         end_trace();
444                         send_and_free_mncc(ms, rej->msg_type, rej);
445                         return 0;
446                 }
447                 /* creating port object, transparent until setup with hdlc */
448                 SPRINT(name, "%s-%d-in", mISDNport->ifport->interface->name, mISDNport->portnum);
449                 if (!(pgsm_ms = new Pgsm_ms(PORT_TYPE_GSM_MS_IN, mISDNport, name, NULL, 0, 0, B_MODE_TRANSPARENT)))
450
451                         FATAL("Cannot create Port instance.\n");
452         }
453
454         switch(msg_type) {
455                 case MNCC_SETUP_IND:
456                 pgsm_ms->setup_ind(msg_type, callref, mncc);
457                 break;
458
459                 case MNCC_ALERT_IND:
460                 pgsm_ms->alert_ind(msg_type, callref, mncc);
461                 break;
462
463                 case MNCC_SETUP_CNF:
464                 pgsm_ms->setup_cnf(msg_type, callref, mncc);
465                 break;
466
467                 case MNCC_SETUP_COMPL_IND:
468                 pgsm_ms->setup_compl_ind(msg_type, callref, mncc);
469                 break;
470
471                 case MNCC_DISC_IND:
472                 pgsm_ms->disc_ind(msg_type, callref, mncc);
473                 break;
474
475                 case MNCC_REL_IND:
476                 case MNCC_REL_CNF:
477                 case MNCC_REJ_IND:
478                 pgsm_ms->rel_ind(msg_type, callref, mncc);
479                 break;
480
481                 case MNCC_NOTIFY_IND:
482                 pgsm_ms->notify_ind(msg_type, callref, mncc);
483                 break;
484
485                 default:
486                 ;
487         }
488         return(0);
489 }
490
491 /* MESSAGE_SETUP */
492 void Pgsm_ms::message_setup(unsigned int epoint_id, int message_id, union parameter *param)
493 {
494         struct lcr_msg *message;
495         int ret;
496         struct epoint_list *epointlist;
497         struct gsm_mncc *mncc;
498         int channel;
499
500         /* copy setup infos to port */
501         memcpy(&p_callerinfo, &param->setup.callerinfo, sizeof(p_callerinfo));
502         memcpy(&p_dialinginfo, &param->setup.dialinginfo, sizeof(p_dialinginfo));
503         memcpy(&p_capainfo, &param->setup.capainfo, sizeof(p_capainfo));
504         memcpy(&p_redirinfo, &param->setup.redirinfo, sizeof(p_redirinfo));
505
506         /* no number */
507         if (!p_dialinginfo.id[0]) {
508                 gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
509                 add_trace("failure", NULL, "No dialed subscriber given.");
510                 end_trace();
511                 message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
512                 message->param.disconnectinfo.cause = 28;
513                 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
514                 message_put(message);
515                 new_state(PORT_STATE_RELEASE);
516                 trigger_work(&p_m_g_delete);
517                 return;
518         }
519         
520         /* release if port is blocked */
521         if (p_m_mISDNport->ifport->block) {
522                 gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
523                 add_trace("failure", NULL, "Port blocked.");
524                 end_trace();
525                 message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
526                 message->param.disconnectinfo.cause = 27; // temp. unavail.
527                 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
528                 message_put(message);
529                 new_state(PORT_STATE_RELEASE);
530                 trigger_work(&p_m_g_delete);
531                 return;
532         }
533
534         /* hunt channel */
535         ret = channel = hunt_bchannel();
536         if (ret < 0)
537                 goto no_channel;
538         /* open channel */
539         ret = seize_bchannel(channel, 1);
540         if (ret < 0) {
541                 no_channel:
542                 gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
543                 add_trace("failure", NULL, "No internal audio channel available.");
544                 end_trace();
545                 message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
546                 message->param.disconnectinfo.cause = 34;
547                 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
548                 message_put(message);
549                 new_state(PORT_STATE_RELEASE);
550                 trigger_work(&p_m_g_delete);
551                 return;
552         }
553         bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE);
554         if (bchannel_open(p_m_b_index))
555                 goto no_channel;
556
557         /* attach only if not already */
558         epointlist = p_epointlist;
559         while(epointlist) {
560                 if (epointlist->epoint_id == epoint_id)
561                         break;
562                 epointlist = epointlist->next;
563         }
564         if (!epointlist)
565                 epointlist_new(epoint_id);
566
567         /* creating l3id */
568         l1l2l3_trace_header(p_m_mISDNport, this, L3_NEW_L3ID_REQ, DIRECTION_OUT);
569         p_m_g_callref = new_callref++;
570         add_trace("callref", "new", "0x%x", p_m_g_callref);
571         end_trace();
572
573         gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
574         mncc = create_mncc(MNCC_SETUP_REQ, p_m_g_callref);
575         if (!strncasecmp(p_dialinginfo.id, "emerg", 5)) {
576                 mncc->emergency = 1;
577         } else {
578                 /* caller info (only clir) */
579                 switch (p_callerinfo.present) {
580                         case INFO_PRESENT_ALLOWED:
581                         mncc->clir.inv = 1;
582                         break;
583                         default:
584                         mncc->clir.sup = 1;
585                 }
586                 /* dialing information (mandatory) */
587                 mncc->fields |= MNCC_F_CALLED;
588                 mncc->called.type = 0; /* unknown */
589                 mncc->called.plan = 1; /* isdn */
590                 SCPY(mncc->called.number, p_dialinginfo.id);
591                 add_trace("dialing", "number", "%s", mncc->called.number);
592                 
593                 /* bearer capability (mandatory) */
594                 mncc->fields |= MNCC_F_BEARER_CAP;
595                 mncc->bearer_cap.coding = 0;
596                 mncc->bearer_cap.radio = 1;
597                 mncc->bearer_cap.speech_ctm = 0;
598                 mncc->bearer_cap.speech_ver[0] = 0;
599                 mncc->bearer_cap.speech_ver[1] = -1; /* end of list */
600                 switch (p_capainfo.bearer_capa) {
601                         case INFO_BC_DATAUNRESTRICTED:
602                         case INFO_BC_DATARESTRICTED:
603                         mncc->bearer_cap.transfer = 1;
604                         break;
605                         case INFO_BC_SPEECH:
606                         mncc->bearer_cap.transfer = 0;
607                         break;
608                         default:
609                         mncc->bearer_cap.transfer = 2;
610                         break;
611                 }
612                 switch (p_capainfo.bearer_mode) {
613                         case INFO_BMODE_PACKET:
614                         mncc->bearer_cap.mode = 1;
615                         break;
616                         default:
617                         mncc->bearer_cap.mode = 0;
618                         break;
619                 }
620         }
621
622         end_trace();
623         send_and_free_mncc(p_m_g_instance, mncc->msg_type, mncc);
624
625         new_state(PORT_STATE_OUT_SETUP);
626
627         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_PROCEEDING);
628         message_put(message);
629
630         new_state(PORT_STATE_OUT_PROCEEDING);
631 }
632
633 /*
634  * endpoint sends messages to the port
635  */
636 int Pgsm_ms::message_epoint(unsigned int epoint_id, int message_id, union parameter *param)
637 {
638         if (Pgsm::message_epoint(epoint_id, message_id, param))
639                 return(1);
640
641         switch(message_id) {
642                 case MESSAGE_SETUP: /* dial-out command received from epoint */
643                 if (p_state!=PORT_STATE_IDLE)
644                         break;
645                 message_setup(epoint_id, message_id, param);
646                 break;
647
648                 default:
649                 PDEBUG(DEBUG_GSM, "Pgsm_ms(%s) gsm port with (caller id %s) received unhandled nessage: %d\n", p_name, p_callerinfo.id, message_id);
650         }
651
652         return(1);
653 }
654
655 int gsm_ms_exit(int rc)
656 {
657
658         return(rc);
659 }
660
661 int gsm_ms_init(void)
662 {
663         INIT_LLIST_HEAD(&ms_list);
664         log_init(&log_info);
665         stderr_target = log_target_create_stderr();
666         log_add_target(stderr_target);
667         log_set_all_filter(stderr_target, 1);
668
669         l23_ctx = talloc_named_const(NULL, 1, "layer2 context");
670
671         return 0;
672 }
673
674 /* add a new GSM mobile instance */
675 int gsm_ms_new(const char *name, const char *socket_path)
676 {
677         struct osmocom_ms *ms = NULL;
678         int rc;
679
680         PDEBUG(DEBUG_GSM, "GSM: creating new instance '%s' on '%s'\n", name, socket_path);
681
682         ms = talloc_zero(l23_ctx, struct osmocom_ms);
683         if (!ms) {
684                 FATAL("Failed to allocate MS\n");
685         }
686         /* must add here, because other init processes may search in the list */
687         llist_add_tail(&ms->entity, &ms_list);
688
689
690         SPRINT(ms->name, name);
691
692         rc = layer2_open(ms, socket_path);
693         if (rc < 0) {
694                 FATAL("Failed during layer2_open()\n");
695         }
696
697         lapdm_init(&ms->l2_entity.lapdm_dcch, ms);
698         lapdm_init(&ms->l2_entity.lapdm_acch, ms);
699
700         rc = l23_app_init(ms);
701         if (rc < 0) {
702                 FATAL("Failed to init layer23\n");
703         }
704         ms->cclayer.mncc_recv = message_ms;
705
706         return 0;
707 }
708
709 int gsm_ms_delete(const char *name)
710 {
711         struct osmocom_ms *ms = NULL;
712         int found = 0;
713
714         PDEBUG(DEBUG_GSM, "GSM: destroying instance '%s'\n", name);
715
716         llist_for_each_entry(ms, &ms_list, entity) {
717                 if (!strcmp(ms->name, name)) {
718                         found = 1;
719                         break;
720                 }
721         }
722
723         if (!found) {
724                 FATAL("Failed delete layer23, instance '%s' not found\n", name);
725         }
726
727         l23_app_exit(ms);
728         lapdm_exit(&ms->l2_entity.lapdm_dcch);
729         lapdm_exit(&ms->l2_entity.lapdm_acch);
730
731         llist_del(&ms->entity);
732
733         return 0;
734 }
735
736 /*
737  * handles bsc select function within LCR's main loop
738  */
739 int handle_gsm_ms(void)
740 {
741         struct osmocom_ms *ms = NULL;
742         int work = 0;
743
744         llist_for_each_entry(ms, &ms_list, entity) {
745                 if (l23_app_work(ms))
746                         work = 1;
747 //              debug_reset_context();
748                 if (bsc_select_main(1)) /* polling */
749                         work = 1;
750         }
751
752         return work;
753 }
754