stasic.c: Fix printf format type mismatches with arguments.
[asterisk/asterisk.git] / channels / misdn / isdn_msg_parser.c
1 /*
2  * Chan_Misdn -- Channel Driver for Asterisk
3  *
4  * Interface to mISDN
5  *
6  * Copyright (C) 2004, Christian Richter
7  *
8  * Christian Richter <crich@beronet.com>
9  *
10  * This program is free software, distributed under the terms of
11  * the GNU General Public License
12  */
13
14 /*! \file
15  * \brief Interface to mISDN - message parser
16  * \author Christian Richter <crich@beronet.com>
17  */
18
19 /*** MODULEINFO
20         <support_level>extended</support_level>
21  ***/
22
23 #include "isdn_lib_intern.h"
24
25
26 #include "isdn_lib.h"
27
28 #include "ie.c"
29
30 /*!
31  * \internal
32  * \brief Build the name, number, name/number display message string
33  *
34  * \param display Display buffer to fill in
35  * \param display_length Length of the display buffer to fill in
36  * \param display_format Display format enumeration
37  * \param name Name string to use
38  * \param number Number string to use
39  *
40  * \return Nothing
41  */
42 static void build_display_str(char *display, size_t display_length, int display_format, const char *name, const char *number)
43 {
44         display[0] = 0;
45         switch (display_format) {
46         default:
47         case 0:         /* none */
48                 break;
49
50         case 1:         /* name */
51                 snprintf(display, display_length, "%s", name);
52                 break;
53
54         case 2:         /* number */
55                 snprintf(display, display_length, "%s", number);
56                 break;
57
58         case 3:         /* both */
59                 if (name[0] || number[0]) {
60                         snprintf(display, display_length, "\"%s\" <%s>", name, number);
61                 }
62                 break;
63         }
64 }
65
66 /*!
67  * \internal
68  * \brief Encode the Facility IE and put it into the message structure.
69  *
70  * \param ntmode Where the encoded facility was put when in NT mode.
71  * \param msg General message structure
72  * \param fac Data to encode into the facility ie.
73  * \param nt TRUE if in NT mode.
74  *
75  * \return Nothing
76  */
77 static void enc_ie_facility(unsigned char **ntmode, msg_t *msg, struct FacParm *fac, int nt)
78 {
79         int len;
80         Q931_info_t *qi;
81         unsigned char *p;
82         unsigned char buf[256];
83
84         len = encodeFac(buf, fac);
85         if (len <= 0) {
86                 /*
87                  * mISDN does not know how to build the requested facility structure
88                  * Clear facility information
89                  */
90                 fac->Function = Fac_None;
91                 return;
92         }
93
94         p = msg_put(msg, len);
95         if (nt) {
96                 *ntmode = p + 1;
97         } else {
98                 qi = (Q931_info_t *) (msg->data + mISDN_HEADER_LEN);
99                 qi->QI_ELEMENT(facility) = p - (unsigned char *) qi - sizeof(Q931_info_t);
100         }
101
102         memcpy(p, buf, len);
103
104         /* Clear facility information */
105         fac->Function = Fac_None;
106 }
107
108 /*!
109  * \internal
110  * \brief Decode the Facility IE.
111  *
112  * \param p Encoded facility ie data to decode. (NT mode)
113  * \param qi Encoded facility ie data to decode. (TE mode)
114  * \param fac Where to put the decoded facility ie data if it is available.
115  * \param nt TRUE if in NT mode.
116  * \param bc Associated B channel
117  *
118  * \return Nothing
119  */
120 static void dec_ie_facility(unsigned char *p, Q931_info_t *qi, struct FacParm *fac, int nt, struct misdn_bchannel *bc)
121 {
122         fac->Function = Fac_None;
123
124         if (!nt) {
125                 p = NULL;
126                 if (qi->QI_ELEMENT(facility)) {
127                         p = (unsigned char *) qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(facility) + 1;
128                 }
129         }
130         if (!p) {
131                 return;
132         }
133
134         if (decodeFac(p, fac)) {
135                 cb_log(3, bc->port, "Decoding facility ie failed! Unrecognized facility message?\n");
136         }
137 }
138
139
140
141 static void set_channel(struct misdn_bchannel *bc, int channel)
142 {
143
144         cb_log(3,bc->port,"set_channel: bc->channel:%d channel:%d\n", bc->channel, channel);
145
146
147         if (channel==0xff) {
148                 /* any channel */
149                 channel=-1;
150         }
151
152         /*  ALERT: is that everytime true ?  */
153         if (channel > 0 && bc->nt ) {
154
155                 if (bc->channel && ( bc->channel != 0xff) ) {
156                         cb_log(0,bc->port,"We already have a channel (%d)\n", bc->channel);
157                 } else {
158                         bc->channel = channel;
159                         cb_event(EVENT_NEW_CHANNEL,bc,NULL);
160                 }
161         }
162
163         if (channel > 0 && !bc->nt ) {
164                 bc->channel = channel;
165                 cb_event(EVENT_NEW_CHANNEL,bc,NULL);
166         }
167 }
168
169 static void parse_proceeding (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
170 {
171         int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
172         CALL_PROCEEDING_t *proceeding = (CALL_PROCEEDING_t *) (msg->data + HEADER_LEN);
173         //struct misdn_stack *stack=get_stack_by_bc(bc);
174
175         {
176                 int  exclusive, channel;
177                 dec_ie_channel_id(proceeding->CHANNEL_ID, (Q931_info_t *)proceeding, &exclusive, &channel, nt,bc);
178
179                 set_channel(bc,channel);
180
181         }
182
183         dec_ie_progress(proceeding->PROGRESS, (Q931_info_t *)proceeding, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc);
184
185         dec_ie_facility(proceeding->FACILITY, (Q931_info_t *) proceeding, &bc->fac_in, nt, bc);
186
187         /* dec_ie_redir_dn */
188
189 #ifdef DEBUG
190         printf("Parsing PROCEEDING Msg\n");
191 #endif
192 }
193 static msg_t *build_proceeding (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
194 {
195         int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
196         CALL_PROCEEDING_t *proceeding;
197         msg_t *msg =(msg_t*)create_l3msg(CC_PROCEEDING | REQUEST, MT_CALL_PROCEEDING,  bc?bc->l3_id:-1, sizeof(CALL_PROCEEDING_t) ,nt);
198
199         proceeding=(CALL_PROCEEDING_t*)((msg->data+HEADER_LEN));
200
201         enc_ie_channel_id(&proceeding->CHANNEL_ID, msg, 1,bc->channel, nt,bc);
202
203         if (nt)
204                 enc_ie_progress(&proceeding->PROGRESS, msg, 0, nt?1:5, 8, nt,bc);
205
206         if (bc->fac_out.Function != Fac_None) {
207                 enc_ie_facility(&proceeding->FACILITY, msg, &bc->fac_out, nt);
208         }
209
210         /* enc_ie_redir_dn */
211
212 #ifdef DEBUG
213         printf("Building PROCEEDING Msg\n");
214 #endif
215         return msg;
216 }
217
218 static void parse_alerting (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
219 {
220         int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
221         ALERTING_t *alerting = (ALERTING_t *) (msg->data + HEADER_LEN);
222         //Q931_info_t *qi=(Q931_info_t*)(msg->data+HEADER_LEN);
223
224         dec_ie_facility(alerting->FACILITY, (Q931_info_t *) alerting, &bc->fac_in, nt, bc);
225
226         /* dec_ie_redir_dn */
227
228         dec_ie_progress(alerting->PROGRESS, (Q931_info_t *)alerting, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc);
229
230 #ifdef DEBUG
231         printf("Parsing ALERTING Msg\n");
232 #endif
233
234
235 }
236
237 static msg_t *build_alerting (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
238 {
239         int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
240         ALERTING_t *alerting;
241         msg_t *msg =(msg_t*)create_l3msg(CC_ALERTING | REQUEST, MT_ALERTING,  bc?bc->l3_id:-1, sizeof(ALERTING_t) ,nt);
242
243         alerting=(ALERTING_t*)((msg->data+HEADER_LEN));
244
245         enc_ie_channel_id(&alerting->CHANNEL_ID, msg, 1,bc->channel, nt,bc);
246
247         if (nt)
248                 enc_ie_progress(&alerting->PROGRESS, msg, 0, nt?1:5, 8, nt,bc);
249
250         if (bc->fac_out.Function != Fac_None) {
251                 enc_ie_facility(&alerting->FACILITY, msg, &bc->fac_out, nt);
252         }
253
254         /* enc_ie_redir_dn */
255
256 #ifdef DEBUG
257         printf("Building ALERTING Msg\n");
258 #endif
259         return msg;
260 }
261
262
263 static void parse_progress (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
264 {
265         int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
266         PROGRESS_t *progress = (PROGRESS_t *) (msg->data + HEADER_LEN);
267         //Q931_info_t *qi=(Q931_info_t*)(msg->data+HEADER_LEN);
268
269         dec_ie_progress(progress->PROGRESS, (Q931_info_t *)progress, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc);
270
271         dec_ie_facility(progress->FACILITY, (Q931_info_t *) progress, &bc->fac_in, nt, bc);
272
273 #ifdef DEBUG
274         printf("Parsing PROGRESS Msg\n");
275 #endif
276 }
277
278 static msg_t *build_progress (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
279 {
280         int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
281         PROGRESS_t *progress;
282         msg_t *msg =(msg_t*)create_l3msg(CC_PROGRESS | REQUEST, MT_PROGRESS,  bc?bc->l3_id:-1, sizeof(PROGRESS_t) ,nt);
283
284         progress=(PROGRESS_t*)((msg->data+HEADER_LEN));
285
286         enc_ie_progress(&progress->PROGRESS, msg, 0, nt ? 1 : 5, 8, nt, bc);
287
288         if (bc->fac_out.Function != Fac_None) {
289                 enc_ie_facility(&progress->FACILITY, msg, &bc->fac_out, nt);
290         }
291
292 #ifdef DEBUG
293         printf("Building PROGRESS Msg\n");
294 #endif
295         return msg;
296 }
297
298 #if defined(AST_MISDN_ENHANCEMENTS)
299 /*!
300  * \internal
301  * \brief Extract the SETUP message's BC, HLC, and LLC encoded ie contents.
302  *
303  * \param setup Indexed setup message contents
304  * \param nt TRUE if in NT mode.
305  * \param bc Associated B channel
306  *
307  * \return Nothing
308  */
309 static void extract_setup_Bc_Hlc_Llc(SETUP_t *setup, int nt, struct misdn_bchannel *bc)
310 {
311         __u8 *p;
312         Q931_info_t *qi;
313
314         qi = (Q931_info_t *) setup;
315
316         /* Extract Bearer Capability */
317         if (nt) {
318                 p = (__u8 *) setup->BEARER;
319         } else {
320                 if (qi->QI_ELEMENT(bearer_capability)) {
321                         p = (__u8 *) qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(bearer_capability) + 1;
322                 } else {
323                         p = NULL;
324                 }
325         }
326         if (!p || *p == 0 || sizeof(bc->setup_bc_hlc_llc.Bc.Contents) < *p) {
327                 bc->setup_bc_hlc_llc.Bc.Length = 0;
328         } else {
329                 bc->setup_bc_hlc_llc.Bc.Length = *p;
330                 memcpy(bc->setup_bc_hlc_llc.Bc.Contents, p + 1, *p);
331         }
332
333         /* Extract Low Layer Compatibility */
334         if (nt) {
335                 p = (__u8 *) setup->LLC;
336         } else {
337                 if (qi->QI_ELEMENT(llc)) {
338                         p = (__u8 *) qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(llc) + 1;
339                 } else {
340                         p = NULL;
341                 }
342         }
343         if (!p || *p == 0 || sizeof(bc->setup_bc_hlc_llc.Llc.Contents) < *p) {
344                 bc->setup_bc_hlc_llc.Llc.Length = 0;
345         } else {
346                 bc->setup_bc_hlc_llc.Llc.Length = *p;
347                 memcpy(bc->setup_bc_hlc_llc.Llc.Contents, p + 1, *p);
348         }
349
350         /* Extract High Layer Compatibility */
351         if (nt) {
352                 p = (__u8 *) setup->HLC;
353         } else {
354                 if (qi->QI_ELEMENT(hlc)) {
355                         p = (__u8 *) qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(hlc) + 1;
356                 } else {
357                         p = NULL;
358                 }
359         }
360         if (!p || *p == 0 || sizeof(bc->setup_bc_hlc_llc.Hlc.Contents) < *p) {
361                 bc->setup_bc_hlc_llc.Hlc.Length = 0;
362         } else {
363                 bc->setup_bc_hlc_llc.Hlc.Length = *p;
364                 memcpy(bc->setup_bc_hlc_llc.Hlc.Contents, p + 1, *p);
365         }
366 }
367 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
368
369 static void parse_setup (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
370 {
371         int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
372         SETUP_t *setup = (SETUP_t *) (msg->data + HEADER_LEN);
373         Q931_info_t *qi = (Q931_info_t *) (msg->data + HEADER_LEN);
374         int type;
375         int plan;
376         int present;
377         int screen;
378         int reason;
379
380 #ifdef DEBUG
381         printf("Parsing SETUP Msg\n");
382 #endif
383
384         dec_ie_calling_pn(setup->CALLING_PN, qi, &type, &plan, &present, &screen, bc->caller.number, sizeof(bc->caller.number), nt, bc);
385         bc->caller.number_type = type;
386         bc->caller.number_plan = plan;
387         switch (present) {
388         default:
389         case 0:
390                 bc->caller.presentation = 0;    /* presentation allowed */
391                 break;
392         case 1:
393                 bc->caller.presentation = 1;    /* presentation restricted */
394                 break;
395         case 2:
396                 bc->caller.presentation = 2;    /* Number not available */
397                 break;
398         }
399         if (0 <= screen) {
400                 bc->caller.screening = screen;
401         } else {
402                 bc->caller.screening = 0;       /* Unscreened */
403         }
404
405         dec_ie_facility(setup->FACILITY, (Q931_info_t *) setup, &bc->fac_in, nt, bc);
406
407         dec_ie_called_pn(setup->CALLED_PN, (Q931_info_t *) setup, &type, &plan, bc->dialed.number, sizeof(bc->dialed.number), nt, bc);
408         bc->dialed.number_type = type;
409         bc->dialed.number_plan = plan;
410
411         dec_ie_keypad(setup->KEYPAD, (Q931_info_t *) setup, bc->keypad, sizeof(bc->keypad), nt, bc);
412
413         dec_ie_complete(setup->COMPLETE, (Q931_info_t *) setup, &bc->sending_complete, nt, bc);
414
415         dec_ie_redir_nr(setup->REDIR_NR, (Q931_info_t *) setup, &type, &plan, &present, &screen, &reason, bc->redirecting.from.number, sizeof(bc->redirecting.from.number), nt, bc);
416         bc->redirecting.from.number_type = type;
417         bc->redirecting.from.number_plan = plan;
418         switch (present) {
419         default:
420         case 0:
421                 bc->redirecting.from.presentation = 0;  /* presentation allowed */
422                 break;
423         case 1:
424                 bc->redirecting.from.presentation = 1;  /* presentation restricted */
425                 break;
426         case 2:
427                 bc->redirecting.from.presentation = 2;  /* Number not available */
428                 break;
429         }
430         if (0 <= screen) {
431                 bc->redirecting.from.screening = screen;
432         } else {
433                 bc->redirecting.from.screening = 0;     /* Unscreened */
434         }
435         if (0 <= reason) {
436                 bc->redirecting.reason = reason;
437         } else {
438                 bc->redirecting.reason = mISDN_REDIRECTING_REASON_UNKNOWN;
439         }
440
441         {
442                 int  coding, capability, mode, rate, multi, user, async, urate, stopbits, dbits, parity;
443
444                 dec_ie_bearer(setup->BEARER, (Q931_info_t *)setup, &coding, &capability, &mode, &rate, &multi, &user, &async, &urate, &stopbits, &dbits, &parity, nt,bc);
445                 switch (capability) {
446                 case -1: bc->capability=INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
447                         break;
448                 case 0: bc->capability=INFO_CAPABILITY_SPEECH;
449                         break;
450                 case 18: bc->capability=INFO_CAPABILITY_VIDEO;
451                         break;
452                 case 8: bc->capability=INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
453                         bc->user1 = user;
454                         bc->urate = urate;
455
456                         bc->rate = rate;
457                         bc->mode = mode;
458                         break;
459                 case 9: bc->capability=INFO_CAPABILITY_DIGITAL_RESTRICTED;
460                         break;
461                 default:
462                         break;
463                 }
464
465                 switch(user) {
466                 case 2:
467                         bc->law=INFO_CODEC_ULAW;
468                         break;
469                 case 3:
470                         bc->law=INFO_CODEC_ALAW;
471                         break;
472                 default:
473                         bc->law=INFO_CODEC_ALAW;
474
475                 }
476
477                 bc->capability=capability;
478         }
479         {
480                 int  exclusive, channel;
481                 dec_ie_channel_id(setup->CHANNEL_ID, (Q931_info_t *)setup, &exclusive, &channel, nt,bc);
482
483                 set_channel(bc,channel);
484         }
485
486         {
487                 int  protocol ;
488                 dec_ie_useruser(setup->USER_USER, (Q931_info_t *)setup, &protocol, bc->uu, &bc->uulen, nt,bc);
489                 if (bc->uulen) cb_log(1, bc->port, "USERUSERINFO:%s\n", bc->uu);
490                 else
491                 cb_log(1, bc->port, "NO USERUSERINFO\n");
492         }
493
494         dec_ie_progress(setup->PROGRESS, (Q931_info_t *)setup, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc);
495
496 #if defined(AST_MISDN_ENHANCEMENTS)
497         extract_setup_Bc_Hlc_Llc(setup, nt, bc);
498 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
499 }
500
501 #define ANY_CHANNEL 0xff /* IE attribute for 'any channel' */
502 static msg_t *build_setup (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
503 {
504         int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
505         SETUP_t *setup;
506         msg_t *msg =(msg_t*)create_l3msg(CC_SETUP | REQUEST, MT_SETUP,  bc?bc->l3_id:-1, sizeof(SETUP_t) ,nt);
507         int is_ptp;
508         enum FacFunction fac_type;
509
510         setup=(SETUP_t*)((msg->data+HEADER_LEN));
511
512         if (bc->channel == 0 || bc->channel == ANY_CHANNEL || bc->channel==-1)
513                 enc_ie_channel_id(&setup->CHANNEL_ID, msg, 0, bc->channel, nt,bc);
514         else
515                 enc_ie_channel_id(&setup->CHANNEL_ID, msg, 1, bc->channel, nt,bc);
516
517         fac_type = bc->fac_out.Function;
518         if (fac_type != Fac_None) {
519                 enc_ie_facility(&setup->FACILITY, msg, &bc->fac_out, nt);
520         }
521
522         enc_ie_calling_pn(&setup->CALLING_PN, msg, bc->caller.number_type, bc->caller.number_plan,
523                 bc->caller.presentation, bc->caller.screening, bc->caller.number, nt, bc);
524
525         if (bc->dialed.number[0]) {
526                 enc_ie_called_pn(&setup->CALLED_PN, msg, bc->dialed.number_type, bc->dialed.number_plan, bc->dialed.number, nt, bc);
527         }
528
529         switch (bc->outgoing_colp) {
530         case 0:/* pass */
531         case 1:/* restricted */
532                 is_ptp = misdn_lib_is_ptp(bc->port);
533                 if (bc->redirecting.from.number[0]
534                         && ((!is_ptp && nt)
535                                 || (is_ptp
536 #if defined(AST_MISDN_ENHANCEMENTS)
537                                         /*
538                                          * There is no need to send out this ie when we are also sending
539                                          * a Fac_DivertingLegInformation2 as well.  The
540                                          * Fac_DivertingLegInformation2 supercedes the information in
541                                          * this ie.
542                                          */
543                                         && fac_type != Fac_DivertingLegInformation2
544 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
545                         ))) {
546 #if 1
547                         /* ETSI and Q.952 do not define the screening field */
548                         enc_ie_redir_nr(&setup->REDIR_NR, msg, bc->redirecting.from.number_type,
549                                 bc->redirecting.from.number_plan, bc->redirecting.from.presentation, 0,
550                                 bc->redirecting.reason, bc->redirecting.from.number, nt, bc);
551 #else
552                         /* Q.931 defines the screening field */
553                         enc_ie_redir_nr(&setup->REDIR_NR, msg, bc->redirecting.from.number_type,
554                                 bc->redirecting.from.number_plan, bc->redirecting.from.presentation,
555                                 bc->redirecting.from.screening, bc->redirecting.reason,
556                                 bc->redirecting.from.number, nt, bc);
557 #endif
558                 }
559                 break;
560         default:
561                 break;
562         }
563
564         if (bc->keypad[0]) {
565                 enc_ie_keypad(&setup->KEYPAD, msg, bc->keypad, nt,bc);
566         }
567
568
569
570         if (*bc->display) {
571                 enc_ie_display(&setup->DISPLAY, msg, bc->display, nt, bc);
572         } else if (nt && bc->caller.presentation == 0) {
573                 char display[sizeof(bc->display)];
574
575                 /* Presentation is allowed */
576                 build_display_str(display, sizeof(display), bc->display_setup, bc->caller.name, bc->caller.number);
577                 if (display[0]) {
578                         enc_ie_display(&setup->DISPLAY, msg, display, nt, bc);
579                 }
580         }
581
582         {
583                 int coding = 0;
584                 int capability;
585                 int mode = 0;   /* 2 for packet! */
586                 int user;
587                 int rate = 0x10;
588
589                 switch (bc->law) {
590                 case INFO_CODEC_ULAW: user=2;
591                         break;
592                 case INFO_CODEC_ALAW: user=3;
593                         break;
594                 default:
595                         user=3;
596                 }
597
598                 switch (bc->capability) {
599                 case INFO_CAPABILITY_SPEECH: capability = 0;
600                         break;
601                 case INFO_CAPABILITY_DIGITAL_UNRESTRICTED: capability = 8;
602                         user=-1;
603                         mode=bc->mode;
604                         rate=bc->rate;
605                         break;
606                 case INFO_CAPABILITY_DIGITAL_RESTRICTED: capability = 9;
607                         user=-1;
608                         break;
609                 default:
610                         capability=bc->capability;
611                 }
612
613                 enc_ie_bearer(&setup->BEARER, msg, coding, capability, mode, rate, -1, user, nt,bc);
614         }
615
616         if (bc->sending_complete) {
617                 enc_ie_complete(&setup->COMPLETE,msg, bc->sending_complete, nt, bc);
618         }
619
620         if (bc->uulen) {
621                 int  protocol=4;
622                 enc_ie_useruser(&setup->USER_USER, msg, protocol, bc->uu, bc->uulen, nt,bc);
623                 cb_log(1, bc->port, "ENCODING USERUSERINFO:%s\n", bc->uu);
624         }
625
626 #if defined(AST_MISDN_ENHANCEMENTS)
627         extract_setup_Bc_Hlc_Llc(setup, nt, bc);
628 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
629
630 #ifdef DEBUG
631         printf("Building SETUP Msg\n");
632 #endif
633         return msg;
634 }
635
636 static void parse_connect (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
637 {
638         int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
639         CONNECT_t *connect = (CONNECT_t *) (msg->data + HEADER_LEN);
640         int type;
641         int plan;
642         int pres;
643         int screen;
644
645         bc->ces = connect->ces;
646
647         dec_ie_progress(connect->PROGRESS, (Q931_info_t *)connect, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc);
648
649         dec_ie_connected_pn(connect->CONNECT_PN, (Q931_info_t *) connect, &type, &plan,
650                 &pres, &screen, bc->connected.number, sizeof(bc->connected.number), nt, bc);
651         bc->connected.number_type = type;
652         bc->connected.number_plan = plan;
653         switch (pres) {
654         default:
655         case 0:
656                 bc->connected.presentation = 0; /* presentation allowed */
657                 break;
658         case 1:
659                 bc->connected.presentation = 1; /* presentation restricted */
660                 break;
661         case 2:
662                 bc->connected.presentation = 2; /* Number not available */
663                 break;
664         }
665         if (0 <= screen) {
666                 bc->connected.screening = screen;
667         } else {
668                 bc->connected.screening = 0;    /* Unscreened */
669         }
670
671         dec_ie_facility(connect->FACILITY, (Q931_info_t *) connect, &bc->fac_in, nt, bc);
672
673         /*
674                 cb_log(1,bc->port,"CONNETED PN: %s cpn_dialplan:%d\n", connected_pn, type);
675         */
676
677 #ifdef DEBUG
678         printf("Parsing CONNECT Msg\n");
679 #endif
680 }
681
682 static msg_t *build_connect (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
683 {
684         int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
685         CONNECT_t *connect;
686         msg_t *msg =(msg_t*)create_l3msg(CC_CONNECT | REQUEST, MT_CONNECT,  bc?bc->l3_id:-1, sizeof(CONNECT_t) ,nt);
687
688         cb_log(6,bc->port,"BUILD_CONNECT: bc:%p bc->l3id:%d, nt:%d\n",bc,bc->l3_id,nt);
689
690         connect=(CONNECT_t*)((msg->data+HEADER_LEN));
691
692         if (nt) {
693                 time_t now;
694                 time(&now);
695                 enc_ie_date(&connect->DATE, msg, now, nt,bc);
696         }
697
698         switch (bc->outgoing_colp) {
699         case 0:/* pass */
700         case 1:/* restricted */
701                 enc_ie_connected_pn(&connect->CONNECT_PN, msg, bc->connected.number_type,
702                         bc->connected.number_plan, bc->connected.presentation,
703                         bc->connected.screening, bc->connected.number, nt, bc);
704                 break;
705         default:
706                 break;
707         }
708
709         if (nt && bc->connected.presentation == 0) {
710                 char display[sizeof(bc->display)];
711
712                 /* Presentation is allowed */
713                 build_display_str(display, sizeof(display), bc->display_connected, bc->connected.name, bc->connected.number);
714                 if (display[0]) {
715                         enc_ie_display(&connect->DISPLAY, msg, display, nt, bc);
716                 }
717         }
718
719         if (bc->fac_out.Function != Fac_None) {
720                 enc_ie_facility(&connect->FACILITY, msg, &bc->fac_out, nt);
721         }
722
723 #ifdef DEBUG
724         printf("Building CONNECT Msg\n");
725 #endif
726         return msg;
727 }
728
729 static void parse_setup_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
730 {
731         int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
732         SETUP_ACKNOWLEDGE_t *setup_acknowledge = (SETUP_ACKNOWLEDGE_t *) (msg->data + HEADER_LEN);
733
734         {
735                 int  exclusive, channel;
736                 dec_ie_channel_id(setup_acknowledge->CHANNEL_ID, (Q931_info_t *)setup_acknowledge, &exclusive, &channel, nt,bc);
737
738
739                 set_channel(bc, channel);
740         }
741
742         dec_ie_progress(setup_acknowledge->PROGRESS, (Q931_info_t *)setup_acknowledge, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc);
743
744         dec_ie_facility(setup_acknowledge->FACILITY, (Q931_info_t *) setup_acknowledge, &bc->fac_in, nt, bc);
745
746 #ifdef DEBUG
747         printf("Parsing SETUP_ACKNOWLEDGE Msg\n");
748 #endif
749
750
751 }
752
753 static msg_t *build_setup_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
754 {
755         int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
756         SETUP_ACKNOWLEDGE_t *setup_acknowledge;
757         msg_t *msg =(msg_t*)create_l3msg(CC_SETUP_ACKNOWLEDGE | REQUEST, MT_SETUP_ACKNOWLEDGE,  bc?bc->l3_id:-1, sizeof(SETUP_ACKNOWLEDGE_t) ,nt);
758
759         setup_acknowledge=(SETUP_ACKNOWLEDGE_t*)((msg->data+HEADER_LEN));
760
761         enc_ie_channel_id(&setup_acknowledge->CHANNEL_ID, msg, 1,bc->channel, nt,bc);
762
763         if (nt)
764                 enc_ie_progress(&setup_acknowledge->PROGRESS, msg, 0, nt?1:5, 8, nt,bc);
765
766         if (bc->fac_out.Function != Fac_None) {
767                 enc_ie_facility(&setup_acknowledge->FACILITY, msg, &bc->fac_out, nt);
768         }
769
770 #ifdef DEBUG
771         printf("Building SETUP_ACKNOWLEDGE Msg\n");
772 #endif
773         return msg;
774 }
775
776 static void parse_connect_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
777 {
778 #ifdef DEBUG
779         printf("Parsing CONNECT_ACKNOWLEDGE Msg\n");
780 #endif
781
782
783 }
784
785 static msg_t *build_connect_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
786 {
787         int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
788         CONNECT_ACKNOWLEDGE_t *connect_acknowledge;
789         msg_t *msg =(msg_t*)create_l3msg(CC_CONNECT | RESPONSE, MT_CONNECT,  bc?bc->l3_id:-1, sizeof(CONNECT_ACKNOWLEDGE_t) ,nt);
790
791         connect_acknowledge=(CONNECT_ACKNOWLEDGE_t*)((msg->data+HEADER_LEN));
792
793         enc_ie_channel_id(&connect_acknowledge->CHANNEL_ID, msg, 1, bc->channel, nt,bc);
794
795 #ifdef DEBUG
796         printf("Building CONNECT_ACKNOWLEDGE Msg\n");
797 #endif
798         return msg;
799 }
800
801 static void parse_user_information (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
802 {
803 #ifdef DEBUG
804         printf("Parsing USER_INFORMATION Msg\n");
805 #endif
806
807
808 }
809
810 static msg_t *build_user_information (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
811 {
812         msg_t *msg =(msg_t*)create_l3msg(CC_USER_INFORMATION | REQUEST, MT_USER_INFORMATION,  bc?bc->l3_id:-1, sizeof(USER_INFORMATION_t) ,nt);
813
814 #ifdef DEBUG
815         printf("Building USER_INFORMATION Msg\n");
816 #endif
817         return msg;
818 }
819
820 static void parse_suspend_reject (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
821 {
822 #ifdef DEBUG
823         printf("Parsing SUSPEND_REJECT Msg\n");
824 #endif
825
826
827 }
828
829 static msg_t *build_suspend_reject (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
830 {
831         msg_t *msg =(msg_t*)create_l3msg(CC_SUSPEND_REJECT | REQUEST, MT_SUSPEND_REJECT,  bc?bc->l3_id:-1, sizeof(SUSPEND_REJECT_t) ,nt);
832
833 #ifdef DEBUG
834         printf("Building SUSPEND_REJECT Msg\n");
835 #endif
836         return msg;
837 }
838
839 static void parse_resume_reject (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
840 {
841 #ifdef DEBUG
842         printf("Parsing RESUME_REJECT Msg\n");
843 #endif
844
845
846 }
847
848 static msg_t *build_resume_reject (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
849 {
850         msg_t *msg =(msg_t*)create_l3msg(CC_RESUME_REJECT | REQUEST, MT_RESUME_REJECT,  bc?bc->l3_id:-1, sizeof(RESUME_REJECT_t) ,nt);
851
852 #ifdef DEBUG
853         printf("Building RESUME_REJECT Msg\n");
854 #endif
855         return msg;
856 }
857
858 static void parse_hold (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
859 {
860 #ifdef DEBUG
861         printf("Parsing HOLD Msg\n");
862 #endif
863
864
865 }
866
867 static msg_t *build_hold (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
868 {
869         msg_t *msg =(msg_t*)create_l3msg(CC_HOLD | REQUEST, MT_HOLD,  bc?bc->l3_id:-1, sizeof(HOLD_t) ,nt);
870
871 #ifdef DEBUG
872         printf("Building HOLD Msg\n");
873 #endif
874         return msg;
875 }
876
877 static void parse_suspend (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
878 {
879 #ifdef DEBUG
880         printf("Parsing SUSPEND Msg\n");
881 #endif
882
883
884 }
885
886 static msg_t *build_suspend (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
887 {
888         msg_t *msg =(msg_t*)create_l3msg(CC_SUSPEND | REQUEST, MT_SUSPEND,  bc?bc->l3_id:-1, sizeof(SUSPEND_t) ,nt);
889
890 #ifdef DEBUG
891         printf("Building SUSPEND Msg\n");
892 #endif
893         return msg;
894 }
895
896 static void parse_resume (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
897 {
898 #ifdef DEBUG
899         printf("Parsing RESUME Msg\n");
900 #endif
901
902
903 }
904
905 static msg_t *build_resume (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
906 {
907         msg_t *msg =(msg_t*)create_l3msg(CC_RESUME | REQUEST, MT_RESUME,  bc?bc->l3_id:-1, sizeof(RESUME_t) ,nt);
908
909 #ifdef DEBUG
910         printf("Building RESUME Msg\n");
911 #endif
912         return msg;
913 }
914
915 static void parse_hold_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
916 {
917 #ifdef DEBUG
918         printf("Parsing HOLD_ACKNOWLEDGE Msg\n");
919 #endif
920
921
922 }
923
924 static msg_t *build_hold_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
925 {
926         msg_t *msg =(msg_t*)create_l3msg(CC_HOLD_ACKNOWLEDGE | REQUEST, MT_HOLD_ACKNOWLEDGE,  bc?bc->l3_id:-1, sizeof(HOLD_ACKNOWLEDGE_t) ,nt);
927
928 #ifdef DEBUG
929         printf("Building HOLD_ACKNOWLEDGE Msg\n");
930 #endif
931         return msg;
932 }
933
934 static void parse_suspend_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
935 {
936 #ifdef DEBUG
937         printf("Parsing SUSPEND_ACKNOWLEDGE Msg\n");
938 #endif
939
940
941 }
942
943 static msg_t *build_suspend_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
944 {
945         msg_t *msg =(msg_t*)create_l3msg(CC_SUSPEND_ACKNOWLEDGE | REQUEST, MT_SUSPEND_ACKNOWLEDGE,  bc?bc->l3_id:-1, sizeof(SUSPEND_ACKNOWLEDGE_t) ,nt);
946
947 #ifdef DEBUG
948         printf("Building SUSPEND_ACKNOWLEDGE Msg\n");
949 #endif
950         return msg;
951 }
952
953 static void parse_resume_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
954 {
955 #ifdef DEBUG
956         printf("Parsing RESUME_ACKNOWLEDGE Msg\n");
957 #endif
958
959
960 }
961
962 static msg_t *build_resume_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
963 {
964         msg_t *msg =(msg_t*)create_l3msg(CC_RESUME_ACKNOWLEDGE | REQUEST, MT_RESUME_ACKNOWLEDGE,  bc?bc->l3_id:-1, sizeof(RESUME_ACKNOWLEDGE_t) ,nt);
965
966 #ifdef DEBUG
967         printf("Building RESUME_ACKNOWLEDGE Msg\n");
968 #endif
969         return msg;
970 }
971
972 static void parse_hold_reject (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
973 {
974 #ifdef DEBUG
975         printf("Parsing HOLD_REJECT Msg\n");
976 #endif
977
978
979 }
980
981 static msg_t *build_hold_reject (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
982 {
983         msg_t *msg =(msg_t*)create_l3msg(CC_HOLD_REJECT | REQUEST, MT_HOLD_REJECT,  bc?bc->l3_id:-1, sizeof(HOLD_REJECT_t) ,nt);
984
985 #ifdef DEBUG
986         printf("Building HOLD_REJECT Msg\n");
987 #endif
988         return msg;
989 }
990
991 static void parse_retrieve (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
992 {
993 #ifdef DEBUG
994         printf("Parsing RETRIEVE Msg\n");
995 #endif
996
997
998 }
999
1000 static msg_t *build_retrieve (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
1001 {
1002         msg_t *msg =(msg_t*)create_l3msg(CC_RETRIEVE | REQUEST, MT_RETRIEVE,  bc?bc->l3_id:-1, sizeof(RETRIEVE_t) ,nt);
1003
1004 #ifdef DEBUG
1005         printf("Building RETRIEVE Msg\n");
1006 #endif
1007         return msg;
1008 }
1009
1010 static void parse_retrieve_acknowledge (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
1011 {
1012 #ifdef DEBUG
1013         printf("Parsing RETRIEVE_ACKNOWLEDGE Msg\n");
1014 #endif
1015
1016
1017 }
1018
1019 static msg_t *build_retrieve_acknowledge (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
1020 {
1021         int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
1022         RETRIEVE_ACKNOWLEDGE_t *retrieve_acknowledge;
1023         msg_t *msg =(msg_t*)create_l3msg(CC_RETRIEVE_ACKNOWLEDGE | REQUEST, MT_RETRIEVE_ACKNOWLEDGE,  bc?bc->l3_id:-1, sizeof(RETRIEVE_ACKNOWLEDGE_t) ,nt);
1024
1025         retrieve_acknowledge=(RETRIEVE_ACKNOWLEDGE_t*)((msg->data+HEADER_LEN));
1026
1027         enc_ie_channel_id(&retrieve_acknowledge->CHANNEL_ID, msg, 1, bc->channel, nt,bc);
1028 #ifdef DEBUG
1029         printf("Building RETRIEVE_ACKNOWLEDGE Msg\n");
1030 #endif
1031         return msg;
1032 }
1033
1034 static void parse_retrieve_reject (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
1035 {
1036 #ifdef DEBUG
1037         printf("Parsing RETRIEVE_REJECT Msg\n");
1038 #endif
1039
1040
1041 }
1042
1043 static msg_t *build_retrieve_reject (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
1044 {
1045         msg_t *msg =(msg_t*)create_l3msg(CC_RETRIEVE_REJECT | REQUEST, MT_RETRIEVE_REJECT,  bc?bc->l3_id:-1, sizeof(RETRIEVE_REJECT_t) ,nt);
1046
1047 #ifdef DEBUG
1048         printf("Building RETRIEVE_REJECT Msg\n");
1049 #endif
1050         return msg;
1051 }
1052
1053 static void parse_disconnect (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
1054 {
1055         int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
1056         DISCONNECT_t *disconnect = (DISCONNECT_t *) (msg->data + HEADER_LEN);
1057         int location;
1058         int cause;
1059         dec_ie_cause(disconnect->CAUSE, (Q931_info_t *)(disconnect), &location, &cause, nt,bc);
1060         if (cause>0) bc->cause=cause;
1061
1062         dec_ie_facility(disconnect->FACILITY, (Q931_info_t *) disconnect, &bc->fac_in, nt, bc);
1063
1064         dec_ie_progress(disconnect->PROGRESS, (Q931_info_t *)disconnect, &bc->progress_coding, &bc->progress_location, &bc->progress_indicator, nt, bc);
1065 #ifdef DEBUG
1066         printf("Parsing DISCONNECT Msg\n");
1067 #endif
1068
1069
1070 }
1071
1072 static msg_t *build_disconnect (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
1073 {
1074         int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
1075         DISCONNECT_t *disconnect;
1076         msg_t *msg =(msg_t*)create_l3msg(CC_DISCONNECT | REQUEST, MT_DISCONNECT,  bc?bc->l3_id:-1, sizeof(DISCONNECT_t) ,nt);
1077
1078         disconnect=(DISCONNECT_t*)((msg->data+HEADER_LEN));
1079
1080         enc_ie_cause(&disconnect->CAUSE, msg, (nt)?1:0, bc->out_cause,nt,bc);
1081         if (nt) {
1082                 enc_ie_progress(&disconnect->PROGRESS, msg, 0, nt ? 1 : 5, 8, nt, bc);
1083         }
1084
1085         if (bc->fac_out.Function != Fac_None) {
1086                 enc_ie_facility(&disconnect->FACILITY, msg, &bc->fac_out, nt);
1087         }
1088
1089         if (bc->uulen) {
1090                 int  protocol=4;
1091                 enc_ie_useruser(&disconnect->USER_USER, msg, protocol, bc->uu, bc->uulen, nt,bc);
1092                 cb_log(1, bc->port, "ENCODING USERUSERINFO:%s\n", bc->uu);
1093         }
1094
1095 #ifdef DEBUG
1096         printf("Building DISCONNECT Msg\n");
1097 #endif
1098         return msg;
1099 }
1100
1101 static void parse_restart (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
1102 {
1103         int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
1104         RESTART_t *restart = (RESTART_t *) (msg->data + HEADER_LEN);
1105
1106         struct misdn_stack *stack=get_stack_by_bc(bc);
1107
1108 #ifdef DEBUG
1109         printf("Parsing RESTART Msg\n");
1110 #endif
1111
1112         {
1113                 int  exclusive;
1114                 dec_ie_channel_id(restart->CHANNEL_ID, (Q931_info_t *)restart, &exclusive, &bc->restart_channel, nt,bc);
1115                 cb_log(3, stack->port, "CC_RESTART Request on channel:%d on this port.\n", bc->restart_channel);
1116         }
1117
1118 }
1119
1120 static msg_t *build_restart (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
1121 {
1122         int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
1123         RESTART_t *restart;
1124         msg_t *msg =(msg_t*)create_l3msg(CC_RESTART | REQUEST, MT_RESTART,  bc?bc->l3_id:-1, sizeof(RESTART_t) ,nt);
1125
1126         restart=(RESTART_t*)((msg->data+HEADER_LEN));
1127
1128 #ifdef DEBUG
1129         printf("Building RESTART Msg\n");
1130 #endif
1131
1132         if (bc->channel > 0) {
1133                 enc_ie_channel_id(&restart->CHANNEL_ID, msg, 1,bc->channel, nt,bc);
1134                 enc_ie_restart_ind(&restart->RESTART_IND, msg, 0x80, nt, bc);
1135         } else {
1136                 enc_ie_restart_ind(&restart->RESTART_IND, msg, 0x87, nt, bc);
1137         }
1138
1139         cb_log(0,bc->port, "Restarting channel %d\n", bc->channel);
1140         return msg;
1141 }
1142
1143 static void parse_release (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
1144 {
1145         int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
1146         RELEASE_t *release = (RELEASE_t *) (msg->data + HEADER_LEN);
1147         int location;
1148         int cause;
1149
1150         dec_ie_cause(release->CAUSE, (Q931_info_t *)(release), &location, &cause, nt,bc);
1151         if (cause>0) bc->cause=cause;
1152
1153         dec_ie_facility(release->FACILITY, (Q931_info_t *) release, &bc->fac_in, nt, bc);
1154
1155 #ifdef DEBUG
1156         printf("Parsing RELEASE Msg\n");
1157 #endif
1158
1159
1160 }
1161
1162 static msg_t *build_release (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
1163 {
1164         int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
1165         RELEASE_t *release;
1166         msg_t *msg =(msg_t*)create_l3msg(CC_RELEASE | REQUEST, MT_RELEASE,  bc?bc->l3_id:-1, sizeof(RELEASE_t) ,nt);
1167
1168         release=(RELEASE_t*)((msg->data+HEADER_LEN));
1169
1170         if (bc->out_cause>= 0)
1171                 enc_ie_cause(&release->CAUSE, msg, nt?1:0, bc->out_cause, nt,bc);
1172
1173         if (bc->fac_out.Function != Fac_None) {
1174                 enc_ie_facility(&release->FACILITY, msg, &bc->fac_out, nt);
1175         }
1176
1177         if (bc->uulen) {
1178                 int  protocol=4;
1179                 enc_ie_useruser(&release->USER_USER, msg, protocol, bc->uu, bc->uulen, nt,bc);
1180                 cb_log(1, bc->port, "ENCODING USERUSERINFO:%s\n", bc->uu);
1181         }
1182
1183 #ifdef DEBUG
1184         printf("Building RELEASE Msg\n");
1185 #endif
1186         return msg;
1187 }
1188
1189 static void parse_release_complete (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
1190 {
1191         int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
1192         RELEASE_COMPLETE_t *release_complete = (RELEASE_COMPLETE_t *) (msg->data + HEADER_LEN);
1193         int location;
1194         int cause;
1195         iframe_t *frm = (iframe_t*) msg->data;
1196
1197         struct misdn_stack *stack=get_stack_by_bc(bc);
1198         mISDNuser_head_t *hh;
1199         hh=(mISDNuser_head_t*)msg->data;
1200
1201         /*hh=(mISDN_head_t*)msg->data;
1202         mISDN_head_t *hh;*/
1203
1204         if (nt) {
1205                 if (hh->prim == (CC_RELEASE_COMPLETE|CONFIRM)) {
1206                         cb_log(0, stack->port, "CC_RELEASE_COMPLETE|CONFIRM [NT] \n");
1207                         return;
1208                 }
1209         } else {
1210                 if (frm->prim == (CC_RELEASE_COMPLETE|CONFIRM)) {
1211                         cb_log(0, stack->port, "CC_RELEASE_COMPLETE|CONFIRM [TE] \n");
1212                         return;
1213                 }
1214         }
1215         dec_ie_cause(release_complete->CAUSE, (Q931_info_t *)(release_complete), &location, &cause, nt,bc);
1216         if (cause>0) bc->cause=cause;
1217
1218         dec_ie_facility(release_complete->FACILITY, (Q931_info_t *) release_complete, &bc->fac_in, nt, bc);
1219
1220 #ifdef DEBUG
1221         printf("Parsing RELEASE_COMPLETE Msg\n");
1222 #endif
1223 }
1224
1225 static msg_t *build_release_complete (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
1226 {
1227         int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
1228         RELEASE_COMPLETE_t *release_complete;
1229         msg_t *msg =(msg_t*)create_l3msg(CC_RELEASE_COMPLETE | REQUEST, MT_RELEASE_COMPLETE,  bc?bc->l3_id:-1, sizeof(RELEASE_COMPLETE_t) ,nt);
1230
1231         release_complete=(RELEASE_COMPLETE_t*)((msg->data+HEADER_LEN));
1232
1233         enc_ie_cause(&release_complete->CAUSE, msg, nt?1:0, bc->out_cause, nt,bc);
1234
1235         if (bc->fac_out.Function != Fac_None) {
1236                 enc_ie_facility(&release_complete->FACILITY, msg, &bc->fac_out, nt);
1237         }
1238
1239         if (bc->uulen) {
1240                 int  protocol=4;
1241                 enc_ie_useruser(&release_complete->USER_USER, msg, protocol, bc->uu, bc->uulen, nt,bc);
1242                 cb_log(1, bc->port, "ENCODING USERUSERINFO:%s\n", bc->uu);
1243         }
1244
1245 #ifdef DEBUG
1246         printf("Building RELEASE_COMPLETE Msg\n");
1247 #endif
1248         return msg;
1249 }
1250
1251 static void parse_facility (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
1252 {
1253         int HEADER_LEN = nt ? mISDNUSER_HEAD_SIZE : mISDN_HEADER_LEN;
1254         FACILITY_t *facility = (FACILITY_t*)(msg->data+HEADER_LEN);
1255         Q931_info_t *qi = (Q931_info_t*)(msg->data+HEADER_LEN);
1256         unsigned char *p = NULL;
1257 #if defined(AST_MISDN_ENHANCEMENTS)
1258         int description_code;
1259         int type;
1260         int plan;
1261         int present;
1262         char number[sizeof(bc->redirecting.to.number)];
1263 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1264
1265 #ifdef DEBUG
1266         printf("Parsing FACILITY Msg\n");
1267 #endif
1268
1269         bc->fac_in.Function = Fac_None;
1270
1271         if (!bc->nt) {
1272                 if (qi->QI_ELEMENT(facility))
1273                         p = (unsigned char *)qi + sizeof(Q931_info_t) + qi->QI_ELEMENT(facility) + 1;
1274         } else {
1275                 p = facility->FACILITY;
1276         }
1277         if (!p)
1278                 return;
1279
1280         if (decodeFac(p, &bc->fac_in)) {
1281                 cb_log(3, bc->port, "Decoding facility ie failed! Unrecognized facility message?\n");
1282         }
1283
1284 #if defined(AST_MISDN_ENHANCEMENTS)
1285         dec_ie_notify(facility->NOTIFY, qi, &description_code, nt, bc);
1286         if (description_code < 0) {
1287                 bc->notify_description_code = mISDN_NOTIFY_CODE_INVALID;
1288         } else {
1289                 bc->notify_description_code = description_code;
1290         }
1291
1292         dec_ie_redir_dn(facility->REDIR_DN, qi, &type, &plan, &present, number, sizeof(number), nt, bc);
1293         if (0 <= type) {
1294                 bc->redirecting.to_changed = 1;
1295
1296                 bc->redirecting.to.number_type = type;
1297                 bc->redirecting.to.number_plan = plan;
1298                 switch (present) {
1299                 default:
1300                 case 0:
1301                         bc->redirecting.to.presentation = 0;    /* presentation allowed */
1302                         break;
1303                 case 1:
1304                         bc->redirecting.to.presentation = 1;    /* presentation restricted */
1305                         break;
1306                 case 2:
1307                         bc->redirecting.to.presentation = 2;    /* Number not available */
1308                         break;
1309                 }
1310                 bc->redirecting.to.screening = 0;       /* Unscreened */
1311                 strcpy(bc->redirecting.to.number, number);
1312         }
1313 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1314 }
1315
1316 static msg_t *build_facility (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
1317 {
1318         int len;
1319         int HEADER_LEN;
1320         unsigned char *ie_fac;
1321         unsigned char fac_tmp[256];
1322         msg_t *msg;
1323         FACILITY_t *facility;
1324         Q931_info_t *qi;
1325
1326 #ifdef DEBUG
1327         printf("Building FACILITY Msg\n");
1328 #endif
1329
1330         len = encodeFac(fac_tmp, &(bc->fac_out));
1331         if (len <= 0) {
1332                 /*
1333                  * mISDN does not know how to build the requested facility structure
1334                  * Clear facility information
1335                  */
1336                 bc->fac_out.Function = Fac_None;
1337
1338 #if defined(AST_MISDN_ENHANCEMENTS)
1339                 /* Clear other one shot information. */
1340                 bc->notify_description_code = mISDN_NOTIFY_CODE_INVALID;
1341                 bc->redirecting.to_changed = 0;
1342 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1343                 return NULL;
1344         }
1345
1346         msg = (msg_t *) create_l3msg(CC_FACILITY | REQUEST, MT_FACILITY, bc ? bc->l3_id : -1, sizeof(FACILITY_t), nt);
1347         HEADER_LEN = nt ? mISDNUSER_HEAD_SIZE : mISDN_HEADER_LEN;
1348         facility = (FACILITY_t *) (msg->data + HEADER_LEN);
1349
1350         ie_fac = msg_put(msg, len);
1351         if (bc->nt) {
1352                 facility->FACILITY = ie_fac + 1;
1353         } else {
1354                 qi = (Q931_info_t *)(msg->data + mISDN_HEADER_LEN);
1355                 qi->QI_ELEMENT(facility) = ie_fac - (unsigned char *)qi - sizeof(Q931_info_t);
1356         }
1357
1358         memcpy(ie_fac, fac_tmp, len);
1359
1360         /* Clear facility information */
1361         bc->fac_out.Function = Fac_None;
1362
1363         if (*bc->display) {
1364 #ifdef DEBUG
1365                 printf("Sending %s as Display\n", bc->display);
1366 #endif
1367                 enc_ie_display(&facility->DISPLAY, msg, bc->display, nt,bc);
1368         }
1369
1370 #if defined(AST_MISDN_ENHANCEMENTS)
1371         if (bc->notify_description_code != mISDN_NOTIFY_CODE_INVALID) {
1372                 enc_ie_notify(&facility->NOTIFY, msg, bc->notify_description_code, nt, bc);
1373                 bc->notify_description_code = mISDN_NOTIFY_CODE_INVALID;
1374         }
1375
1376         if (bc->redirecting.to_changed) {
1377                 bc->redirecting.to_changed = 0;
1378                 switch (bc->outgoing_colp) {
1379                 case 0:/* pass */
1380                 case 1:/* restricted */
1381                         enc_ie_redir_dn(&facility->REDIR_DN, msg, bc->redirecting.to.number_type,
1382                                 bc->redirecting.to.number_plan, bc->redirecting.to.presentation,
1383                                 bc->redirecting.to.number, nt, bc);
1384                         break;
1385                 default:
1386                         break;
1387                 }
1388         }
1389 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1390
1391         return msg;
1392 }
1393
1394 #if defined(AST_MISDN_ENHANCEMENTS)
1395 /*!
1396  * \internal
1397  * \brief Parse a received REGISTER message
1398  *
1399  * \param msgs Search table entry that called us.
1400  * \param msg Received message contents
1401  * \param bc Associated B channel
1402  * \param nt TRUE if in NT mode.
1403  *
1404  * \return Nothing
1405  */
1406 static void parse_register(struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
1407 {
1408         int HEADER_LEN;
1409         REGISTER_t *reg;
1410
1411         HEADER_LEN = nt ? mISDNUSER_HEAD_SIZE : mISDN_HEADER_LEN;
1412         reg = (REGISTER_t *) (msg->data + HEADER_LEN);
1413
1414         /*
1415          * A facility ie is optional.
1416          * The peer may just be establishing a connection to send
1417          * messages later.
1418          */
1419         dec_ie_facility(reg->FACILITY, (Q931_info_t *) reg, &bc->fac_in, nt, bc);
1420 }
1421 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1422
1423 #if defined(AST_MISDN_ENHANCEMENTS)
1424 /*!
1425  * \internal
1426  * \brief Construct a REGISTER message
1427  *
1428  * \param msgs Search table entry that called us.
1429  * \param bc Associated B channel
1430  * \param nt TRUE if in NT mode.
1431  *
1432  * \return Allocated built message
1433  */
1434 static msg_t *build_register(struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
1435 {
1436         int HEADER_LEN;
1437         REGISTER_t *reg;
1438         msg_t *msg;
1439
1440         msg = (msg_t *) create_l3msg(CC_REGISTER | REQUEST, MT_REGISTER,  bc ? bc->l3_id : -1, sizeof(REGISTER_t), nt);
1441         HEADER_LEN = nt ? mISDNUSER_HEAD_SIZE : mISDN_HEADER_LEN;
1442         reg = (REGISTER_t *) (msg->data + HEADER_LEN);
1443
1444         if (bc->fac_out.Function != Fac_None) {
1445                 enc_ie_facility(&reg->FACILITY, msg, &bc->fac_out, nt);
1446         }
1447
1448         return msg;
1449 }
1450 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1451
1452 static void parse_notify (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
1453 {
1454         int HEADER_LEN = nt ? mISDNUSER_HEAD_SIZE : mISDN_HEADER_LEN;
1455         NOTIFY_t *notify = (NOTIFY_t *) (msg->data + HEADER_LEN);
1456         int description_code;
1457         int type;
1458         int plan;
1459         int present;
1460         char number[sizeof(bc->redirecting.to.number)];
1461
1462 #ifdef DEBUG
1463         printf("Parsing NOTIFY Msg\n");
1464 #endif
1465
1466         dec_ie_notify(notify->NOTIFY, (Q931_info_t *) notify, &description_code, nt, bc);
1467         if (description_code < 0) {
1468                 bc->notify_description_code = mISDN_NOTIFY_CODE_INVALID;
1469         } else {
1470                 bc->notify_description_code = description_code;
1471         }
1472
1473         dec_ie_redir_dn(notify->REDIR_DN, (Q931_info_t *) notify, &type, &plan, &present, number, sizeof(number), nt, bc);
1474         if (0 <= type) {
1475                 bc->redirecting.to_changed = 1;
1476
1477                 bc->redirecting.to.number_type = type;
1478                 bc->redirecting.to.number_plan = plan;
1479                 switch (present) {
1480                 default:
1481                 case 0:
1482                         bc->redirecting.to.presentation = 0;    /* presentation allowed */
1483                         break;
1484                 case 1:
1485                         bc->redirecting.to.presentation = 1;    /* presentation restricted */
1486                         break;
1487                 case 2:
1488                         bc->redirecting.to.presentation = 2;    /* Number not available */
1489                         break;
1490                 }
1491                 bc->redirecting.to.screening = 0;       /* Unscreened */
1492                 strcpy(bc->redirecting.to.number, number);
1493         }
1494 }
1495
1496 static msg_t *build_notify (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
1497 {
1498         int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
1499         NOTIFY_t *notify;
1500         msg_t *msg =(msg_t*)create_l3msg(CC_NOTIFY | REQUEST, MT_NOTIFY,  bc?bc->l3_id:-1, sizeof(NOTIFY_t) ,nt);
1501
1502 #ifdef DEBUG
1503         printf("Building NOTIFY Msg\n");
1504 #endif
1505
1506         notify = (NOTIFY_t *) (msg->data + HEADER_LEN);
1507
1508         enc_ie_notify(&notify->NOTIFY, msg, bc->notify_description_code, nt, bc);
1509         bc->notify_description_code = mISDN_NOTIFY_CODE_INVALID;
1510
1511         if (bc->redirecting.to_changed) {
1512                 bc->redirecting.to_changed = 0;
1513                 switch (bc->outgoing_colp) {
1514                 case 0:/* pass */
1515                 case 1:/* restricted */
1516                         enc_ie_redir_dn(&notify->REDIR_DN, msg, bc->redirecting.to.number_type,
1517                                 bc->redirecting.to.number_plan, bc->redirecting.to.presentation,
1518                                 bc->redirecting.to.number, nt, bc);
1519                         break;
1520                 default:
1521                         break;
1522                 }
1523         }
1524         return msg;
1525 }
1526
1527 static void parse_status_enquiry (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
1528 {
1529 #ifdef DEBUG
1530         printf("Parsing STATUS_ENQUIRY Msg\n");
1531 #endif
1532 }
1533
1534 static msg_t *build_status_enquiry (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
1535 {
1536         msg_t *msg =(msg_t*)create_l3msg(CC_STATUS_ENQUIRY | REQUEST, MT_STATUS_ENQUIRY,  bc?bc->l3_id:-1, sizeof(STATUS_ENQUIRY_t) ,nt);
1537
1538 #ifdef DEBUG
1539         printf("Building STATUS_ENQUIRY Msg\n");
1540 #endif
1541         return msg;
1542 }
1543
1544 static void parse_information (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
1545 {
1546         int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
1547         INFORMATION_t *information = (INFORMATION_t *) (msg->data + HEADER_LEN);
1548         int type, plan;
1549
1550         dec_ie_called_pn(information->CALLED_PN, (Q931_info_t *) information, &type, &plan, bc->info_dad, sizeof(bc->info_dad), nt, bc);
1551         dec_ie_keypad(information->KEYPAD, (Q931_info_t *) information, bc->keypad, sizeof(bc->keypad), nt, bc);
1552
1553 #ifdef DEBUG
1554         printf("Parsing INFORMATION Msg\n");
1555 #endif
1556 }
1557
1558 static msg_t *build_information (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
1559 {
1560         int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
1561         INFORMATION_t *information;
1562         msg_t *msg =(msg_t*)create_l3msg(CC_INFORMATION | REQUEST, MT_INFORMATION,  bc?bc->l3_id:-1, sizeof(INFORMATION_t) ,nt);
1563
1564         information=(INFORMATION_t*)((msg->data+HEADER_LEN));
1565
1566         enc_ie_called_pn(&information->CALLED_PN, msg, 0, 1, bc->info_dad, nt,bc);
1567
1568         {
1569                 if (*bc->display) {
1570 #ifdef DEBUG
1571                         printf("Sending %s as Display\n", bc->display);
1572 #endif
1573                         enc_ie_display(&information->DISPLAY, msg, bc->display, nt,bc);
1574                 }
1575         }
1576
1577 #ifdef DEBUG
1578         printf("Building INFORMATION Msg\n");
1579 #endif
1580         return msg;
1581 }
1582
1583 static void parse_status (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
1584 {
1585         int HEADER_LEN = nt?mISDNUSER_HEAD_SIZE:mISDN_HEADER_LEN;
1586         STATUS_t *status = (STATUS_t *) (msg->data + HEADER_LEN);
1587         int location;
1588         int cause;
1589
1590         dec_ie_cause(status->CAUSE, (Q931_info_t *)(status), &location, &cause, nt,bc);
1591         if (cause>0) bc->cause=cause;
1592
1593 #ifdef DEBUG
1594         printf("Parsing STATUS Msg\n");
1595 #endif
1596 }
1597
1598 static msg_t *build_status (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
1599 {
1600         msg_t *msg =(msg_t*)create_l3msg(CC_STATUS | REQUEST, MT_STATUS,  bc?bc->l3_id:-1, sizeof(STATUS_t) ,nt);
1601
1602 #ifdef DEBUG
1603         printf("Building STATUS Msg\n");
1604 #endif
1605         return msg;
1606 }
1607
1608 static void parse_timeout (struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
1609 {
1610 #ifdef DEBUG
1611         printf("Parsing STATUS Msg\n");
1612 #endif
1613 }
1614
1615 static msg_t *build_timeout (struct isdn_msg msgs[], struct misdn_bchannel *bc, int nt)
1616 {
1617         msg_t *msg =(msg_t*)create_l3msg(CC_STATUS | REQUEST, MT_STATUS,  bc?bc->l3_id:-1, sizeof(STATUS_t) ,nt);
1618
1619 #ifdef DEBUG
1620         printf("Building STATUS Msg\n");
1621 #endif
1622         return msg;
1623 }
1624
1625
1626 /************************************/
1627
1628
1629
1630
1631 /** Msg Array **/
1632
1633 struct isdn_msg msgs_g[] = {
1634 /* *INDENT-OFF* */
1635         /* misdn_msg,               event,                      msg_parser,                 msg_builder,                info */
1636         { CC_PROCEEDING,            EVENT_PROCEEDING,           parse_proceeding,           build_proceeding,           "PROCEEDING" },
1637         { CC_ALERTING,              EVENT_ALERTING,             parse_alerting,             build_alerting,             "ALERTING" },
1638         { CC_PROGRESS,              EVENT_PROGRESS,             parse_progress,             build_progress,             "PROGRESS" },
1639         { CC_SETUP,                 EVENT_SETUP,                parse_setup,                build_setup,                "SETUP" },
1640 #if defined(AST_MISDN_ENHANCEMENTS)
1641         { CC_REGISTER,              EVENT_REGISTER,             parse_register,             build_register,             "REGISTER" },
1642 #endif  /* defined(AST_MISDN_ENHANCEMENTS) */
1643         { CC_CONNECT,               EVENT_CONNECT,              parse_connect,              build_connect,              "CONNECT" },
1644         { CC_SETUP_ACKNOWLEDGE,     EVENT_SETUP_ACKNOWLEDGE,    parse_setup_acknowledge,    build_setup_acknowledge,    "SETUP_ACKNOWLEDGE" },
1645         { CC_CONNECT_ACKNOWLEDGE,   EVENT_CONNECT_ACKNOWLEDGE,  parse_connect_acknowledge,  build_connect_acknowledge,  "CONNECT_ACKNOWLEDGE " },
1646         { CC_USER_INFORMATION,      EVENT_USER_INFORMATION,     parse_user_information,     build_user_information,     "USER_INFORMATION" },
1647         { CC_SUSPEND_REJECT,        EVENT_SUSPEND_REJECT,       parse_suspend_reject,       build_suspend_reject,       "SUSPEND_REJECT" },
1648         { CC_RESUME_REJECT,         EVENT_RESUME_REJECT,        parse_resume_reject,        build_resume_reject,        "RESUME_REJECT" },
1649         { CC_HOLD,                  EVENT_HOLD,                 parse_hold,                 build_hold,                 "HOLD" },
1650         { CC_SUSPEND,               EVENT_SUSPEND,              parse_suspend,              build_suspend,              "SUSPEND" },
1651         { CC_RESUME,                EVENT_RESUME,               parse_resume,               build_resume,               "RESUME" },
1652         { CC_HOLD_ACKNOWLEDGE,      EVENT_HOLD_ACKNOWLEDGE,     parse_hold_acknowledge,     build_hold_acknowledge,     "HOLD_ACKNOWLEDGE" },
1653         { CC_SUSPEND_ACKNOWLEDGE,   EVENT_SUSPEND_ACKNOWLEDGE,  parse_suspend_acknowledge,  build_suspend_acknowledge,  "SUSPEND_ACKNOWLEDGE" },
1654         { CC_RESUME_ACKNOWLEDGE,    EVENT_RESUME_ACKNOWLEDGE,   parse_resume_acknowledge,   build_resume_acknowledge,   "RESUME_ACKNOWLEDGE" },
1655         { CC_HOLD_REJECT,           EVENT_HOLD_REJECT,          parse_hold_reject,          build_hold_reject,          "HOLD_REJECT" },
1656         { CC_RETRIEVE,              EVENT_RETRIEVE,             parse_retrieve,             build_retrieve,             "RETRIEVE" },
1657         { CC_RETRIEVE_ACKNOWLEDGE,  EVENT_RETRIEVE_ACKNOWLEDGE, parse_retrieve_acknowledge, build_retrieve_acknowledge, "RETRIEVE_ACKNOWLEDGE" },
1658         { CC_RETRIEVE_REJECT,       EVENT_RETRIEVE_REJECT,      parse_retrieve_reject,      build_retrieve_reject,      "RETRIEVE_REJECT" },
1659         { CC_DISCONNECT,            EVENT_DISCONNECT,           parse_disconnect,           build_disconnect,           "DISCONNECT" },
1660         { CC_RESTART,               EVENT_RESTART,              parse_restart,              build_restart,              "RESTART" },
1661         { CC_RELEASE,               EVENT_RELEASE,              parse_release,              build_release,              "RELEASE" },
1662         { CC_RELEASE_COMPLETE,      EVENT_RELEASE_COMPLETE,     parse_release_complete,     build_release_complete,     "RELEASE_COMPLETE" },
1663         { CC_FACILITY,              EVENT_FACILITY,             parse_facility,             build_facility,             "FACILITY" },
1664         { CC_NOTIFY,                EVENT_NOTIFY,               parse_notify,               build_notify,               "NOTIFY" },
1665         { CC_STATUS_ENQUIRY,        EVENT_STATUS_ENQUIRY,       parse_status_enquiry,       build_status_enquiry,       "STATUS_ENQUIRY" },
1666         { CC_INFORMATION,           EVENT_INFORMATION,          parse_information,          build_information,          "INFORMATION" },
1667         { CC_STATUS,                EVENT_STATUS,               parse_status,               build_status,               "STATUS" },
1668         { CC_TIMEOUT,               EVENT_TIMEOUT,              parse_timeout,              build_timeout,              "TIMEOUT" },
1669         { 0, 0, NULL, NULL, NULL }
1670 /* *INDENT-ON* */
1671 };
1672
1673 #define msgs_max (sizeof(msgs_g)/sizeof(struct isdn_msg))
1674
1675 /** INTERFACE FCTS ***/
1676 int isdn_msg_get_index(struct isdn_msg msgs[], msg_t *msg, int nt)
1677 {
1678         int i;
1679
1680         if (nt){
1681                 mISDNuser_head_t *hh = (mISDNuser_head_t*)msg->data;
1682
1683                 for (i=0; i< msgs_max -1; i++) {
1684                         if ( (hh->prim&COMMAND_MASK)==(msgs[i].misdn_msg&COMMAND_MASK)) return i;
1685                 }
1686
1687         } else {
1688                 iframe_t *frm = (iframe_t*)msg->data;
1689
1690                 for (i=0; i< msgs_max -1; i++)
1691                         if ( (frm->prim&COMMAND_MASK)==(msgs[i].misdn_msg&COMMAND_MASK)) return i;
1692         }
1693
1694         return -1;
1695 }
1696
1697 int isdn_msg_get_index_by_event(struct isdn_msg msgs[], enum event_e event, int nt)
1698 {
1699         int i;
1700         for (i=0; i< msgs_max; i++)
1701                 if ( event == msgs[i].event) return i;
1702
1703         cb_log(10,0, "get_index: event not found!\n");
1704
1705         return -1;
1706 }
1707
1708 enum event_e isdn_msg_get_event(struct isdn_msg msgs[], msg_t *msg, int nt)
1709 {
1710         int i=isdn_msg_get_index(msgs, msg, nt);
1711         if(i>=0) return msgs[i].event;
1712         return EVENT_UNKNOWN;
1713 }
1714
1715 char * isdn_msg_get_info(struct isdn_msg msgs[], msg_t *msg, int nt)
1716 {
1717         int i=isdn_msg_get_index(msgs, msg, nt);
1718         if(i>=0) return msgs[i].info;
1719         return NULL;
1720 }
1721
1722
1723 char EVENT_CLEAN_INFO[] = "CLEAN_UP";
1724 char EVENT_DTMF_TONE_INFO[] = "DTMF_TONE";
1725 char EVENT_NEW_L3ID_INFO[] = "NEW_L3ID";
1726 char EVENT_NEW_BC_INFO[] = "NEW_BC";
1727 char EVENT_PORT_ALARM_INFO[] = "ALARM";
1728 char EVENT_NEW_CHANNEL_INFO[] = "NEW_CHANNEL";
1729 char EVENT_BCHAN_DATA_INFO[] = "BCHAN_DATA";
1730 char EVENT_BCHAN_ACTIVATED_INFO[] = "BCHAN_ACTIVATED";
1731 char EVENT_TONE_GENERATE_INFO[] = "TONE_GENERATE";
1732 char EVENT_BCHAN_ERROR_INFO[] = "BCHAN_ERROR";
1733
1734 char * isdn_get_info(struct isdn_msg msgs[], enum event_e event, int nt)
1735 {
1736         int i=isdn_msg_get_index_by_event(msgs, event, nt);
1737
1738         if(i>=0) return msgs[i].info;
1739
1740         if (event == EVENT_CLEANUP) return EVENT_CLEAN_INFO;
1741         if (event == EVENT_DTMF_TONE) return EVENT_DTMF_TONE_INFO;
1742         if (event == EVENT_NEW_L3ID) return EVENT_NEW_L3ID_INFO;
1743         if (event == EVENT_NEW_BC) return EVENT_NEW_BC_INFO;
1744         if (event == EVENT_NEW_CHANNEL) return EVENT_NEW_CHANNEL_INFO;
1745         if (event == EVENT_BCHAN_DATA) return EVENT_BCHAN_DATA_INFO;
1746         if (event == EVENT_BCHAN_ACTIVATED) return EVENT_BCHAN_ACTIVATED_INFO;
1747         if (event == EVENT_TONE_GENERATE) return EVENT_TONE_GENERATE_INFO;
1748         if (event == EVENT_PORT_ALARM) return EVENT_PORT_ALARM_INFO;
1749         if (event == EVENT_BCHAN_ERROR) return EVENT_BCHAN_ERROR_INFO;
1750
1751         return NULL;
1752 }
1753
1754 int isdn_msg_parse_event(struct isdn_msg msgs[], msg_t *msg, struct misdn_bchannel *bc, int nt)
1755 {
1756         int i=isdn_msg_get_index(msgs, msg, nt);
1757         if(i<0) return -1;
1758
1759         msgs[i].msg_parser(msgs, msg, bc, nt);
1760         return 0;
1761 }
1762
1763 msg_t * isdn_msg_build_event(struct isdn_msg msgs[], struct misdn_bchannel *bc, enum event_e event, int nt)
1764 {
1765         int i=isdn_msg_get_index_by_event(msgs, event, nt);
1766         if(i<0) return NULL;
1767
1768         return  msgs[i].msg_builder(msgs, bc, nt);
1769 }