error inside information elements are now reported inside trace and main log,
[lcr.git] / mISDN.cpp
1 /*****************************************************************************\
2 **                                                                           **
3 ** Linux Call Router                                                         **
4 **                                                                           **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg                                              **
7 **                                                                           **
8 ** mISDN port abstraction for dss1 and sip                                   **
9 **                                                                           **
10 \*****************************************************************************/ 
11
12 #include "main.h"
13 #include <poll.h>
14 #include <errno.h>
15 #include <sys/ioctl.h>
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <fcntl.h>
19 #ifdef SOCKET_MISDN
20 #include <netinet/udp.h>
21 #include <netinet/in.h>
22 #include <netdb.h>
23 #include <sys/socket.h>
24 #include <pthread.h>
25 #include <linux/mISDNif.h>
26 #include <q931.h>
27 #include <mlayer3.h>
28 #else
29 extern "C" {
30 #include <mISDNuser/net_l2.h>
31 }
32 #endif
33
34 #ifndef CMX_TXDATA_ON
35 #define OLD_MISDN
36 #endif
37 #ifndef CMX_TXDATA_OFF
38 #define OLD_MISDN
39 #endif
40 #ifndef CMX_DELAY
41 #define OLD_MISDN
42 #endif
43 #ifndef PIPELINE_CFG
44 #define OLD_MISDN
45 #endif
46 #ifndef CMX_TX_DATA
47 #define OLD_MISDN
48 #endif
49
50 #ifdef OLD_MISDN
51 #warning
52 #warning *********************************************************
53 #warning *
54 #warning * It seems that you use an older version of mISDN.
55 #warning * Features like voice recording or echo will not work.
56 #warning * Also it causes problems with loading modules and may
57 #warning * not work at all.
58 #warning *
59 #warning * Please upgrade to newer version. A working version can
60 #warning * be found at www.linux-call-router.de.
61 #warning *
62 #warning * Do not use the mISDN_1_1 branch, it does not have all
63 #warning * the features that are required. Use the master branch
64 #warning * instead.
65 #warning *
66 #warning *********************************************************
67 #warning
68 #error
69 #endif
70
71 #ifndef ISDN_PID_L4_B_USER
72 #define ISDN_PID_L4_B_USER 0x440000ff
73 #endif
74
75 /* list of mISDN ports */
76 struct mISDNport *mISDNport_first;
77
78 /* noise randomizer */
79 unsigned char mISDN_rand[256];
80 int mISDN_rand_count = 0;
81
82 #ifdef MISDN_SOCKET
83 int mISDNsocket = -1;
84
85 int mISDN_initialize(void)
86 {
87         /* try to open raw socket to check kernel */
88         mISDNsocket = socket(PF_ISDN, SOCK_RAW, ISDN_P_BASE);
89         if (mISDNsocket < 0)
90         {
91                 fprintf(stderr, "Cannot open mISDN due to %s. (Does your Kernel support socket based mISDN?)\n", strerror(errno));
92                 return(-1);
93         }
94
95         /* initialize stuff of the NT lib */
96         if (options.deb & DEBUG_STACK)
97         {
98                 global_debug = 0xffffffff & ~DBGM_MSG;
99 //              global_debug = DBGM_L3DATA;
100         } else
101                 global_debug = DBGM_MAN;
102         SPRINT(debug_log, "%s/debug.log", INSTALL_DATA);
103         if (options.deb & DEBUG_LOG)
104                 mISDN_debug_init(global_debug, debug_log, debug_log, debug_log);
105         else
106                 mISDN_debug_init(global_debug, NULL, NULL, NULL);
107
108         /* init mlayer3 */
109         init_layer3(4); // buffer of 4
110
111         return(0);
112 }
113
114 void mISDN_deinitialize(void)
115 {
116         cleanup_layer3();
117
118         mISDN_debug_close();
119
120         if (mISDNsocket > -1)
121                 close(mISDNsocket);
122 }
123 #else
124 int entity = 0; /* used for udevice */
125 int mISDNdevice = -1; /* the device handler and port list */
126
127 int mISDN_initialize(void)
128 {
129         char debug_log[128];
130         unsigned char buff[1025];
131         iframe_t *frm = (iframe_t *)buff;
132         int ret;
133
134         /* initialize stuff of the NT lib */
135         if (options.deb & DEBUG_STACK)
136         {
137                 global_debug = 0xffffffff & ~DBGM_MSG;
138 //              global_debug = DBGM_L3DATA;
139         } else
140                 global_debug = DBGM_MAN;
141         SPRINT(debug_log, "%s/debug.log", INSTALL_DATA);
142         if (options.deb & DEBUG_LOG)
143                 debug_init(global_debug, debug_log, debug_log, debug_log);
144         else
145                 debug_init(global_debug, NULL, NULL, NULL);
146         msg_init();
147
148         /* open mISDNdevice if not already open */
149         if (mISDNdevice < 0)
150         {
151                 ret = mISDN_open();
152                 if (ret < 0)
153                 {
154                         fprintf(stderr, "cannot open mISDN device ret=%d errno=%d (%s) Check for mISDN modules!\nAlso did you create \"/dev/mISDN\"? Do: \"mknod /dev/mISDN c 46 0\"\n", ret, errno, strerror(errno));
155                         return(-1);
156                 }
157                 mISDNdevice = ret;
158                 PDEBUG(DEBUG_ISDN, "mISDN device opened.\n");
159
160                 /* create entity for layer 3 TE-mode */
161                 mISDN_write_frame(mISDNdevice, buff, 0, MGR_NEWENTITY | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
162                 ret = mISDN_read_frame(mISDNdevice, frm, sizeof(iframe_t), 0, MGR_NEWENTITY | CONFIRM, TIMEOUT_1SEC);
163                 if (ret < (int)mISDN_HEADER_LEN)
164                 {
165                         noentity:
166                         FATAL("Cannot request MGR_NEWENTITY from mISDN. Exitting due to software bug.");
167                 }
168                 entity = frm->dinfo & 0xffff;
169                 if (!entity)
170                         goto noentity;
171                 PDEBUG(DEBUG_ISDN, "our entity for l3-processes is %d.\n", entity);
172         }
173         return(0);
174 }
175
176 void mISDN_deinitialize(void)
177 {
178         unsigned char buff[1025];
179
180         debug_close();
181
182         if (mISDNdevice >= 0)
183         {
184                 /* free entity */
185                 mISDN_write_frame(mISDNdevice, buff, 0, MGR_DELENTITY | REQUEST, entity, 0, NULL, TIMEOUT_1SEC);
186                 /* close device */
187                 mISDN_close(mISDNdevice);
188                 mISDNdevice = -1;
189                 PDEBUG(DEBUG_ISDN, "mISDN device closed.\n");
190         }
191 }
192 #endif
193
194 /*
195  * constructor
196  */
197 PmISDN::PmISDN(int type, mISDNport *mISDNport, char *portname, struct port_settings *settings, int channel, int exclusive) : Port(type, portname, settings)
198 {
199         p_m_mISDNport = mISDNport;
200         p_m_portnum = mISDNport->portnum;
201         p_m_b_index = -1;
202         p_m_b_channel = 0;
203         p_m_b_exclusive = 0;
204         p_m_b_reserve = 0;
205         p_m_delete = 0;
206         p_m_hold = 0;
207         p_m_tx_gain = mISDNport->ifport->interface->tx_gain;
208         p_m_rx_gain = mISDNport->ifport->interface->rx_gain;
209         p_m_conf = 0;
210         p_m_txdata = 0;
211         p_m_delay = 0;
212         p_m_echo = 0;
213         p_m_tone = 0;
214         p_m_rxoff = 0;
215         p_m_joindata = 0;
216         p_m_dtmf = !mISDNport->ifport->nodtmf;
217         p_m_timeout = 0;
218         p_m_timer = 0;
219         p_m_remote_ref = 0; /* channel shall be exported to given remote */
220         p_m_remote_id = 0; /* channel shall be exported to given remote */
221         SCPY(p_m_pipeline, mISDNport->ifport->interface->pipeline);
222         
223         /* audio */
224         p_m_load = 0;
225         p_m_last_tv_sec = 0;
226
227         /* crypt */
228         p_m_crypt = 0;
229         p_m_crypt_listen = 0;
230         p_m_crypt_msg_loops = 0;
231         p_m_crypt_msg_loops = 0;
232         p_m_crypt_msg_len = 0;
233         p_m_crypt_msg[0] = '\0';
234         p_m_crypt_msg_current = 0;
235         p_m_crypt_key_len = 0;
236         p_m_crypt_listen = 0;
237         p_m_crypt_listen_state = 0;
238         p_m_crypt_listen_len = 0;
239         p_m_crypt_listen_msg[0] = '\0';
240         p_m_crypt_listen_crc = 0;
241         if (mISDNport->ifport->interface->bf_len >= 4 && mISDNport->ifport->interface->bf_len <= 56)
242         {
243                 memcpy(p_m_crypt_key, mISDNport->ifport->interface->bf_key, p_m_crypt_key_len);
244                 p_m_crypt_key_len = mISDNport->ifport->interface->bf_len;
245                 p_m_crypt = 1;
246         }
247
248         /* if any channel requested by constructor */
249         if (channel == CHANNEL_ANY)
250         {
251                 /* reserve channel */
252                 p_m_b_reserve = 1;
253                 mISDNport->b_reserved++;
254         }
255
256         /* reserve channel */
257         if (channel > 0) // only if constructor was called with a channel resevation
258                 seize_bchannel(channel, exclusive);
259
260         /* we increase the number of objects: */
261         mISDNport->use++;
262         PDEBUG(DEBUG_ISDN, "Created new mISDNPort(%s). Currently %d objects use, port #%d\n", portname, mISDNport->use, p_m_portnum);
263 }
264
265
266 /*
267  * destructor
268  */
269 PmISDN::~PmISDN()
270 {
271         struct message *message;
272
273         /* remove bchannel relation */
274         drop_bchannel();
275
276         /* release epoint */
277         while (p_epointlist)
278         {
279                 PDEBUG(DEBUG_ISDN, "destroy mISDNPort(%s). endpoint still exists, releaseing.\n", p_name);
280                 message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
281                 message->param.disconnectinfo.cause = 16;
282                 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
283                 message_put(message);
284                 /* remove from list */
285                 free_epointlist(p_epointlist);
286         }
287
288         /* we decrease the number of objects: */
289         p_m_mISDNport->use--;
290         PDEBUG(DEBUG_ISDN, "destroyed mISDNPort(%s). Currently %d objects\n", p_name, p_m_mISDNport->use);
291 }
292
293
294 /*
295  * trace
296  */
297 void chan_trace_header(struct mISDNport *mISDNport, class PmISDN *port, char *msgtext, int direction)
298 {
299         /* init trace with given values */
300         start_trace(mISDNport?mISDNport->portnum:0,
301                     (mISDNport)?((mISDNport->ifport)?mISDNport->ifport->interface:NULL):NULL,
302                     port?numberrize_callerinfo(port->p_callerinfo.id, port->p_callerinfo.ntype):NULL,
303                     port?port->p_dialinginfo.id:NULL,
304                     direction,
305                     CATEGORY_CH,
306                     port?port->p_serial:0,
307                     msgtext);
308 }
309
310
311 /*
312  * layer trace header
313  */
314 static struct isdn_message {
315         char *name;
316         unsigned long value;
317 } isdn_message[] = {
318         {"TIMEOUT", CC_TIMEOUT},
319         {"SETUP", CC_SETUP},
320         {"SETUP_ACK", CC_SETUP_ACKNOWLEDGE},
321         {"PROCEEDING", CC_PROCEEDING},
322         {"ALERTING", CC_ALERTING},
323         {"CONNECT", CC_CONNECT},
324         {"CONNECT RES", CC_CONNECT},
325         {"CONNECT_ACK", CC_CONNECT_ACKNOWLEDGE},
326         {"DISCONNECT", CC_DISCONNECT},
327         {"RELEASE", CC_RELEASE},
328         {"RELEASE_COMP", CC_RELEASE_COMPLETE},
329         {"INFORMATION", CC_INFORMATION},
330         {"PROGRESS", CC_PROGRESS},
331         {"NOTIFY", CC_NOTIFY},
332         {"SUSPEND", CC_SUSPEND},
333         {"SUSPEND_ACK", CC_SUSPEND_ACKNOWLEDGE},
334         {"SUSPEND_REJ", CC_SUSPEND_REJECT},
335         {"RESUME", CC_RESUME},
336         {"RESUME_ACK", CC_RESUME_ACKNOWLEDGE},
337         {"RESUME_REJ", CC_RESUME_REJECT},
338         {"HOLD", CC_HOLD},
339         {"HOLD_ACK", CC_HOLD_ACKNOWLEDGE},
340         {"HOLD_REJ", CC_HOLD_REJECT},
341         {"RETRIEVE", CC_RETRIEVE},
342         {"RETRIEVE_ACK", CC_RETRIEVE_ACKNOWLEDGE},
343         {"RETRIEVE_REJ", CC_RETRIEVE_REJECT},
344         {"FACILITY", CC_FACILITY},
345         {"STATUS", CC_STATUS},
346         {"RESTART", CC_RESTART},
347         {"RELEASE_CR", CC_RELEASE_CR},
348         {"NEW_CR", CC_NEW_CR},
349         {"DL_ESTABLISH", DL_ESTABLISH},
350         {"DL_RELEASE", DL_RELEASE},
351         {"PH_ACTIVATE", PH_ACTIVATE},
352         {"PH_DEACTIVATE", PH_DEACTIVATE},
353
354         {NULL, 0},
355 };
356 static char *isdn_prim[4] = {
357         " REQUEST",
358         " CONFIRM",
359         " INDICATION",
360         " RESPONSE",
361 };
362 void l1l2l3_trace_header(struct mISDNport *mISDNport, class PmISDN *port, unsigned long prim, int direction)
363 {
364         int i;
365         char msgtext[64] = "<<UNKNOWN MESSAGE>>";
366
367         /* select message and primitive text */
368         i = 0;
369         while(isdn_message[i].name)
370         {
371                 if (isdn_message[i].value == (prim&0xffffff00))
372                 {
373                         SCPY(msgtext, isdn_message[i].name);
374                         break;
375                 }
376                 i++;
377         }
378         SCAT(msgtext, isdn_prim[prim&0x00000003]);
379
380         /* add direction */
381         if (direction && (prim&0xffffff00)!=CC_NEW_CR && (prim&0xffffff00)!=CC_RELEASE_CR)
382         {
383                 if (mISDNport)
384                 {
385                         if (mISDNport->ntmode)
386                         {
387                                 if (direction == DIRECTION_OUT)
388                                         SCAT(msgtext, " N->U");
389                                 else
390                                         SCAT(msgtext, " N<-U");
391                         } else
392                         {
393                                 if (direction == DIRECTION_OUT)
394                                         SCAT(msgtext, " U->N");
395                                 else
396                                         SCAT(msgtext, " U<-N");
397                         }
398                 }
399         }
400
401         /* init trace with given values */
402         start_trace(mISDNport?mISDNport->portnum:0,
403                     mISDNport?mISDNport->ifport->interface:NULL,
404                     port?numberrize_callerinfo(port->p_callerinfo.id, port->p_callerinfo.ntype):NULL,
405                     port?port->p_dialinginfo.id:NULL,
406                     direction,
407                     CATEGORY_CH,
408                     port?port->p_serial:0,
409                     msgtext);
410 }
411
412
413 /*
414  * send control information to the channel (dsp-module)
415  */
416 void ph_control(struct mISDNport *mISDNport, class PmISDN *isdnport, unsigned long handle, unsigned long c1, unsigned long c2, char *trace_name, int trace_value)
417 {
418 #ifdef SOCKET_MISDN
419         unsigned char buffer[MISDN_HEADER_LEN+sizeof(int)+sizeof(int)];
420         struct mISDNhead *ctrl = (struct mISDNhead *)buffer;
421         unsigned long *d = buffer+MISDN_HEADER_LEN;
422         int ret;
423
424         ctrl->prim = PH_CONTROL_REQ;
425         ctrl->id = 0;
426         *d++ = c1;
427         *d++ = c2;
428         ret = sendto(handle, buffer, MISDN_HEADER_LEN+sizeof(int)*2, 0, NULL, 0);
429         if (!ret)
430                 PERROR("Failed to send to socket %d\n", handle);
431 #else
432         unsigned char buffer[mISDN_HEADER_LEN+sizeof(int)+sizeof(int)];
433         iframe_t *ctrl = (iframe_t *)buffer; 
434         unsigned long *d = (unsigned long *)&ctrl->data.p;
435
436         ctrl->prim = PH_CONTROL | REQUEST;
437         ctrl->addr = handle | FLG_MSG_DOWN;
438         ctrl->dinfo = 0;
439         ctrl->len = sizeof(int)*2;
440         *d++ = c1;
441         *d++ = c2;
442         mISDN_write(mISDNdevice, ctrl, mISDN_HEADER_LEN+ctrl->len, TIMEOUT_1SEC);
443 #endif
444         chan_trace_header(mISDNport, isdnport, "BCHANNEL control", DIRECTION_OUT);
445         if (c1 == CMX_CONF_JOIN)
446                 add_trace(trace_name, NULL, "0x%08x", trace_value);
447         else
448                 add_trace(trace_name, NULL, "%d", trace_value);
449         end_trace();
450 }
451
452 void ph_control_block(struct mISDNport *mISDNport, class PmISDN *isdnport, unsigned long handle, unsigned long c1, void *c2, int c2_len, char *trace_name, int trace_value)
453 {
454 #ifdef SOCKET_MISDN
455         unsigned char buffer[MISDN_HEADER_LEN+sizeof(int)+c2_len];
456         struct mISDNhead *ctrl = (struct mISDNhead *)buffer;
457         unsigned long *d = buffer+MISDN_HEADER_LEN;
458         int ret;
459
460         ctrl->prim = PH_CONTROL_REQ;
461         ctrl->id = 0;
462         *d++ = c1;
463         memcpy(d, c2, c2_len);
464         ret = sendto(handle, buffer, MISDN_HEADER_LEN+sizeof(int)+c2_len, 0, NULL, 0);
465         if (!ret)
466                 PERROR("Failed to send to socket %d\n", handle);
467 #else
468         unsigned char buffer[mISDN_HEADER_LEN+sizeof(int)+c2_len];
469         iframe_t *ctrl = (iframe_t *)buffer;
470         unsigned long *d = (unsigned long *)&ctrl->data.p;
471
472         ctrl->prim = PH_CONTROL | REQUEST;
473         ctrl->addr = handle | FLG_MSG_DOWN;
474         ctrl->dinfo = 0;
475         ctrl->len = sizeof(int)+c2_len;
476         *d++ = c1;
477         memcpy(d, c2, c2_len);
478         mISDN_write(mISDNdevice, ctrl, mISDN_HEADER_LEN+ctrl->len, TIMEOUT_1SEC);
479 #endif
480         chan_trace_header(mISDNport, isdnport, "BCHANNEL control", DIRECTION_OUT);
481         add_trace(trace_name, NULL, "%d", trace_value);
482         end_trace();
483 }
484
485
486 /*
487  * subfunction for bchannel_event
488  * create stack
489  */
490 static int _bchannel_create(struct mISDNport *mISDNport, int i)
491 {
492         unsigned char buff[1024];
493         int ret;
494 #ifdef SOCKET_MISDN
495         unsigned long on = 1;
496         struct sockadd_mISDN addr;
497
498         if (mISDNport->b_socket[i])
499         {
500                 PERROR("Error: Socket already created for index %d\n", i);
501                 return(0);
502         }
503
504         /* open socket */
505         mISDNport->b_socket[i] = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_B_L2DSP);
506         if (mISDNport->b_socket[i] < 0)
507         {
508                 PERROR("Error: Failed to open bchannel-socket for index %d with mISDN-DSP layer. Did you load mISDNdsp.ko?\n", i);
509                 return(0);
510         }
511         
512         /* set nonblocking io */
513         ret = ioctl(mISDNport->b_socket[i], FIONBIO, &on);
514         if (ret < 0)
515         {
516                 PERROR("Error: Failed to set bchannel-socket index %d into nonblocking IO\n", i);
517                 close(mISDNport->b_socket[i]);
518                 mISDNport->b_socket[i] = -1;
519                 return(0);
520         }
521
522         /* bind socket to bchannel */
523         addr.family = AF_ISDN;
524         addr.dev = mISDNport->port-1;
525         addr.channel = i+1+(i>=15);
526         ret = bind(di->bchan, (struct sockaddr *)&addr, sizeof(addr));
527         if (ret < 0)
528         {
529                 PERROR("Error: Failed to bind bchannel-socket for index %d with mISDN-DSP layer. Did you load mISDNdsp.ko?\n", i);
530                 close(mISDNport->b_socket[i]);
531                 mISDNport->b_socket[i] = -1;
532                 return(0);
533         }
534
535         chan_trace_header(mISDNport, mISDNport->b_port[i], "BCHANNEL create socket", DIRECTION_OUT);
536         add_trace("channel", NULL, "%d", i+1+(i>=15));
537         add_trace("socket", NULL, "%d", mISDNport->b_socket[i]);
538         end_trace();
539 #else
540         layer_info_t li;
541         mISDN_pid_t pid;
542
543         if (!mISDNport->b_stid[i])
544         {
545                 PERROR("Error: no stack for index %d\n", i);
546                 return(0);
547         }
548         if (mISDNport->b_addr[i])
549         {
550                 PERROR("Error: stack already created for index %d\n", i);
551                 return(0);
552         }
553
554         /* create new layer */
555         PDEBUG(DEBUG_BCHANNEL, "creating new layer for bchannel %d (index %d).\n" , i+1+(i>=15), i);
556         memset(&li, 0, sizeof(li));
557         memset(&pid, 0, sizeof(pid));
558         li.object_id = -1;
559         li.extentions = 0;
560         li.st = mISDNport->b_stid[i];
561         UCPY(li.name, "B L4");
562         li.pid.layermask = ISDN_LAYER((4));
563         li.pid.protocol[4] = ISDN_PID_L4_B_USER;
564         ret = mISDN_new_layer(mISDNdevice, &li);
565         if (ret)
566         {
567                 failed_new_layer:
568                 PERROR("mISDN_new_layer() failed to add bchannel %d (index %d)\n", i+1+(i>=15), i);
569                 goto failed;
570         }
571         mISDNport->b_addr[i] = li.id;
572         if (!li.id)
573         {
574                 goto failed_new_layer;
575         }
576         PDEBUG(DEBUG_BCHANNEL, "new layer (b_addr=0x%x)\n", mISDNport->b_addr[i]);
577
578         /* create new stack */
579         pid.protocol[1] = ISDN_PID_L1_B_64TRANS;
580         pid.protocol[2] = ISDN_PID_L2_B_TRANS;
581         pid.protocol[3] = ISDN_PID_L3_B_DSP;
582         pid.protocol[4] = ISDN_PID_L4_B_USER;
583         pid.layermask = ISDN_LAYER((1)) | ISDN_LAYER((2)) | ISDN_LAYER((3)) | ISDN_LAYER((4));
584         ret = mISDN_set_stack(mISDNdevice, mISDNport->b_stid[i], &pid);
585         if (ret)
586         {
587                 stack_error:
588                 PERROR("mISDN_set_stack() failed (ret=%d) to add bchannel (index %d) stid=0x%x\n", ret, i, mISDNport->b_stid[i]);
589                 mISDN_write_frame(mISDNdevice, buff, mISDNport->b_addr[i], MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
590                 goto failed;
591         }
592         ret = mISDN_get_setstack_ind(mISDNdevice, mISDNport->b_addr[i]);
593         if (ret)
594                 goto stack_error;
595
596         /* get layer id */
597         mISDNport->b_addr[i] = mISDN_get_layerid(mISDNdevice, mISDNport->b_stid[i], 4);
598         if (!mISDNport->b_addr[i])
599                 goto stack_error;
600         chan_trace_header(mISDNport, mISDNport->b_port[i], "BCHANNEL create stack", DIRECTION_OUT);
601         add_trace("channel", NULL, "%d", i+1+(i>=15));
602         add_trace("stack", "id", "0x%08x", mISDNport->b_stid[i]);
603         add_trace("stack", "address", "0x%08x", mISDNport->b_addr[i]);
604         end_trace();
605 #endif
606
607         return(1);
608
609 failed:
610         mISDNport->b_addr[i] = 0;
611         return(0);
612 }
613
614
615 /*
616  * subfunction for bchannel_event
617  * activate / deactivate request
618  */
619 static void _bchannel_activate(struct mISDNport *mISDNport, int i, int activate)
620 {
621 #ifdef SOCKET_MISDN
622         struct mISDNhead act;
623         int ret;
624
625         act.prim = (activate)?DL_ESTABLISH_REQ:DL_RELEASE_REQ; 
626         act.id = 0;
627         ret = sendto(mISDNport->b_socket[i], &act, MISDN_HEADER_LEN, 0, NULL, 0);
628         if (!ret)
629                 PERROR("Failed to send to socket %d\n", mISDNport->b_socket[i]);
630 #else
631         iframe_t act;
632
633         /* activate bchannel */
634         act.prim = (activate?DL_ESTABLISH:DL_RELEASE) | REQUEST; 
635         act.addr = mISDNport->b_addr[i] | FLG_MSG_DOWN;
636         act.dinfo = 0;
637         act.len = 0;
638         mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
639 #endif
640
641         /* trace */
642         chan_trace_header(mISDNport, mISDNport->b_port[i], activate?(char*)"BCHANNEL activate":(char*)"BCHANNEL deactivate", DIRECTION_OUT);
643         add_trace("channel", NULL, "%d", i+1+(i>=15));
644         end_trace();
645 }
646
647
648 /*
649  * subfunction for bchannel_event
650  * set features
651  */
652 static void _bchannel_configure(struct mISDNport *mISDNport, int i)
653 {
654         struct PmISDN *port;
655 #ifdef SOCKET_MISDN
656         int handle;
657
658         handle = mISDNport->b_socket[i];
659 #else
660         unsigned long handle;
661
662         handle = mISDNport->b_addr[i];
663 #endif
664         port = mISDNport->b_port[i];
665         if (!port)
666         {
667                 PERROR("bchannel index i=%d not associated with a port object\n", i);
668                 return;
669         }
670
671         /* set dsp features */
672 #ifndef OLD_MISDN
673         if (port->p_m_txdata)
674                 ph_control(mISDNport, port, handle, (port->p_m_txdata)?CMX_TXDATA_ON:CMX_TXDATA_OFF, 0, "DSP-TXDATA", port->p_m_txdata);
675         if (port->p_m_delay)
676                 ph_control(mISDNport, port, handle, CMX_DELAY, port->p_m_delay, "DSP-DELAY", port->p_m_delay);
677 #endif
678         if (port->p_m_tx_gain)
679                 ph_control(mISDNport, port, handle, VOL_CHANGE_TX, port->p_m_tx_gain, "DSP-TX_GAIN", port->p_m_tx_gain);
680         if (port->p_m_rx_gain)
681                 ph_control(mISDNport, port, handle, VOL_CHANGE_RX, port->p_m_rx_gain, "DSP-RX_GAIN", port->p_m_rx_gain);
682 #ifndef OLD_MISDN
683         if (port->p_m_pipeline[0])
684                 ph_control_block(mISDNport, port, handle, PIPELINE_CFG, port->p_m_pipeline, strlen(port->p_m_pipeline)+1, "DSP-PIPELINE", 0);
685 #endif
686         if (port->p_m_conf)
687                 ph_control(mISDNport, port, handle, CMX_CONF_JOIN, port->p_m_conf, "DSP-CONF", port->p_m_conf);
688         if (port->p_m_echo)
689                 ph_control(mISDNport, port, handle, CMX_ECHO_ON, 0, "DSP-ECHO", 1);
690         if (port->p_m_tone)
691                 ph_control(mISDNport, port, handle, TONE_PATT_ON, port->p_m_tone, "DSP-TONE", port->p_m_tone);
692         if (port->p_m_rxoff)
693                 ph_control(mISDNport, port, handle, CMX_RECEIVE_OFF, 0, "DSP-RXOFF", 1);
694 //      if (port->p_m_txmix)
695 //              ph_control(mISDNport, port, handle, CMX_MIX_ON, 0, "DSP-MIX", 1);
696         if (port->p_m_dtmf)
697                 ph_control(mISDNport, port, handle, DTMF_TONE_START, 0, "DSP-DTMF", 1);
698         if (port->p_m_crypt)
699                 ph_control_block(mISDNport, port, handle, BF_ENABLE_KEY, port->p_m_crypt_key, port->p_m_crypt_key_len, "DSP-CRYPT", port->p_m_crypt_key_len);
700 }
701
702 /*
703  * subfunction for bchannel_event
704  * destroy stack
705  */
706 static void _bchannel_destroy(struct mISDNport *mISDNport, int i)
707 {
708 #ifdef SOCKET_MISDN
709         chan_trace_header(mISDNport, mISDNport->b_port[i], "BCHANNEL remove socket", DIRECTION_OUT);
710         add_trace("channel", NULL, "%d", i+1+(i>=15));
711         add_trace("socket", NULL, "%d", mISDNport->b_socket[i]);
712         end_trace();
713         if (mISDNport->b_socket[i] > -1)
714         {
715                 close(mISDNport->b_socket[i]);
716                 mISDNport->b_socket[i] = -1;
717         }
718 #else
719         unsigned char buff[1024];
720
721         chan_trace_header(mISDNport, mISDNport->b_port[i], "BCHANNEL remove stack", DIRECTION_OUT);
722         add_trace("channel", NULL, "%d", i+1+(i>=15));
723         add_trace("stack", "id", "0x%08x", mISDNport->b_stid[i]);
724         add_trace("stack", "address", "0x%08x", mISDNport->b_addr[i]);
725         end_trace();
726         /* remove our stack only if set */
727         if (mISDNport->b_addr[i])
728         {
729                 PDEBUG(DEBUG_BCHANNEL, "free stack (b_addr=0x%x)\n", mISDNport->b_addr[i]);
730                 mISDN_clear_stack(mISDNdevice, mISDNport->b_stid[i]);
731                 mISDN_write_frame(mISDNdevice, buff, mISDNport->b_addr[i] | FLG_MSG_DOWN, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
732                 mISDNport->b_addr[i] = 0;
733         }
734 #endif
735 }
736
737
738 /*
739 bchannel procedure
740 ------------------
741
742 A bchannel goes through the following states in this order:
743
744 - B_STATE_IDLE
745 No one is using the bchannel.
746 It is available and not linked to Port class, nor reserved.
747
748 - B_STATE_ACTIVATING
749 The bchannel stack is created and an activation request is sent.
750 It MAY be linked to Port class, but already unlinked due to Port class removal.
751
752 - B_STATE_ACTIVE
753 The bchannel is active and cofigured to the Port class needs.
754 Also it is linked to a Port class, otherwhise it would be deactivated.
755
756 - B_STATE_DEACTIVATING
757 The bchannel is in deactivating state, due to deactivation request.
758 It may be linked to a Port class, that likes to reactivate it.
759
760 - B_STATE_IDLE
761 See above.
762 After deactivating bchannel, and if not used, the bchannel becomes idle again.
763
764 Also the bchannel may be exported, but only if the state is or becomes idle:
765
766 - B_STATE_EXPORTING
767 The bchannel assignment has been sent to the remove application.
768
769 - B_STATE_REMOTE
770 The bchannel assignment is acknowledged by the remote application.
771
772 - B_STATE_IMPORTING
773 The bchannel is re-imported by mISDN port object.
774
775 - B_STATE_IDLE
776 See above.
777 After re-importing bchannel, and if not used, the bchannel becomes idle again.
778
779
780 A bchannel can have the following events:
781
782 - B_EVENT_USE
783 A bchannel is required by a Port class.
784 The bchannel shall be exported to the remote application.
785
786 - B_EVENT_ACTIVATED
787 The bchannel beomes active.
788
789 - B_EVENT_DROP
790 The bchannel is not required by Port class anymore
791
792 - B_EVENT_DEACTIVATED
793 The bchannel becomes inactive.
794
795 - B_EVENT_EXPORTED
796 The bchannel is now used by remote application.
797
798 - B_EVENT_IMPORTED
799 The bchannel is not used by remote application.
800
801 All actions taken on these events depend on the current bchannel's state and if it is linked to a Port class.
802
803 if an export request is receive by remote application, p_m_remote_* is set.
804 the b_remote_*[index] indicates if and where the channel is exported to. (set from the point on, where export is initiated, until imported is acknowledged.)
805 - set on export request from remote application (if port is assigned)
806 - set on channel use, if requested by remote application (p_m_remote_*)
807 - cleared on drop request
808
809 the bchannel will be exported with ref and stack given. remote application uses the ref to link bchannel to the call.
810 the bchannel will be imported with stack given only. remote application must store stack id with the bchannel process.
811 the bchannel import/export is acknowledged with stack given.
812
813 if exporting, b_remote_*[index] is set to the remote socket id.
814 if importing has been acknowledged. b_remote_*[index] is cleared.
815
816 */
817
818 /*
819  * process bchannel events
820  * - mISDNport is a pointer to the port's structure
821  * - i is the index of the bchannel
822  * - event is the B_EVENT_* value
823  * - port is the PmISDN class pointer
824  */
825 void bchannel_event(struct mISDNport *mISDNport, int i, int event)
826 {
827         class PmISDN *b_port = mISDNport->b_port[i];
828         int state = mISDNport->b_state[i];
829         unsigned long p_m_remote_ref = 0;
830         unsigned long p_m_remote_id = 0;
831         int p_m_tx_gain = 0;
832         int p_m_rx_gain = 0;
833         char *p_m_pipeline = NULL;
834         unsigned char *p_m_crypt_key = NULL;
835         int p_m_crypt_key_len = 0;
836         int p_m_crypt_key_type = 0;
837 #ifdef SOCKET_MISDN
838         unsigned long portid = (mISDNport->portnum<<8) + i+1+(i>=15);
839 #else
840         unsigned long portid = mISDNport->b_stid[i];
841 #endif
842
843         if (b_port)
844         {
845                 p_m_remote_id = b_port->p_m_remote_id;
846                 p_m_remote_ref = b_port->p_m_remote_ref;
847                 p_m_tx_gain = b_port->p_m_tx_gain;
848                 p_m_rx_gain = b_port->p_m_rx_gain;
849                 p_m_pipeline = b_port->p_m_pipeline;
850                 p_m_crypt_key = b_port->p_m_crypt_key;
851                 p_m_crypt_key_len = b_port->p_m_crypt_key_len;
852                 p_m_crypt_key_type = /*b_port->p_m_crypt_key_type*/1;
853         }
854
855         switch(event)
856         {
857                 case B_EVENT_USE:
858                 /* port must be linked in order to allow activation */
859                 if (!b_port)
860                         FATAL("bchannel must be linked to a Port class\n");
861                 switch(state)
862                 {
863                         case B_STATE_IDLE:
864                         if (p_m_remote_ref)
865                         {
866                                 /* export bchannel */
867                                 message_bchannel_to_join(p_m_remote_id, p_m_remote_ref, BCHANNEL_ASSIGN, portid, p_m_tx_gain, p_m_rx_gain, p_m_pipeline, p_m_crypt_key, p_m_crypt_key_len, p_m_crypt_key_type);
868                                 chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
869                                 add_trace("type", NULL, "assign");
870 #ifdef SOCKET_MISDN
871                                 add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff);
872 #else
873                                 add_trace("socket", "id", "%d", portid);
874 #endif
875                                 end_trace();
876                                 state = B_STATE_EXPORTING;
877                                 mISDNport->b_remote_id[i] = p_m_remote_id;
878                                 mISDNport->b_remote_ref[i] = p_m_remote_ref;
879                         } else
880                         {
881                                 /* create stack and send activation request */
882                                 if (_bchannel_create(mISDNport, i))
883                                 {
884                                         _bchannel_activate(mISDNport, i, 1);
885                                         state = B_STATE_ACTIVATING;
886                                 }
887                         }
888                         break;
889
890                         case B_STATE_ACTIVATING:
891                         case B_STATE_EXPORTING:
892                         /* do nothing, because it is already activating */
893                         break;
894
895                         case B_STATE_DEACTIVATING:
896                         case B_STATE_IMPORTING:
897                         /* do nothing, because we must wait until we can reactivate */
898                         break;
899
900                         default:
901                         /* problems that might ocurr:
902                          * B_EVENT_USE is received when channel already in use.
903                          * bchannel exported, but not freed by other port
904                          */
905                         PERROR("Illegal event %d at state %d, please correct.\n", event, state);
906                 }
907                 break;
908
909                 case B_EVENT_EXPORTREQUEST:
910                 /* special case where the bchannel is requested by remote */
911                 if (!p_m_remote_ref)
912                 {
913                         PERROR("export request without remote channel set, please correct.\n");
914                         break;
915                 }
916                 switch(state)
917                 {
918                         case B_STATE_IDLE:
919                         /* in case, the bchannel is exported right after seize_bchannel */
920                         /* export bchannel */
921                         /* p_m_remote_id is set, when this event happens. */
922                         message_bchannel_to_join(p_m_remote_id, p_m_remote_ref, BCHANNEL_ASSIGN, portid, p_m_tx_gain, p_m_rx_gain, p_m_pipeline, p_m_crypt_key, p_m_crypt_key_len, p_m_crypt_key_type);
923                         chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
924                         add_trace("type", NULL, "assign");
925 #ifdef SOCKET_MISDN
926                         add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff);
927 #else
928                         add_trace("socket", "id", "%d", portid);
929 #endif
930                         end_trace();
931                         state = B_STATE_EXPORTING;
932                         mISDNport->b_remote_id[i] = p_m_remote_id;
933                         mISDNport->b_remote_ref[i] = p_m_remote_ref;
934                         break;
935
936                         case B_STATE_ACTIVATING:
937                         case B_STATE_EXPORTING:
938                         /* do nothing, because it is already activating */
939                         break;
940
941                         case B_STATE_DEACTIVATING:
942                         case B_STATE_IMPORTING:
943                         /* do nothing, because we must wait until we can reactivate */
944                         break;
945
946                         case B_STATE_ACTIVE:
947                         /* bchannel is active, so we deactivate */
948                         _bchannel_activate(mISDNport, i, 0);
949                         state = B_STATE_DEACTIVATING;
950                         break;
951
952                         default:
953                         /* problems that might ocurr:
954                          * ... when channel already in use.
955                          * bchannel exported, but not freed by other port
956                          */
957                         PERROR("Illegal event %d at state %d, please correct.\n", event, state);
958                 }
959                 break;
960
961                 case B_EVENT_ACTIVATED:
962                 switch(state)
963                 {
964                         case B_STATE_ACTIVATING:
965                         if (b_port && !p_m_remote_id)
966                         {
967                                 /* bchannel is active and used by Port class, so we configure bchannel */
968                                 _bchannel_configure(mISDNport, i);
969                                 state = B_STATE_ACTIVE;
970                         } else
971                         {
972                                 /* bchannel is active, but exported OR not used anymore (or has wrong stack config), so we deactivate */
973                                 _bchannel_activate(mISDNport, i, 0);
974                                 state = B_STATE_DEACTIVATING;
975                         }
976                         break;
977
978                         default:
979                         PERROR("Illegal event %d at state %d, please correct.\n", event, state);
980                 }
981                 break;
982
983                 case B_EVENT_EXPORTED:
984                 switch(state)
985                 {
986                         case B_STATE_EXPORTING:
987                         if (b_port && p_m_remote_ref && p_m_remote_ref==mISDNport->b_remote_ref[i])
988                         {
989                                 /* remote export done */
990                                 state = B_STATE_REMOTE;
991                         } else
992                         {
993                                 /* bchannel is now exported, but we need bchannel back
994                                  * OR bchannel is not used anymore
995                                  * OR bchannel has been exported to an obsolete ref,
996                                  * so reimport, to later export to new remote */
997                                 message_bchannel_to_join(mISDNport->b_remote_id[i], 0, BCHANNEL_REMOVE, portid, 0,0,0,0,0,0);
998                                 chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
999                                 add_trace("type", NULL, "remove");
1000 #ifdef SOCKET_MISDN
1001                                 add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff);
1002 #else
1003                                 add_trace("socket", "id", "%d", portid);
1004 #endif
1005                                 end_trace();
1006                                 state = B_STATE_IMPORTING;
1007                         }
1008                         break;
1009
1010                         default:
1011                         PERROR("Illegal event %d at state %d, please correct.\n", event, state);
1012                 }
1013                 break;
1014
1015                 case B_EVENT_DROP:
1016                 if (!b_port)
1017                         FATAL("bchannel must be linked to a Port class\n");
1018                 switch(state)
1019                 {
1020                         case B_STATE_IDLE:
1021                         /* bchannel is idle due to an error, so we do nothing */
1022                         break;
1023
1024                         case B_STATE_ACTIVATING:
1025                         case B_STATE_EXPORTING:
1026                         /* do nothing because we must wait until bchanenl is active before deactivating */
1027                         break;
1028
1029                         case B_STATE_ACTIVE:
1030                         /* bchannel is active, so we deactivate */
1031                         _bchannel_activate(mISDNport, i, 0);
1032                         state = B_STATE_DEACTIVATING;
1033                         break;
1034
1035                         case B_STATE_REMOTE:
1036                         /* bchannel is exported, so we re-import */
1037                         message_bchannel_to_join(mISDNport->b_remote_id[i], 0, BCHANNEL_REMOVE, portid, 0,0,0,0,0,0);
1038                         chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
1039                         add_trace("type", NULL, "remove");
1040 #ifdef SOCKET_MISDN
1041                         add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff);
1042 #else
1043                         add_trace("socket", "id", "%d", portid);
1044 #endif
1045                         end_trace();
1046                         state = B_STATE_IMPORTING;
1047                         break;
1048
1049                         case B_STATE_DEACTIVATING:
1050                         case B_STATE_IMPORTING:
1051                         /* we may have taken an already deactivating bchannel, but do not require it anymore, so we do nothing */
1052                         break;
1053
1054                         default:
1055                         PERROR("Illegal event %d at state %d, please correct.\n", event, state);
1056                 }
1057                 break;
1058
1059                 case B_EVENT_DEACTIVATED:
1060                 switch(state)
1061                 {
1062                         case B_STATE_IDLE:
1063                         /* ignore due to deactivation confirm after unloading */
1064                         break;
1065
1066                         case B_STATE_DEACTIVATING:
1067                         _bchannel_destroy(mISDNport, i);
1068                         state = B_STATE_IDLE;
1069                         if (b_port)
1070                         {
1071                                 /* bchannel is now deactivate, but is requied by Port class, so we reactivate / export */
1072                                 if (p_m_remote_ref)
1073                                 {
1074                                         message_bchannel_to_join(p_m_remote_id, p_m_remote_ref, BCHANNEL_ASSIGN, portid, p_m_tx_gain, p_m_rx_gain, p_m_pipeline, p_m_crypt_key, p_m_crypt_key_len, p_m_crypt_key_type);
1075                                         chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
1076                                         add_trace("type", NULL, "assign");
1077 #ifdef SOCKET_MISDN
1078                                         add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff);
1079 #else
1080                                         add_trace("socket", "id", "%d", portid);
1081 #endif
1082                                         end_trace();
1083                                         state = B_STATE_EXPORTING;
1084                                         mISDNport->b_remote_id[i] = p_m_remote_id;
1085                                         mISDNport->b_remote_ref[i] = p_m_remote_ref;
1086                                 } else
1087                                 {
1088                                         if (_bchannel_create(mISDNport, i))
1089                                         {
1090                                                 _bchannel_activate(mISDNport, i, 1);
1091                                                 state = B_STATE_ACTIVATING;
1092                                         }
1093                                 }
1094                         }
1095                         break;
1096
1097                         default:
1098                         PERROR("Illegal event %d at state %d, please correct.\n", event, state);
1099                 }
1100                 break;
1101
1102                 case B_EVENT_IMPORTED:
1103                 switch(state)
1104                 {
1105                         case B_STATE_IMPORTING:
1106                         state = B_STATE_IDLE;
1107                         mISDNport->b_remote_id[i] = 0;
1108                         mISDNport->b_remote_ref[i] = 0;
1109                         if (b_port)
1110                         {
1111                                 /* bchannel is now imported, but is requied by Port class, so we reactivate / export */
1112                                 if (p_m_remote_ref)
1113                                 {
1114                                         message_bchannel_to_join(p_m_remote_id, p_m_remote_ref, BCHANNEL_ASSIGN, portid, p_m_tx_gain, p_m_rx_gain, p_m_pipeline, p_m_crypt_key, p_m_crypt_key_len, p_m_crypt_key_type);
1115                                         chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
1116                                         add_trace("type", NULL, "assign");
1117 #ifdef SOCKET_MISDN
1118                                         add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff);
1119 #else
1120                                         add_trace("socket", "id", "%d", portid);
1121 #endif
1122                                         end_trace();
1123                                         state = B_STATE_EXPORTING;
1124                                         mISDNport->b_remote_id[i] = p_m_remote_id;
1125                                         mISDNport->b_remote_ref[i] = p_m_remote_ref;
1126                                 } else
1127                                 {
1128                                         if (_bchannel_create(mISDNport, i))
1129                                         {
1130                                                 _bchannel_activate(mISDNport, i, 1);
1131                                                 state = B_STATE_ACTIVATING;
1132                                         }
1133                                 }
1134                         }
1135                         break;
1136
1137                         default:
1138                         /* ignore, because not assigned */
1139                         ;
1140                 }
1141                 break;
1142
1143                 default:
1144                 PERROR("Illegal event %d, please correct.\n", event);
1145         }
1146
1147         mISDNport->b_state[i] = state;
1148 }
1149
1150
1151
1152
1153 /*
1154  * check for available channel and reserve+set it.
1155  * give channel number or SEL_CHANNEL_ANY or SEL_CHANNEL_NO
1156  * give exclusiv flag
1157  * returns -(cause value) or x = channel x or 0 = no channel
1158  * NOTE: no activation is done here
1159  */
1160 int PmISDN::seize_bchannel(int channel, int exclusive)
1161 {
1162         int i;
1163
1164         /* the channel is what we have */
1165         if (p_m_b_channel == channel)
1166                 return(channel);
1167
1168         /* if channel already in use, release it */
1169         if (p_m_b_channel)
1170                 drop_bchannel();
1171
1172         /* if CHANNEL_NO */
1173         if (channel==CHANNEL_NO || channel==0)
1174                 return(0);
1175         
1176         /* is channel in range ? */
1177         if (channel==16
1178          || (channel>p_m_mISDNport->b_num && channel<16)
1179          || ((channel-1)>p_m_mISDNport->b_num && channel>16)) /* channel-1 because channel 16 is not counted */
1180                 return(-6); /* channel unacceptable */
1181
1182         /* request exclusive channel */
1183         if (exclusive && channel>0)
1184         {
1185                 i = channel-1-(channel>16);
1186                 if (p_m_mISDNport->b_port[i])
1187                         return(-44); /* requested channel not available */
1188                 goto seize;
1189         }
1190
1191         /* ask for channel */
1192         if (channel>0)
1193         {
1194                 i = channel-1-(channel>16);
1195                 if (p_m_mISDNport->b_port[i] == NULL)
1196                         goto seize;
1197         }
1198
1199         /* search for channel */
1200         i = 0;
1201         while(i < p_m_mISDNport->b_num)
1202         {
1203                 if (!p_m_mISDNport->b_port[i])
1204                 {
1205                         channel = i+1+(i>=15);
1206                         goto seize;
1207                 }
1208                 i++;
1209         }
1210         return(-34); /* no free channel */
1211
1212 seize:
1213         PDEBUG(DEBUG_BCHANNEL, "PmISDN(%s) seizing bchannel %d (index %d)\n", p_name, channel, i);
1214
1215         /* link Port */
1216         p_m_mISDNport->b_port[i] = this;
1217         p_m_b_index = i;
1218         p_m_b_channel = channel;
1219         p_m_b_exclusive = exclusive;
1220
1221         /* reserve channel */
1222         if (!p_m_b_reserve)
1223         {
1224                 p_m_b_reserve = 1;
1225                 p_m_mISDNport->b_reserved++;
1226         }
1227
1228         return(channel);
1229 }
1230
1231 /*
1232  * drop reserved channel and unset it.
1233  * deactivation is also done
1234  */
1235 void PmISDN::drop_bchannel(void)
1236 {
1237         /* unreserve channel */
1238         if (p_m_b_reserve)
1239                 p_m_mISDNport->b_reserved--;
1240         p_m_b_reserve = 0;
1241
1242         /* if not in use */
1243         if (p_m_b_index < 0)
1244                 return;
1245         if (!p_m_b_channel)
1246                 return;
1247
1248         PDEBUG(DEBUG_BCHANNEL, "PmISDN(%s) dropping bchannel\n", p_name);
1249
1250         if (p_m_mISDNport->b_state[p_m_b_index] != B_STATE_IDLE)
1251                 bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_DROP);
1252         p_m_mISDNport->b_port[p_m_b_index] = NULL;
1253         p_m_b_index = -1;
1254         p_m_b_channel = 0;
1255         p_m_b_exclusive = 0;
1256 }
1257
1258 /* process bchannel export/import message from join */
1259 void message_bchannel_from_join(class JoinRemote *joinremote, int type, unsigned long handle)
1260 {
1261         class Endpoint *epoint;
1262         class Port *port;
1263         class PmISDN *isdnport;
1264         struct mISDNport *mISDNport;
1265         int i, ii;
1266
1267         switch(type)
1268         {
1269                 case BCHANNEL_REQUEST:
1270                 /* find the port object for the join object ref */
1271                 if (!(epoint = find_epoint_id(joinremote->j_epoint_id)))
1272                 {
1273                         PDEBUG(DEBUG_BCHANNEL, "join %d has no endpoint (anymore)\n", joinremote->j_serial);
1274                         return;
1275                 }
1276                 if (!epoint->ep_portlist)
1277                 {
1278                         PDEBUG(DEBUG_BCHANNEL, "join %d has no port (anymore in portlist)\n", joinremote->j_serial);
1279                         return;
1280                 }
1281                 if (epoint->ep_portlist->next)
1282                 {
1283                         PERROR("join %d has enpoint %d with more than one port. this shall not happen to remote joins.\n", joinremote->j_serial, epoint->ep_serial);
1284                 }
1285                 if (!(port = find_port_id(epoint->ep_portlist->port_id)))
1286                 {
1287                         PDEBUG(DEBUG_BCHANNEL, "join %d has no port (anymore as object)\n", joinremote->j_serial);
1288                         return;
1289                 }
1290                 if (!((port->p_type&PORT_CLASS_MASK) != PORT_CLASS_mISDN))
1291                 {
1292                         PERROR("join %d has port %d not of mISDN type. This shall not happen.\n", joinremote->j_serial, port->p_serial);
1293                 }
1294                 isdnport = (class PmISDN *)port;
1295
1296                 /* assign */
1297                 if (isdnport->p_m_remote_id)
1298                 {
1299                         PERROR("join %d recevied bchannel request from remote, but channel is already assinged.\n", joinremote->j_serial);
1300                         break;
1301                 }
1302                 mISDNport = isdnport->p_m_mISDNport;
1303                 i = isdnport->p_m_b_index;
1304                 chan_trace_header(mISDNport, isdnport, "MESSAGE_BCHANNEL (from remote application)", DIRECTION_NONE);
1305                 add_trace("type", NULL, "export request");
1306                 isdnport->p_m_remote_ref = joinremote->j_serial;
1307                 isdnport->p_m_remote_id = joinremote->j_remote_id;
1308                 if (mISDNport && i>=0)
1309                 {
1310                         bchannel_event(mISDNport, i, B_EVENT_EXPORTREQUEST);
1311                 }
1312                 end_trace();
1313                 break;
1314
1315                 case BCHANNEL_ASSIGN_ACK:
1316                 case BCHANNEL_REMOVE_ACK:
1317                 /* find mISDNport for stack ID */
1318                 mISDNport = mISDNport_first;
1319                 while(mISDNport)
1320                 {
1321                         i = 0;
1322                         ii = mISDNport->b_num;
1323                         while(i < ii)
1324                         {
1325 #ifdef SOCKET_MISDN
1326                                 if (mISDNport->b_socket[i] == handle)
1327 #else
1328                                 if ((unsigned long)(mISDNport->portnum<<8)+i+1+(i>=15) == handle)
1329 #endif
1330                                         break;
1331                                 i++;
1332                         }
1333                         if (i != ii)
1334                                 break;
1335                         mISDNport = mISDNport->next;
1336                 }
1337                 if (!mISDNport)
1338                 {
1339                         PERROR("received assign/remove ack for handle=%x, but handle does not exist in any mISDNport structure.\n", handle);
1340                         break;
1341                 }
1342                 /* mISDNport may now be set or NULL */
1343                 
1344                 /* set */
1345                 chan_trace_header(mISDNport, mISDNport->b_port[i], "MESSAGE_BCHANNEL (from remote application)", DIRECTION_NONE);
1346                 add_trace("type", NULL, (type==BCHANNEL_ASSIGN_ACK)?"assign_ack":"remove_ack");
1347                 if (mISDNport && i>=0)
1348                         bchannel_event(mISDNport, i, (type==BCHANNEL_ASSIGN_ACK)?B_EVENT_EXPORTED:B_EVENT_IMPORTED);
1349                 end_trace();
1350                 break;
1351                 default:
1352                 PERROR("received wrong bchannel message type %d from remote\n", type);
1353         }
1354 }
1355
1356
1357 /*
1358  * handler
1359
1360 audio transmission procedure:
1361 -----------------------------
1362
1363 * priority
1364 three sources of audio transmission:
1365 - crypto-data high priority
1366 - tones high priority (also high)
1367 - remote-data low priority
1368
1369 * elapsed
1370 a variable that temporarily shows the number of samples elapsed since last transmission process.
1371 p_m_last_tv_* is used to store that last timestamp. this is used to calculate the time elapsed.
1372
1373 * load
1374 a variable that is increased whenever data is transmitted.
1375 it is decreased while time elapses. it stores the number of samples that
1376 are currently loaded to dsp module.
1377 since clock in dsp module is the same clock for user space process, these 
1378 times have no skew.
1379
1380 * levels
1381 there are two levels:
1382 ISDN_LOAD will give the load that have to be kept in dsp.
1383 ISDN_MAXLOAD will give the maximum load before dropping.
1384
1385 * procedure for low priority data
1386 see txfromup() for procedure
1387 in short: remote data is ignored during high priority tones
1388
1389 * procedure for high priority data
1390 whenever load is below ISDN_LOAD, load is filled up to ISDN_LOAD
1391 if no more data is available, load becomes empty again.
1392
1393 'load' variable:
1394 0                    ISDN_LOAD           ISDN_MAXLOAD
1395 +--------------------+----------------------+
1396 |                    |                      |
1397 +--------------------+----------------------+
1398
1399 on empty load or on load below ISDN_LOAD, the load is inceased to ISDN_LOAD:
1400 0                    ISDN_LOAD           ISDN_MAXLOAD
1401 +--------------------+----------------------+
1402 |TTTTTTTTTTTTTTTTTTTT|                      |
1403 +--------------------+----------------------+
1404
1405 on empty load, remote-audio causes the load with the remote audio to be increased to ISDN_LOAD.
1406 0                    ISDN_LOAD           ISDN_MAXLOAD
1407 +--------------------+----------------------+
1408 |TTTTTTTTTTTTTTTTTTTTRRRRR                  |
1409 +--------------------+----------------------+
1410
1411  */
1412 int PmISDN::handler(void)
1413 {
1414         struct message *message;
1415         int elapsed = 0;
1416         int ret;
1417
1418         if ((ret = Port::handler()))
1419                 return(ret);
1420
1421         /* get elapsed */
1422         if (p_m_last_tv_sec)
1423         {
1424                 elapsed = 8000 * (now_tv.tv_sec - p_m_last_tv_sec)
1425                         + 8 * (now_tv.tv_usec/1000 - p_m_last_tv_msec);
1426         } else
1427         {
1428                 /* set clock of first process ever in this instance */
1429                 p_m_last_tv_sec = now_tv.tv_sec;
1430                 p_m_last_tv_msec = now_tv.tv_usec/1000;
1431         }
1432         /* process only if we have a minimum of samples, to make packets not too small */
1433         if (elapsed >= ISDN_TRANSMIT)
1434         {
1435                 /* set clock of last process! */
1436                 p_m_last_tv_sec = now_tv.tv_sec;
1437                 p_m_last_tv_msec = now_tv.tv_usec/1000;
1438
1439                 /* update load */
1440                 if (elapsed < p_m_load)
1441                         p_m_load -= elapsed;
1442                 else
1443                         p_m_load = 0;
1444
1445                 /* to send data, tone must be active OR crypt messages must be on */
1446                 if ((p_tone_name[0] || p_m_crypt_msg_loops)
1447                  && (p_m_load < ISDN_LOAD)
1448                  && (p_state==PORT_STATE_CONNECT || p_m_mISDNport->tones))
1449                 {
1450                         int tosend = ISDN_LOAD - p_m_load, length; 
1451 #ifdef SOCKET_MISDN
1452                         unsigned char buf[MISDN_HEADER_LEN+tosend];
1453                         struct mISDNhead *frm = (struct mISDNhead *)buf;
1454                         unsigned long *d = buf+MISDN_HEADER_LEN;
1455 #else
1456                         unsigned char buf[mISDN_HEADER_LEN+tosend];
1457                         iframe_t *frm = (iframe_t *)buf;
1458                         unsigned char *p = buf+mISDN_HEADER_LEN;
1459 #endif
1460
1461                         /* copy crypto loops */
1462                         while (p_m_crypt_msg_loops && tosend)
1463                         {
1464                                 /* how much do we have to send */
1465                                 length = p_m_crypt_msg_len - p_m_crypt_msg_current;
1466
1467                                 /* clip tosend */
1468                                 if (length > tosend)
1469                                         length = tosend;
1470
1471                                 /* copy message (part) to buffer */
1472                                 memcpy(p, p_m_crypt_msg+p_m_crypt_msg_current, length);
1473
1474                                 /* new position */
1475                                 p_m_crypt_msg_current += length;
1476                                 if (p_m_crypt_msg_current == p_m_crypt_msg_len)
1477                                 {
1478                                         /* next loop */
1479                                         p_m_crypt_msg_current = 0;
1480                                         p_m_crypt_msg_loops--;
1481 //                                      puts("eine loop weniger");
1482                                 }
1483
1484                                 /* new length */
1485                                 tosend -= length;
1486                         }
1487
1488                         /* copy tones */
1489                         if (p_tone_name[0] && tosend)
1490                         {
1491                                 tosend -= read_audio(p, tosend);
1492                         }
1493
1494                         /* send data */
1495 #ifdef SOCKET_MISDN
1496                         frm->prim = DL_DATA_REQ;
1497                         frm->id = 0;
1498                         ret = sendto(handle, buffer, MISDN_HEADER_LEN+ISDN_LOAD-p_m_load-tosend, 0, NULL, 0);
1499                         if (!ret)
1500                                 PERROR("Failed to send to socket %d\n", handle);
1501 #else
1502                         frm->prim = DL_DATA | REQUEST; 
1503                         frm->addr = p_m_mISDNport->b_addr[p_m_b_index] | FLG_MSG_DOWN;
1504                         frm->dinfo = 0;
1505                         frm->len = ISDN_LOAD - p_m_load - tosend;
1506 #endif
1507                         if (frm->len)
1508                                 mISDN_write(mISDNdevice, frm, mISDN_HEADER_LEN+frm->len, TIMEOUT_1SEC);
1509                         p_m_load += frm->len;
1510                 }
1511         }
1512
1513         // NOTE: deletion is done by the child class
1514
1515         /* handle timeouts */
1516         if (p_m_timeout)
1517         {
1518                 if (p_m_timer+p_m_timeout < now_d)
1519                 {
1520                         PDEBUG(DEBUG_ISDN, "(%s) timeout after %d seconds detected (state=%d).\n", p_name, p_m_timeout, p_state);
1521                         p_m_timeout = 0;
1522                         /* send timeout to endpoint */
1523                         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_TIMEOUT);
1524                         message->param.state = p_state;
1525                         message_put(message);
1526                         return(1);
1527                 }
1528         }
1529         
1530         return(0); /* nothing done */
1531 }
1532
1533
1534 /*
1535  * whenever we get audio data from bchannel, we process it here
1536  */
1537 #ifdef SOCKET_MISDN
1538 void PmISDN::bchannel_receive(mISDNhead *hh, unsigned char *data, int len)
1539 {
1540         unsigned long cont = *((unsigned long *)data);
1541 #else
1542 void PmISDN::bchannel_receive(iframe_t *frm)
1543 {
1544         int len = frm->len;
1545         unsigned long cont = *((unsigned long *)&frm->data.p);
1546         unsigned char *data =(unsigned char *)&frm->data.p;
1547 #endif
1548         unsigned char *data_temp;
1549         unsigned long length_temp;
1550         struct message *message;
1551         unsigned char *p;
1552         int l;
1553
1554 #ifdef SOCKET_MISDN
1555         if (hh->prim == PH_CONTROL_IND)
1556 #else
1557         if (frm->prim == (PH_CONTROL | INDICATION))
1558 #endif
1559         {
1560                 if (len < 4)
1561                 {
1562                         PERROR("SHORT READ OF PH_CONTROL INDICATION\n");
1563                         return;
1564                 }
1565                 if ((cont&(~DTMF_TONE_MASK)) == DTMF_TONE_VAL)
1566                 {
1567                         chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
1568                         add_trace("DTMF", NULL, "%c", cont & DTMF_TONE_MASK);
1569                         end_trace();
1570                         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_DTMF);
1571                         message->param.dtmf = cont & DTMF_TONE_MASK;
1572                         PDEBUG(DEBUG_PORT, "PmISDN(%s) PH_CONTROL INDICATION  DTMF digit '%c'\n", p_name, message->param.dtmf);
1573                         message_put(message);
1574                         return;
1575                 }
1576                 switch(cont)
1577                 {
1578                         case BF_REJECT:
1579                         chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
1580                         add_trace("DSP-CRYPT", NULL, "error");
1581                         end_trace();
1582                         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CRYPT);
1583                         message->param.crypt.type = CC_ERROR_IND;
1584                         PDEBUG(DEBUG_PORT, "PmISDN(%s) PH_CONTROL INDICATION  reject of blowfish.\n", p_name);
1585                         message_put(message);
1586                         break;
1587
1588                         case BF_ACCEPT:
1589                         chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
1590                         add_trace("DSP-CRYPT", NULL, "ok");
1591                         end_trace();
1592                         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CRYPT);
1593                         message->param.crypt.type = CC_ACTBF_CONF;
1594                         PDEBUG(DEBUG_PORT, "PmISDN(%s) PH_CONTROL INDICATION  accept of blowfish.\n", p_name);
1595                         message_put(message);
1596                         break;
1597
1598                         default:
1599                         chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
1600                         add_trace("unknown", NULL, "0x%x", cont);
1601                         end_trace();
1602                 }
1603                 return;
1604         }
1605 #ifdef SOCKET_MISDN
1606         if (hh->prim == PH_SIGNAL_IND)
1607 #else
1608         if (frm->prim == (PH_SIGNAL | INDICATION))
1609 #endif
1610         {
1611                 switch(frm->dinfo)
1612                 {
1613 #ifndef OLD_MISDN
1614                         case CMX_TX_DATA:
1615                         if (!p_m_txdata)
1616                         {
1617                                 /* if tx is off, it may happen that fifos send us pending informations, we just ignore them */
1618                                 PDEBUG(DEBUG_BCHANNEL, "PmISDN(%s) ignoring tx data, because 'txdata' is turned off\n", p_name);
1619                                 return;
1620                         }
1621                         /* see below (same condition) */
1622                         if (p_state!=PORT_STATE_CONNECT
1623                                  && !p_m_mISDNport->tones)
1624                                 break;
1625 //                      printf(".");fflush(stdout);return;
1626                         if (p_record)
1627                                 record(data, len, 1); // from up
1628                         break;
1629 #endif
1630
1631                         default:
1632                         chan_trace_header(p_m_mISDNport, this, "BCHANNEL signal", DIRECTION_IN);
1633                         add_trace("unknown", NULL, "0x%x", frm->dinfo);
1634                         end_trace();
1635                 }
1636                 return;
1637         }
1638 #ifdef SOCKET_MISDN
1639         if (hh->prim != PH_DATA_IND && hh->prim != DL_DATA_IND)
1640         {
1641                 PERROR("Bchannel received unknown primitve: 0x%x\n", hh->prim);
1642 #else
1643         if (frm->prim != (PH_DATA | INDICATION) && frm->prim != (DL_DATA | INDICATION))
1644         {
1645                 PERROR("Bchannel received unknown primitve: 0x%x\n", frm->prim);
1646 #endif
1647                 return;
1648         }
1649         /* calls will not process any audio data unless
1650          * the call is connected OR interface features audio during call setup.
1651          */
1652 //printf("%d -> %d prim=%x joindata=%d tones=%d\n", p_serial, ACTIVE_EPOINT(p_epointlist), frm->prim, p_m_joindata, p_m_mISDNport->earlyb);     
1653 #ifndef DEBUG_COREBRIDGE
1654         if (p_state!=PORT_STATE_CONNECT
1655          && !p_m_mISDNport->tones)
1656                 return;
1657 #endif
1658
1659         /* if rx is off, it may happen that fifos send us pending informations, we just ignore them */
1660         if (p_m_rxoff)
1661         {
1662                 PDEBUG(DEBUG_BCHANNEL, "PmISDN(%s) ignoring data, because rx is turned off\n", p_name);
1663                 return;
1664         }
1665
1666         /* record data */
1667         if (p_record)
1668                 record(data, len, 0); // from down
1669
1670         /* randomize and listen to crypt message if enabled */
1671         if (p_m_crypt_listen)
1672         {
1673                 /* the noisy randomizer */
1674                 p = data;
1675                 l = len;
1676                 while(l--)
1677                         mISDN_rand[mISDN_rand_count & 0xff] += *p++;
1678
1679                 cryptman_listen_bch(data, len);
1680         }
1681
1682         p = data;
1683
1684         /* send data to epoint */
1685         if (p_m_joindata && ACTIVE_EPOINT(p_epointlist)) /* only if we have an epoint object */
1686         {
1687                 length_temp = len;
1688                 data_temp = p;
1689                 while(length_temp)
1690                 {
1691                         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_DATA);
1692                         message->param.data.len = (length_temp>sizeof(message->param.data.data))?sizeof(message->param.data.data):length_temp;
1693                         memcpy(message->param.data.data, data_temp, message->param.data.len);
1694                         message_put(message);
1695                         if (length_temp <= sizeof(message->param.data.data))
1696                                 break;
1697                         data_temp += sizeof(message->param.data.data);
1698                         length_temp -= sizeof(message->param.data.data);
1699                 }
1700         }
1701 }
1702
1703
1704 /*
1705  * set echotest
1706  */
1707 void PmISDN::set_echotest(int echo)
1708 {
1709         if (p_m_echo != echo)
1710         {
1711                 p_m_echo = echo;
1712                 PDEBUG(DEBUG_ISDN, "we set echo to echo=%d.\n", p_m_echo);
1713                 if (p_m_b_channel)
1714                         if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1715 #ifdef SOCKET_MISDN
1716                                 ph_control(p_m_mISDNport, this, p_m_mISDNport->b_socket[p_m_b_index], p_m_echo?CMX_ECHO_ON:CMX_ECHO_OFF, 0, "DSP-ECHO", p_m_echo);
1717 #else
1718                                 ph_control(p_m_mISDNport, this, p_m_mISDNport->b_addr[p_m_b_index], p_m_echo?CMX_ECHO_ON:CMX_ECHO_OFF, 0, "DSP-ECHO", p_m_echo);
1719 #endif
1720         }
1721 }
1722
1723 /*
1724  * set tone
1725  */
1726 void PmISDN::set_tone(char *dir, char *tone)
1727 {
1728         int id;
1729
1730         if (!tone)
1731                 tone = "";
1732         PDEBUG(DEBUG_ISDN, "isdn port now plays tone:'%s'.\n", tone);
1733         if (!tone[0])
1734         {
1735                 id = TONE_OFF;
1736                 goto setdsp;
1737         }
1738
1739         /* check if we NOT really have to use a dsp-tone */
1740         if (!options.dsptones)
1741         {
1742                 nodsp:
1743                 if (p_m_tone)
1744                 if (p_m_b_index >= 0)
1745                 if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1746                 {
1747                         PDEBUG(DEBUG_ISDN, "we reset tone from id=%d to OFF.\n", p_m_tone);
1748 #ifdef SOCKET_MISDN
1749                         ph_control(p_m_mISDNport, this, p_m_mISDNport->b_socket[p_m_b_index], TONE_PATT_OFF, 0, "DSP-TONE", 0);
1750 #else
1751                         ph_control(p_m_mISDNport, this, p_m_mISDNport->b_addr[p_m_b_index], TONE_PATT_OFF, 0, "DSP-TONE", 0);
1752 #endif
1753                 }
1754                 p_m_tone = 0;
1755                 Port::set_tone(dir, tone);
1756                 return;
1757         }
1758         if (p_tone_dir[0])
1759                 goto nodsp;
1760
1761         /* now we USE dsp-tone, convert name */
1762         else if (!strcmp(tone, "dialtone"))
1763         {
1764                 switch(options.dsptones) {
1765                 case DSP_AMERICAN: id = TONE_AMERICAN_DIALTONE; break;
1766                 case DSP_GERMAN: id = TONE_GERMAN_DIALTONE; break;
1767                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDDIALTONE; break;
1768                 }
1769         } else if (!strcmp(tone, "dialpbx"))
1770         {
1771                 switch(options.dsptones) {
1772                 case DSP_AMERICAN: id = TONE_AMERICAN_DIALPBX; break;
1773                 case DSP_GERMAN: id = TONE_GERMAN_DIALPBX; break;
1774                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDDIALPBX; break;
1775                 }
1776         } else if (!strcmp(tone, "ringing"))
1777         {
1778                 switch(options.dsptones) {
1779                 case DSP_AMERICAN: id = TONE_AMERICAN_RINGING; break;
1780                 case DSP_GERMAN: id = TONE_GERMAN_RINGING; break;
1781                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDRINGING; break;
1782                 }
1783         } else if (!strcmp(tone, "ringpbx"))
1784         {
1785                 switch(options.dsptones) {
1786                 case DSP_AMERICAN: id = TONE_AMERICAN_RINGPBX; break;
1787                 case DSP_GERMAN: id = TONE_GERMAN_RINGPBX; break;
1788                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDRINGPBX; break;
1789                 }
1790         } else if (!strcmp(tone, "busy"))
1791         {
1792                 busy:
1793                 switch(options.dsptones) {
1794                 case DSP_AMERICAN: id = TONE_AMERICAN_BUSY; break;
1795                 case DSP_GERMAN: id = TONE_GERMAN_BUSY; break;
1796                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDBUSY; break;
1797                 }
1798         } else if (!strcmp(tone, "release"))
1799         {
1800                 hangup:
1801                 switch(options.dsptones) {
1802                 case DSP_AMERICAN: id = TONE_AMERICAN_HANGUP; break;
1803                 case DSP_GERMAN: id = TONE_GERMAN_HANGUP; break;
1804                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDHANGUP; break;
1805                 }
1806         } else if (!strcmp(tone, "cause_10"))
1807                 goto hangup;
1808         else if (!strcmp(tone, "cause_11"))
1809                 goto busy;
1810         else if (!strcmp(tone, "cause_22"))
1811         {
1812                 switch(options.dsptones) {
1813                 case DSP_AMERICAN: id = TONE_SPECIAL_INFO; break;
1814                 case DSP_GERMAN: id = TONE_GERMAN_GASSENBESETZT; break;
1815                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDBUSY; break;
1816                 }
1817         } else if (!strncmp(tone, "cause_", 6))
1818                 id = TONE_SPECIAL_INFO;
1819         else
1820                 id = TONE_OFF;
1821
1822         /* if we have a tone that is not supported by dsp */
1823         if (id==TONE_OFF && tone[0])
1824                 goto nodsp;
1825
1826         setdsp:
1827         if (p_m_tone != id)
1828         {
1829                 /* set new tone */
1830                 p_m_tone = id;
1831                 PDEBUG(DEBUG_ISDN, "we set tone to id=%d.\n", p_m_tone);
1832                 if (p_m_b_index >= 0)
1833                 if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1834 #ifdef SOCKET_MISDN
1835                         ph_control(p_m_mISDNport, this, p_m_mISDNport->b_socket[p_m_b_index], p_m_tone?TONE_PATT_ON:TONE_PATT_OFF, p_m_tone, "DSP-TONE", p_m_tone);
1836 #else
1837                         ph_control(p_m_mISDNport, this, p_m_mISDNport->b_addr[p_m_b_index], p_m_tone?TONE_PATT_ON:TONE_PATT_OFF, p_m_tone, "DSP-TONE", p_m_tone);
1838 #endif
1839         }
1840         /* turn user-space tones off in cases of no tone OR dsp tone */
1841         Port::set_tone("",NULL);
1842 }
1843
1844
1845 /* MESSAGE_mISDNSIGNAL */
1846 //extern struct message *dddebug;
1847 void PmISDN::message_mISDNsignal(unsigned long epoint_id, int message_id, union parameter *param)
1848 {
1849         switch(param->mISDNsignal.message)
1850         {
1851                 case mISDNSIGNAL_VOLUME:
1852                 if (p_m_tx_gain != param->mISDNsignal.tx_gain)
1853                 {
1854                         p_m_tx_gain = param->mISDNsignal.tx_gain;
1855                         PDEBUG(DEBUG_BCHANNEL, "we change tx-volume to shift=%d.\n", p_m_tx_gain);
1856                         if (p_m_b_index >= 0)
1857                         if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1858 #ifdef SOCKET_MISDN
1859                                 ph_control(p_m_mISDNport, this, p_m_mISDNport->b_socket[p_m_b_index], VOL_CHANGE_TX, p_m_tx_gain, "DSP-TX_GAIN", p_m_tx_gain);
1860 #else
1861                                 ph_control(p_m_mISDNport, this, p_m_mISDNport->b_addr[p_m_b_index], VOL_CHANGE_TX, p_m_tx_gain, "DSP-TX_GAIN", p_m_tx_gain);
1862 #endif
1863                 } else
1864                         PDEBUG(DEBUG_BCHANNEL, "we already have tx-volume shift=%d.\n", p_m_rx_gain);
1865                 if (p_m_rx_gain != param->mISDNsignal.rx_gain)
1866                 {
1867                         p_m_rx_gain = param->mISDNsignal.rx_gain;
1868                         PDEBUG(DEBUG_BCHANNEL, "we change rx-volume to shift=%d.\n", p_m_rx_gain);
1869                         if (p_m_b_index >= 0)
1870                         if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1871 #ifdef SOCKET_MISDN
1872                                 ph_control(p_m_mISDNport, this, p_m_mISDNport->b_socket[p_m_b_index], VOL_CHANGE_RX, p_m_rx_gain, "DSP-RX_GAIN", p_m_rx_gain);
1873 #else
1874                                 ph_control(p_m_mISDNport, this, p_m_mISDNport->b_addr[p_m_b_index], VOL_CHANGE_RX, p_m_rx_gain, "DSP-RX_GAIN", p_m_rx_gain);
1875 #endif
1876                 } else
1877                         PDEBUG(DEBUG_BCHANNEL, "we already have rx-volume shift=%d.\n", p_m_rx_gain);
1878                 break;
1879
1880                 case mISDNSIGNAL_CONF:
1881 //if (dddebug) PDEBUG(DEBUG_ISDN, "dddebug = %d\n", dddebug->type);
1882 //tone          if (!p_m_tone && p_m_conf!=param->mISDNsignal.conf)
1883                 if (p_m_conf != param->mISDNsignal.conf)
1884                 {
1885                         p_m_conf = param->mISDNsignal.conf;
1886                         PDEBUG(DEBUG_BCHANNEL, "we change conference to conf=%d.\n", p_m_conf);
1887                         if (p_m_b_index >= 0)
1888                         if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1889 #ifdef SOCKET_MISDN
1890                                 ph_control(p_m_mISDNport, this, p_m_mISDNport->b_socket[p_m_b_index], (p_m_conf)?CMX_CONF_JOIN:CMX_CONF_SPLIT, p_m_conf, "DSP-CONF", p_m_conf);
1891 #else
1892                                 ph_control(p_m_mISDNport, this, p_m_mISDNport->b_addr[p_m_b_index], (p_m_conf)?CMX_CONF_JOIN:CMX_CONF_SPLIT, p_m_conf, "DSP-CONF", p_m_conf);
1893 #endif
1894                 } else
1895                         PDEBUG(DEBUG_BCHANNEL, "we already have conf=%d.\n", p_m_conf);
1896                 /* we must set, even if currently tone forbids conf */
1897                 p_m_conf = param->mISDNsignal.conf;
1898 //if (dddebug) PDEBUG(DEBUG_ISDN, "dddebug = %d\n", dddebug->type);
1899                 break;
1900
1901                 case mISDNSIGNAL_JOINDATA:
1902                 if (p_m_joindata != param->mISDNsignal.joindata)
1903                 {
1904                         p_m_joindata = param->mISDNsignal.joindata;
1905                         PDEBUG(DEBUG_BCHANNEL, "we change to joindata=%d.\n", p_m_joindata);
1906                 } else
1907                         PDEBUG(DEBUG_BCHANNEL, "we already have joindata=%d.\n", p_m_joindata);
1908                 break;
1909                 
1910                 case mISDNSIGNAL_DELAY:
1911                 if (p_m_delay != param->mISDNsignal.delay)
1912                 {
1913                         p_m_delay = param->mISDNsignal.delay;
1914                         PDEBUG(DEBUG_BCHANNEL, "we change delay mode to delay=%d.\n", p_m_delay);
1915 #ifndef OLD_MISDN
1916                         if (p_m_b_index >= 0)
1917                         if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1918 #ifdef SOCKET_MISDN
1919                                 ph_control(p_m_mISDNport, this, p_m_mISDNport->b_socket[p_m_b_index], p_m_delay?CMX_DELAY:CMX_JITTER, p_m_delay, "DSP-DELAY", p_m_delay);
1920 #else
1921                                 ph_control(p_m_mISDNport, this, p_m_mISDNport->b_addr[p_m_b_index], p_m_delay?CMX_DELAY:CMX_JITTER, p_m_delay, "DSP-DELAY", p_m_delay);
1922 #endif
1923 #endif
1924                 } else
1925                         PDEBUG(DEBUG_BCHANNEL, "we already have delay=%d.\n", p_m_delay);
1926                 break;
1927
1928                 default:
1929                 PERROR("PmISDN(%s) unsupported signal message %d.\n", p_name, param->mISDNsignal.message);
1930         }
1931 }
1932
1933 /* MESSAGE_CRYPT */
1934 void PmISDN::message_crypt(unsigned long epoint_id, int message_id, union parameter *param)
1935 {
1936         struct message *message;
1937
1938         switch(param->crypt.type)
1939         {
1940                 case CC_ACTBF_REQ:           /* activate blowfish */
1941                 p_m_crypt = 1;
1942                 p_m_crypt_key_len = param->crypt.len;
1943                 if (p_m_crypt_key_len > (int)sizeof(p_m_crypt_key))
1944                 {
1945                         PERROR("PmISDN(%s) key too long %d > %d\n", p_name, p_m_crypt_key_len, sizeof(p_m_crypt_key));
1946                         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CRYPT);
1947                         message->param.crypt.type = CC_ERROR_IND;
1948                         message_put(message);
1949                         break;
1950                 }
1951                 memcpy(p_m_crypt_key, param->crypt.data, p_m_crypt_key_len);
1952                 crypt_off:
1953                 PDEBUG(DEBUG_BCHANNEL, "we set encryption to crypt=%d. (0 means OFF)\n", p_m_crypt);
1954                 if (p_m_b_index >= 0)
1955                 if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1956 #ifdef SOCKET_MISDN
1957                         ph_control_block(p_m_mISDNport, this, p_m_mISDNport->b_socket[p_m_b_index], p_m_crypt?BF_ENABLE_KEY:BF_DISABLE, p_m_crypt_key, p_m_crypt_key_len, "DSP-CRYPT", p_m_crypt_key_len);
1958 #else
1959                         ph_control_block(p_m_mISDNport, this, p_m_mISDNport->b_addr[p_m_b_index], p_m_crypt?BF_ENABLE_KEY:BF_DISABLE, p_m_crypt_key, p_m_crypt_key_len, "DSP-CRYPT", p_m_crypt_key_len);
1960 #endif
1961                 break;
1962
1963                 case CC_DACT_REQ:            /* deactivate session encryption */
1964                 p_m_crypt = 0;
1965                 goto crypt_off;
1966                 break;
1967
1968                 case CR_LISTEN_REQ:          /* start listening to messages */
1969                 p_m_crypt_listen = 1;
1970                 p_m_crypt_listen_state = 0;
1971                 break;
1972
1973                 case CR_UNLISTEN_REQ:        /* stop listening to messages */
1974                 p_m_crypt_listen = 0;
1975                 break;
1976
1977                 case CR_MESSAGE_REQ:         /* send message */
1978                 p_m_crypt_msg_len = cryptman_encode_bch(param->crypt.data, param->crypt.len, p_m_crypt_msg, sizeof(p_m_crypt_msg));
1979                 if (!p_m_crypt_msg_len)
1980                 {
1981                         PERROR("PmISDN(%s) message too long %d > %d\n", p_name, param->crypt.len-1, sizeof(p_m_crypt_msg));
1982                         break;
1983                 }
1984                 p_m_crypt_msg_current = 0; /* reset */
1985                 p_m_crypt_msg_loops = 6; /* enable */
1986 #if 0
1987                 /* disable txmix, or we get corrupt data due to audio process */
1988                 if (p_m_txmix && p_m_b_index>=0)
1989                 {
1990                         PDEBUG(DEBUG_BCHANNEL, "for sending CR_MESSAGE_REQ, we reset txmix from txmix=%d.\n", p_m_txmix);
1991 #ifdef SOCKET_MISDN
1992                         ph_control(p_m_mISDNport, this, p_mISDNport->b_socket[p_m_b_index], CMX_MIX_OFF, 0, "DSP-TXMIX", 0);
1993 #else
1994                         ph_control(p_m_mISDNport, this, p_mISDNport->b_addr[p_m_b_index], CMX_MIX_OFF, 0, "DSP-TXMIX", 0);
1995 #endif
1996                 }
1997 #endif
1998                 break;
1999
2000                 default:
2001                 PERROR("PmISDN(%s) unknown crypt message %d\n", p_name, param->crypt.type);
2002         }
2003
2004 }
2005
2006 /*
2007  * endpoint sends messages to the port
2008  */
2009 int PmISDN::message_epoint(unsigned long epoint_id, int message_id, union parameter *param)
2010 {
2011         if (Port::message_epoint(epoint_id, message_id, param))
2012                 return(1);
2013
2014         switch(message_id)
2015         {
2016                 case MESSAGE_DATA: /* tx-data from upper layer */
2017                 txfromup(param->data.data, param->data.len);
2018                 return(1);
2019
2020                 case MESSAGE_mISDNSIGNAL: /* user command */
2021                 PDEBUG(DEBUG_ISDN, "PmISDN(%s) received special ISDN SIGNAL %d.\n", p_name, param->mISDNsignal.message);
2022                 message_mISDNsignal(epoint_id, message_id, param);
2023                 return(1);
2024
2025                 case MESSAGE_CRYPT: /* crypt control command */
2026                 PDEBUG(DEBUG_ISDN, "PmISDN(%s) received encryption command '%d'.\n", p_name, param->crypt.type);
2027                 message_crypt(epoint_id, message_id, param);
2028                 return(1);
2029         }
2030
2031         return(0);
2032 }
2033
2034
2035 /*
2036  * main loop for processing messages from mISDN
2037  */
2038 #ifdef SOCKET_MISDN
2039 int mISDN_handler(void)
2040 {
2041         int ret, work = 0;
2042         struct mISDNport *mISDNport;
2043         class PmISDN *isdnport;
2044         int i;
2045         char buffer[2048+MISDN_HEADER_LEN];
2046         struct mISDNhead *hh = (struct mISDNhead *)buffer;
2047
2048         /* process all ports */
2049         mISDNport = mISDNport_first;
2050         while(mISDNport)
2051         {
2052                 /* process all bchannels */
2053                 i = 0;
2054                 while(i < mISDNport->b_num)
2055                 {
2056                         /* handle port of bchannel */
2057                         isdnport=mISDNport->b_port[i];
2058                         if (isdnport)
2059                         {
2060                                 /* call bridges in user space OR crypto OR recording */
2061                                 if (isdnport->p_m_joindata || isdnport->p_m_crypt_msg_loops || isdnport->p_m_crypt_listen || isdnport->p_record)
2062                                 {
2063                                         /* rx IS required */
2064                                         if (isdnport->p_m_rxoff)
2065                                         {
2066                                                 /* turn on RX */
2067                                                 isdnport->p_m_rxoff = 0;
2068                                                 PDEBUG(DEBUG_BCHANNEL, "%s: receive data is required, so we turn them on\n");
2069                                                 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
2070                                                         ph_control(mISDNport, isdnport, mISDNport->b_socket[isdnport->p_m_b_index], CMX_RECEIVE_ON, 0, "DSP-RXOFF", 0);
2071                                                 return(1);
2072                                         }
2073                                 } else
2074                                 {
2075                                         /* rx NOT required */
2076                                         if (!isdnport->p_m_rxoff)
2077                                         {
2078                                                 /* turn off RX */
2079                                                 isdnport->p_m_rxoff = 1;
2080                                                 PDEBUG(DEBUG_BCHANNEL, "%s: receive data is not required, so we turn them off\n");
2081                                                 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
2082                                                         ph_control(mISDNport, isdnport, mISDNport->b_socket[isdnport->p_m_b_index], CMX_RECEIVE_OFF, 0, "DSP-RXOFF", 1);
2083                                                 return(1);
2084                                         }
2085                                 }
2086                                 /* recording */
2087                                 if (isdnport->p_record)
2088                                 {
2089                                         /* txdata IS required */
2090                                         if (!isdnport->p_m_txdata)
2091                                         {
2092                                                 /* turn on RX */
2093                                                 isdnport->p_m_txdata = 1;
2094                                                 PDEBUG(DEBUG_BCHANNEL, "%s: transmit data is required, so we turn them on\n");
2095                                                 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
2096                                                         ph_control(mISDNport, isdnport, mISDNport->b_socket[isdnport->p_m_b_index], CMX_TXDATA_ON, 0, "DSP-TXDATA", 1);
2097                                                 return(1);
2098                                         }
2099                                 } else
2100                                 {
2101                                         /* txdata NOT required */
2102                                         if (isdnport->p_m_txdata)
2103                                         {
2104                                                 /* turn off RX */
2105                                                 isdnport->p_m_txdata = 0;
2106                                                 PDEBUG(DEBUG_BCHANNEL, "%s: transmit data is not required, so we turn them off\n");
2107                                                 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
2108                                                         ph_control(mISDNport, isdnport, mISDNport->b_socket[isdnport->p_m_b_index], CMX_TXDATA_OFF, 0, "DSP-TXDATA", 0);
2109                                                 return(1);
2110                                         }
2111                                 }
2112                         }
2113
2114                         /* handle message from bchannel */
2115                         if (mISDNport->b_stack[i] > -1)
2116                         {
2117                                 ret = recv(mISDNport->b_stack[i], buffer, sizeof(buffer), 0);
2118                                 if (ret >= MISDN_HEADER_LEN)
2119                                 {
2120                                         work = 1;
2121                                         switch(hh->prim)
2122                                         {
2123                                                 /* we don't care about confirms, we use rx data to sync tx */
2124                                                 case PH_DATA_CONF:
2125                                                 case DL_DATA_CONF:
2126                                                 break;
2127
2128                                                 /* we receive audio data, we respond to it AND we send tones */
2129                                                 case PH_DATA_IND:
2130                                                 case DL_DATA_IND:
2131                                                 case PH_SIGNAL_IND:
2132                                                 case PH_CONTROL_IND:
2133                                                 if (mISDNport->b_port[i])
2134                                                         mISDNport->b_port[i]->bchannel_receive(hh, buffer+MISDN_HEADER_LEN, ret-MISDN_HEADER_LEN);
2135                                                 else
2136                                                         PDEBUG(DEBUG_BCHANNEL, "b-channel is not associated to an ISDNPort (socket %d), ignoring.\n", mISDNport->b_stack[i]);
2137                                                 break;
2138
2139                                                 case PH_ACTIVATE_IND:
2140                                                 case DL_ESTABLISH_IND:
2141                                                 case PH_ACTIVATE_CONF:
2142                                                 case DL_ESTABLISH_CONF:
2143                                                 PDEBUG(DEBUG_BCHANNEL, "DL_ESTABLISH confirm: bchannel is now activated (socket %d).\n", mISDNport->b_socket[i]);
2144                                                 bchannel_event(mISDNport, i, B_EVENT_ACTIVATED);
2145                                                 break;
2146
2147                                                 case PH_DEACTIVATE_IND:
2148                                                 case DL_RELEASE_IND:
2149                                                 case PH_DEACTIVATE_CONF:
2150                                                 case DL_RELEASE_CONF:
2151                                                 PDEBUG(DEBUG_BCHANNEL, "DL_RELEASE confirm: bchannel is now de-activated (socket %d).\n", mISDNport->b_socket[i]);
2152                                                 bchannel_event(mISDNport, i, B_EVENT_DEACTIVATED);
2153                                                 break;
2154
2155                                                 default:
2156                                                 PERROR("child message not handled: prim(0x%x) socket(%d) msg->len(%d)\n", hh->prim, mISDNport->b_socket[i], msg->len);
2157                                         }
2158                                 } else
2159                                 {
2160                                         if (ret < 0 && errno != EWOULDBLOCK)
2161                                                 PERROR("Read from port %d, index %d failed with return code %d\n", mISDNport->portnum, i, ret);
2162                                 }
2163                         }
2164                         
2165                         i++;
2166                 }
2167 #if 0
2168                 if (mISDNport->l1timeout && now>mISDNport->l1timeout)
2169                 { ---}
2170                         PDEBUG(DEBUG_ISDN, "the L1 establish timer expired, we release all pending messages.\n", mISDNport->portnum);
2171                         mISDNport->l1timeout = 0;
2172 #endif
2173
2174                 /* layer 2 establish timer */
2175                 if (mISDNport->l2establish)
2176                 {
2177                         if (now-mISDNport->l2establish > 5)
2178                         {
2179
2180                                 PDEBUG(DEBUG_ISDN, "the L2 establish timer expired, we try to establish the link portnum=%d.\n", mISDNport->portnum);
2181                                 mISDNport->ml3->to_layer2(mISDNport->ml3, DL_ESTABLISH_REQ);
2182                                 l1l2l3_trace_header(mISDNport, NULL, DL_ESTABLISH_REQ, DIRECTION_OUT);
2183                                 end_trace();
2184                                 return(1);
2185                         }
2186                 }
2187
2188
2189                 mISDNport = mISDNport->next;
2190         }
2191
2192         /* if we received at least one b-frame, we will return 1 */
2193         return(work);
2194 }
2195 #else
2196 int mISDN_handler(void)
2197 {
2198         int ret;
2199         struct mISDNport *mISDNport;
2200         class PmISDN *isdnport;
2201         int i;
2202         msg_t *msg;
2203         iframe_t *frm;
2204         msg_t *dmsg;
2205         mISDNuser_head_t *hh;
2206         net_stack_t *nst;
2207
2208         /* the que avoids loopbacks when replying to stack after receiving
2209          * from stack. */
2210         mISDNport = mISDNport_first;
2211         while(mISDNport)
2212         {
2213                 /* process turning on/off rx */
2214                 i = 0;
2215                 while(i < mISDNport->b_num)
2216                 {
2217                         isdnport=mISDNport->b_port[i];
2218                         if (isdnport)
2219                         {
2220                                 /* call bridges in user space OR crypto OR recording */
2221                                 if (isdnport->p_m_joindata || isdnport->p_m_crypt_msg_loops || isdnport->p_m_crypt_listen || isdnport->p_record)
2222                                 {
2223                                         /* rx IS required */
2224                                         if (isdnport->p_m_rxoff)
2225                                         {
2226                                                 /* turn on RX */
2227                                                 isdnport->p_m_rxoff = 0;
2228                                                 PDEBUG(DEBUG_BCHANNEL, "%s: receive data is required, so we turn them on\n");
2229                                                 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
2230                                                         ph_control(mISDNport, isdnport, mISDNport->b_addr[isdnport->p_m_b_index], CMX_RECEIVE_ON, 0, "DSP-RXOFF", 0);
2231                                                 return(1);
2232                                         }
2233                                 } else
2234                                 {
2235                                         /* rx NOT required */
2236                                         if (!isdnport->p_m_rxoff)
2237                                         {
2238                                                 /* turn off RX */
2239                                                 isdnport->p_m_rxoff = 1;
2240                                                 PDEBUG(DEBUG_BCHANNEL, "%s: receive data is not required, so we turn them off\n");
2241                                                 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
2242                                                         ph_control(mISDNport, isdnport, mISDNport->b_addr[isdnport->p_m_b_index], CMX_RECEIVE_OFF, 0, "DSP-RXOFF", 1);
2243                                                 return(1);
2244                                         }
2245                                 }
2246                                 /* recording */
2247                                 if (isdnport->p_record)
2248                                 {
2249                                         /* txdata IS required */
2250                                         if (!isdnport->p_m_txdata)
2251                                         {
2252                                                 /* turn on RX */
2253                                                 isdnport->p_m_txdata = 1;
2254                                                 PDEBUG(DEBUG_BCHANNEL, "%s: transmit data is required, so we turn them on\n");
2255 #ifndef OLD_MISDN
2256                                                 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
2257                                                         ph_control(mISDNport, isdnport, mISDNport->b_addr[isdnport->p_m_b_index], CMX_TXDATA_ON, 0, "DSP-TXDATA", 1);
2258 #endif
2259                                                 return(1);
2260                                         }
2261                                 } else
2262                                 {
2263                                         /* txdata NOT required */
2264                                         if (isdnport->p_m_txdata)
2265                                         {
2266                                                 /* turn off RX */
2267                                                 isdnport->p_m_txdata = 0;
2268                                                 PDEBUG(DEBUG_BCHANNEL, "%s: transmit data is not required, so we turn them off\n");
2269 #ifndef OLD_MISDN
2270                                                 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
2271                                                         ph_control(mISDNport, isdnport, mISDNport->b_addr[isdnport->p_m_b_index], CMX_TXDATA_OFF, 0, "DSP-TXDATA", 0);
2272 #endif
2273                                                 return(1);
2274                                         }
2275                                 }
2276                         }
2277                         i++;
2278                 }
2279 #if 0
2280                 if (mISDNport->l1timeout && now>mISDNport->l1timeout)
2281                 { ---}
2282                         PDEBUG(DEBUG_ISDN, "the L1 establish timer expired, we release all pending messages.\n", mISDNport->portnum);
2283                         mISDNport->l1timeout = 0;
2284 #endif
2285
2286                 if (mISDNport->l2establish)
2287                 {
2288                         if (now-mISDNport->l2establish > 5)
2289                         {
2290                                 if (mISDNport->ntmode)
2291                                 {
2292                                         PDEBUG(DEBUG_ISDN, "the L2 establish timer expired, we try to establish the link NT portnum=%d.\n", mISDNport->portnum);
2293                                         time(&mISDNport->l2establish);
2294                                         /* establish */
2295                                         dmsg = create_l2msg(DL_ESTABLISH | REQUEST, 0, 0);
2296                                         if (mISDNport->nst.manager_l3(&mISDNport->nst, dmsg))
2297                                                 free_msg(dmsg);
2298                                 } else {
2299                                         iframe_t act;
2300
2301                                         PDEBUG(DEBUG_ISDN, "the L2 establish timer expired, we try to establish the link TE portnum=%d.\n", mISDNport->portnum);
2302                                         time(&mISDNport->l2establish);
2303                                         /* establish */
2304                                         act.prim = DL_ESTABLISH | REQUEST; 
2305                                         act.addr = (mISDNport->upper_id & ~LAYER_ID_MASK) | 3 | FLG_MSG_DOWN;
2306                                         act.dinfo = 0;
2307                                         act.len = 0;
2308                                         mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
2309                                 }
2310                                 l1l2l3_trace_header(mISDNport, NULL, DL_ESTABLISH | REQUEST, DIRECTION_OUT);
2311                                 end_trace();
2312                                 return(1);
2313                         }
2314                 }
2315                 if ((dmsg = msg_dequeue(&mISDNport->downqueue)))
2316                 {
2317                         if (mISDNport->ntmode)
2318                         {
2319                                 hh = (mISDNuser_head_t *)dmsg->data;
2320                                 PDEBUG(DEBUG_ISDN, "sending queued NT l3-down-message: prim(0x%x) dinfo(0x%x) msg->len(%d)\n", hh->prim, hh->dinfo, dmsg->len);
2321                                 if (mISDNport->nst.manager_l3(&mISDNport->nst, dmsg))
2322                                         free_msg(dmsg);
2323                         } else
2324                         {
2325                                 frm = (iframe_t *)dmsg->data;
2326                                 frm->addr = mISDNport->upper_id | FLG_MSG_DOWN;
2327                                 frm->len = (dmsg->len) - mISDN_HEADER_LEN;
2328                                 PDEBUG(DEBUG_ISDN, "sending queued TE l3-down-message: prim(0x%x) dinfo(0x%x) msg->len(%d)\n", frm->prim, frm->dinfo, dmsg->len);
2329                                 mISDN_write(mISDNdevice, dmsg->data, dmsg->len, TIMEOUT_1SEC);
2330                                 free_msg(dmsg);
2331                         }
2332                         return(1);
2333                 }
2334                 mISDNport = mISDNport->next;
2335         } 
2336
2337         /* no device, no read */
2338         if (mISDNdevice < 0)
2339                 return(0);
2340
2341         /* get message from kernel */
2342         if (!(msg = alloc_msg(MAX_MSG_SIZE)))
2343                 return(1);
2344         ret = mISDN_read(mISDNdevice, msg->data, MAX_MSG_SIZE, 0);
2345         if (ret < 0)
2346         {
2347                 free_msg(msg);
2348                 if (errno == EAGAIN)
2349                         return(0);
2350                 FATAL("Failed to do mISDN_read()\n");
2351         }
2352         if (!ret)
2353         {
2354                 free_msg(msg);
2355 //              printf("%s: ERROR: mISDN_read() returns nothing\n");
2356                 return(0);
2357         }
2358         msg->len = ret;
2359         frm = (iframe_t *)msg->data;
2360
2361         /* global prim */
2362         switch(frm->prim)
2363         {
2364                 case MGR_DELLAYER | CONFIRM:
2365                 case MGR_INITTIMER | CONFIRM:
2366                 case MGR_ADDTIMER | CONFIRM:
2367                 case MGR_DELTIMER | CONFIRM:
2368                 case MGR_REMOVETIMER | CONFIRM:
2369                 free_msg(msg);
2370                 return(1);
2371         }
2372
2373         /* handle timer events from mISDN for NT-stack
2374          * note: they do not associate with a stack */
2375         if (frm->prim == (MGR_TIMER | INDICATION))
2376         {
2377                 itimer_t *it;
2378
2379                 /* find mISDNport */
2380                 mISDNport = mISDNport_first;
2381                 while(mISDNport)
2382                 {
2383                         /* nt mode only */
2384                         if (mISDNport->ntmode)
2385                         {
2386                                 it = mISDNport->nst.tlist;
2387                                 /* find timer */
2388                                 while(it)
2389                                 {
2390                                         if (it->id == (int)frm->addr)
2391                                                 break;
2392                                         it = it->next;
2393                                 }
2394                                 if (it)
2395                                         break;
2396                         }
2397                         mISDNport = mISDNport->next;
2398                 }
2399                 if (mISDNport)
2400                 {
2401                         mISDN_write_frame(mISDNdevice, msg->data, mISDNport->upper_id | FLG_MSG_DOWN,
2402                                 MGR_TIMER | RESPONSE, 0, 0, NULL, TIMEOUT_1SEC);
2403
2404                         PDEBUG(DEBUG_ISDN, "timer-indication port %d it=%p\n", mISDNport->portnum, it);
2405                         test_and_clear_bit(FLG_TIMER_RUNING, (long unsigned int *)&it->Flags);
2406                         ret = it->function(it->data);
2407                 } else
2408                 {
2409                         PDEBUG(DEBUG_ISDN, "timer-indication not handled\n");
2410                 }
2411                 goto out;
2412         }
2413
2414         /* find the mISDNport that belongs to the stack */
2415         mISDNport = mISDNport_first;
2416         while(mISDNport)
2417         {
2418                 if ((frm->addr&MASTER_ID_MASK) == (unsigned int)(mISDNport->upper_id&MASTER_ID_MASK))
2419                         break;
2420                 mISDNport = mISDNport->next;
2421         } 
2422         if (!mISDNport)
2423         {
2424                 PERROR("message belongs to no mISDNport: prim(0x%x) addr(0x%x) msg->len(%d)\n", frm->prim, frm->addr, msg->len);
2425                 goto out;
2426         }
2427
2428         /* master stack */
2429         if (!(frm->addr&FLG_CHILD_STACK))
2430         {
2431                 /* d-message */
2432                 switch(frm->prim)
2433                 {
2434                         case MGR_SHORTSTATUS | INDICATION:
2435                         case MGR_SHORTSTATUS | CONFIRM:
2436                         switch(frm->dinfo) {
2437                                 case SSTATUS_L1_ACTIVATED:
2438                                 l1l2l3_trace_header(mISDNport, NULL, PH_ACTIVATE | (frm->prim & 0x3), DIRECTION_IN);
2439                                 end_trace();
2440                                 goto ss_act;
2441                                 case SSTATUS_L1_DEACTIVATED:
2442                                 l1l2l3_trace_header(mISDNport, NULL, PH_DEACTIVATE | (frm->prim & 0x3), DIRECTION_IN);
2443                                 end_trace();
2444                                 goto ss_deact;
2445                                 case SSTATUS_L2_ESTABLISHED:
2446                                 l1l2l3_trace_header(mISDNport, NULL, DL_ESTABLISH | (frm->prim & 0x3), DIRECTION_IN);
2447                                 end_trace();
2448                                 goto ss_estab;
2449                                 case SSTATUS_L2_RELEASED:
2450                                 l1l2l3_trace_header(mISDNport, NULL, DL_RELEASE | (frm->prim & 0x3), DIRECTION_IN);
2451                                 end_trace();
2452                                 goto ss_rel;
2453                         }
2454                         break;
2455
2456                         case PH_ACTIVATE | CONFIRM:
2457                         case PH_ACTIVATE | INDICATION:
2458                         l1l2l3_trace_header(mISDNport, NULL, frm->prim, DIRECTION_IN);
2459                         end_trace();
2460                         if (mISDNport->ntmode)
2461                         {
2462                                 mISDNport->l1link = 1;
2463                                 setup_queue(mISDNport, 1);
2464                                 goto l1_msg;
2465                         }
2466                         ss_act:
2467                         mISDNport->l1link = 1;
2468                         setup_queue(mISDNport, 1);
2469                         break;
2470
2471                         case PH_DEACTIVATE | CONFIRM:
2472                         case PH_DEACTIVATE | INDICATION:
2473                         l1l2l3_trace_header(mISDNport, NULL, frm->prim, DIRECTION_IN);
2474                         end_trace();
2475                         if (mISDNport->ntmode)
2476                         {
2477                                 mISDNport->l1link = 0;
2478                                 setup_queue(mISDNport, 0);
2479                                 goto l1_msg;
2480                         }
2481                         ss_deact:
2482                         mISDNport->l1link = 0;
2483                         setup_queue(mISDNport, 0);
2484                         break;
2485
2486                         case PH_CONTROL | CONFIRM:
2487                         case PH_CONTROL | INDICATION:
2488                         PDEBUG(DEBUG_ISDN, "Received PH_CONTROL for port %d (%s).\n", mISDNport->portnum, mISDNport->ifport->interface->name);
2489                         break;
2490
2491                         case DL_ESTABLISH | INDICATION:
2492                         case DL_ESTABLISH | CONFIRM:
2493                         l1l2l3_trace_header(mISDNport, NULL, frm->prim, DIRECTION_IN);
2494                         end_trace();
2495                         if (!mISDNport->ntmode) break; /* !!!!!!!!!!!!!!!! */
2496                         ss_estab:
2497                         if (mISDNport->l2establish)
2498                         {
2499                                 mISDNport->l2establish = 0;
2500                                 PDEBUG(DEBUG_ISDN, "the link became active before l2establish timer expiry.\n");
2501                         }
2502                         mISDNport->l2link = 1;
2503                         break;
2504
2505                         case DL_RELEASE | INDICATION:
2506                         case DL_RELEASE | CONFIRM:
2507                         l1l2l3_trace_header(mISDNport, NULL, frm->prim, DIRECTION_IN);
2508                         end_trace();
2509                         if (!mISDNport->ntmode) break; /* !!!!!!!!!!!!!!!! */
2510                         ss_rel:
2511                         mISDNport->l2link = 0;
2512                         if (mISDNport->ptp)
2513                         {
2514                                 time(&mISDNport->l2establish);
2515                                 PDEBUG(DEBUG_ISDN, "because we are ptp, we set a l2establish timer.\n");
2516                         }
2517                         break;
2518
2519                         default:
2520                         l1_msg:
2521                         PDEBUG(DEBUG_STACK, "GOT d-msg from %s port %d prim 0x%x dinfo 0x%x addr 0x%x\n", (mISDNport->ntmode)?"NT":"TE", mISDNport->portnum, frm->prim, frm->dinfo, frm->addr);
2522                         if (frm->dinfo==(signed long)0xffffffff && frm->prim==(PH_DATA|CONFIRM))
2523                         {
2524                                 PERROR("SERIOUS BUG, dinfo == 0xffffffff, prim == PH_DATA | CONFIRM !!!!\n");
2525                         }
2526                         /* d-message */
2527                         if (mISDNport->ntmode)
2528                         {
2529                                 /* l1-data enters the nt-mode library */
2530                                 nst = &mISDNport->nst;
2531                                 if (nst->l1_l2(nst, msg))
2532                                         free_msg(msg);
2533                                 return(1);
2534                         } else
2535                         {
2536                                 /* l3-data is sent to pbx */
2537                                 if (stack2manager_te(mISDNport, msg))
2538                                         free_msg(msg);
2539                                 return(1);
2540                         }
2541                 }
2542         } else
2543         /* child stack */
2544         {
2545                 /* b-message */
2546                 switch(frm->prim)
2547                 {
2548                         /* we don't care about confirms, we use rx data to sync tx */
2549                         case PH_DATA | CONFIRM:
2550                         case DL_DATA | CONFIRM:
2551                         break;
2552
2553                         /* we receive audio data, we respond to it AND we send tones */
2554                         case PH_DATA | INDICATION:
2555                         case DL_DATA | INDICATION:
2556                         case PH_CONTROL | INDICATION:
2557                         case PH_SIGNAL | INDICATION:
2558                         i = 0;
2559                         while(i < mISDNport->b_num)
2560                         {
2561                                 if ((unsigned int)(mISDNport->b_addr[i]&STACK_ID_MASK) == (frm->addr&STACK_ID_MASK))
2562                                         break;
2563                                 i++;
2564                         }
2565                         if (i == mISDNport->b_num)
2566                         {
2567                                 PERROR("unhandled b-message (prim 0x%x address 0x%x).\n", frm->prim, frm->addr);
2568                                 break;
2569                         }
2570                         if (mISDNport->b_port[i])
2571                         {
2572 //PERROR("port sech: %s data\n", mISDNport->b_port[i]->p_name);
2573                                 mISDNport->b_port[i]->bchannel_receive(frm);
2574                         } else
2575                                 PDEBUG(DEBUG_BCHANNEL, "b-channel is not associated to an ISDNPort (address 0x%x), ignoring.\n", frm->addr);
2576                         break;
2577
2578                         case PH_ACTIVATE | INDICATION:
2579                         case DL_ESTABLISH | INDICATION:
2580                         case PH_ACTIVATE | CONFIRM:
2581                         case DL_ESTABLISH | CONFIRM:
2582                         PDEBUG(DEBUG_BCHANNEL, "DL_ESTABLISH confirm: bchannel is now activated (address 0x%x).\n", frm->addr);
2583                         i = 0;
2584                         while(i < mISDNport->b_num)
2585                         {
2586                                 if ((unsigned int)(mISDNport->b_addr[i]&STACK_ID_MASK) == (frm->addr&STACK_ID_MASK))
2587                                         break;
2588                                 i++;
2589                         }
2590                         if (i == mISDNport->b_num)
2591                         {
2592                                 PERROR("unhandled b-establish (prim 0x%x address 0x%x).\n", frm->prim, frm->addr);
2593                                 break;
2594                         }
2595                         bchannel_event(mISDNport, i, B_EVENT_ACTIVATED);
2596                         break;
2597
2598                         case PH_DEACTIVATE | INDICATION:
2599                         case DL_RELEASE | INDICATION:
2600                         case PH_DEACTIVATE | CONFIRM:
2601                         case DL_RELEASE | CONFIRM:
2602                         PDEBUG(DEBUG_BCHANNEL, "DL_RELEASE confirm: bchannel is now de-activated (address 0x%x).\n", frm->addr);
2603                         i = 0;
2604                         while(i < mISDNport->b_num)
2605                         {
2606                                 if ((unsigned int)(mISDNport->b_addr[i]&STACK_ID_MASK) == (frm->addr&STACK_ID_MASK))
2607                                         break;
2608                                 i++;
2609                         }
2610                         if (i == mISDNport->b_num)
2611                         {
2612                                 PERROR("unhandled b-release (prim 0x%x address 0x%x).\n", frm->prim, frm->addr);
2613                                 break;
2614                         }
2615                         bchannel_event(mISDNport, i, B_EVENT_DEACTIVATED);
2616                         break;
2617
2618                         default:
2619                         PERROR("child message not handled: prim(0x%x) addr(0x%x) msg->len(%d)\n", frm->prim, frm->addr, msg->len);
2620                 }
2621         }
2622
2623         out:
2624         free_msg(msg);
2625         return(1);
2626 }
2627 #endif
2628
2629 #ifdef SOCKET_MISDN
2630 int do_layer3(struct mlayer3 *ml3, unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
2631 {
2632         struct mISDNport *mISDNport = ml3->private;
2633
2634         if (cmd == MT_ASSIGN)
2635         {
2636                 ueberdenken!!!
2637         }
2638         
2639         /* lock LCR */
2640         achtung MT_ASSIGN kommt hier an
2641         lock it baby
2642
2643         /* d-message */
2644         switch(cmd)
2645         {
2646                 case MGR_SHORTSTATUS_IND:
2647                 case MGR_SHORTSTATUS_CONF:
2648                 switch(frm->dinfo) {
2649                         case SSTATUS_L1_ACTIVATED:
2650                         l1l2l3_trace_header(mISDNport, NULL, PH_ACTIVATE_IND, DIRECTION_IN);
2651                         end_trace();
2652                         goto ss_act;
2653                         case SSTATUS_L1_DEACTIVATED:
2654                         l1l2l3_trace_header(mISDNport, NULL, PH_DEACTIVATE_IND, DIRECTION_IN);
2655                         end_trace();
2656                         goto ss_deact;
2657                         case SSTATUS_L2_ESTABLISHED:
2658                         l1l2l3_trace_header(mISDNport, NULL, DL_ESTABLISH_IND, DIRECTION_IN);
2659                         end_trace();
2660                         goto ss_estab;
2661                         case SSTATUS_L2_RELEASED:
2662                         l1l2l3_trace_header(mISDNport, NULL, DL_RELEASE_IND, DIRECTION_IN);
2663                         end_trace();
2664                         goto ss_rel;
2665                 }
2666                 break;
2667
2668                 case PH_ACTIVATE_CONF:
2669                 case PH_ACTIVATE_IND:
2670                 l1l2l3_trace_header(mISDNport, NULL, cmd, DIRECTION_IN);
2671                 end_trace();
2672                 ss_act:
2673                 mISDNport->l1link = 1;
2674 #if 0
2675                 if (mISDNport->ntmode)
2676                         setup_queue(mISDNport, 1);
2677 #endif
2678                 break;
2679
2680                 case PH_DEACTIVATE | CONFIRM:
2681                 case PH_DEACTIVATE | INDICATION:
2682                 l1l2l3_trace_header(mISDNport, NULL, cmd, DIRECTION_IN);
2683                 end_trace();
2684                 ss_deact:
2685                 mISDNport->l1link = 0;
2686 raus mit der setup-queue, da dies im stack geschieht
2687 #if 0
2688                 if (mISDNport->ntmode)
2689                         setup_queue(mISDNport, 0);
2690 #endif
2691                 break;
2692
2693                 case PH_CONTROL_CONFIRM:
2694                 case PH_CONTROL_INDICATION:
2695                 PDEBUG(DEBUG_ISDN, "Received PH_CONTROL for port %d (%s).\n", mISDNport->portnum, mISDNport->ifport->interface->name);
2696                 break;
2697
2698                 case DL_ESTABLISH_IND:
2699                 case DL_ESTABLISH_CONF:
2700                 l1l2l3_trace_header(mISDNport, NULL, cmd, DIRECTION_IN);
2701                 end_trace();
2702                 if (!mISDNport->ntmode) break; /* !!!!!!!!!!!!!!!! */
2703                 ss_estab:
2704                 if (mISDNport->l2establish)
2705                 {
2706                         mISDNport->l2establish = 0;
2707                         PDEBUG(DEBUG_ISDN, "the link became active before l2establish timer expiry.\n");
2708                 }
2709                 mISDNport->l2link = 1;
2710                 break;
2711
2712                 case DL_RELEASE_IND:
2713                 case DL_RELEASE_CONF:
2714                 l1l2l3_trace_header(mISDNport, NULL, cmd, DIRECTION_IN);
2715                 end_trace();
2716                 ss_rel:
2717                 mISDNport->l2link = 0;
2718                 if (mISDNport->ptp)
2719                 {
2720                         time(&mISDNport->l2establish);
2721                         PDEBUG(DEBUG_ISDN, "because we are ptp, we set a l2establish timer.\n");
2722                 }
2723                 break;
2724
2725                 default:
2726                 /* l3-data is sent to LCR */
2727                 message_from_mlayer3(mISDNport, cmd, pid, l3m);
2728         }
2729
2730         /* unlock LCR */
2731         unlock it baby
2732
2733         /* free message */
2734         if (l3m)
2735                 free_l3_msg(l3m);
2736         return(0);
2737
2738 }
2739 #endif
2740
2741
2742 /*
2743  * global function to add a new card (port)
2744  */
2745 struct mISDNport *mISDNport_open(int port, int ptp, int ptmp, int force_nt, struct interface *interface)
2746 {
2747         int ret;
2748         unsigned char buff[1025];
2749         iframe_t *frm = (iframe_t *)buff;
2750         struct mISDNport *mISDNport, **mISDNportp;
2751         int i, cnt;
2752         int pri, bri, ports;
2753         int nt, te;
2754 #ifdef SOCKET_MISDN
2755         struct mlayer3 *ml3;
2756         struct mISDN_devinfo devinfo;
2757
2758         ret = ioctl(mISDNsocket, IMGETCOUNT, &cnt);
2759         if (ret < 0)
2760         {
2761                 fprintf(stderr, "Cannot get number of mISDN devices. (ioctl IMGETCOUNT failed ret=%d)\n", ret);
2762                 return(NULL);
2763         }
2764 #else
2765 //      interface_info_t ii;
2766         net_stack_t *nst;
2767         manager_t *mgr;
2768         layer_info_t li;
2769         stack_info_t *stinf;
2770
2771         /* query port's requirements */
2772         cnt = mISDN_get_stack_count(mISDNdevice);
2773 #endif
2774
2775         if (cnt <= 0)
2776         {
2777                 PERROR_RUNTIME("Found no card. Please be sure to load card drivers.\n");
2778                 return(NULL);
2779         }
2780         if (port>cnt || port<1)
2781         {
2782                 PERROR_RUNTIME("Port (%d) given at 'ports' (options.conf) is out of existing port range (%d-%d)\n", port, 1, cnt);
2783                 return(NULL);
2784         }
2785
2786         pri = bri = ports = nt = te = 0;
2787 #ifdef SOCKET_MISDN
2788         devinfo.id = port - 1;
2789         ret = ioctl(socket, IMGETDEVINFO, &devinfo);
2790         if (ret <= 0)
2791         {
2792                 PERROR_RUNTIME("Cannot get device information for port %d. (ioctl IMGETDEVINFO failed ret=%d)\n", i, ret);
2793                 break;
2794         }
2795         /* output the port info */
2796         if (devinfo.Dprotocols & (1 << ISDN_P_TE_S0))
2797         {
2798                 bri = 1;
2799                 te = 1;
2800         }
2801         if (devinfo.Dprotocols & (1 << ISDN_P_NT_S0))
2802         {
2803                 bri = 1;
2804                 nt = 1;
2805         }
2806 #ifdef ISDN_P_TE_E1
2807         if (devinfo.Dprotocols & (1 << ISDN_P_TE_E1))
2808         {
2809                 pri = 1;
2810                 te = 1;
2811         }
2812 #endif
2813 #ifdef ISDN_P_NT_E1
2814         if (devinfo.Dprotocols & (1 << ISDN_P_NT_E1))
2815         {
2816                 pri = 1;
2817                 nt = 1;
2818         }
2819 #endif
2820 #ifdef ISDN_P_FXS
2821         if (devinfo.Dprotocols & (1 << ISDN_P_FXS))
2822         {
2823                 pots = 1;
2824                 te = 1;
2825         }
2826 #endif
2827 #ifdef ISDN_P_FXO
2828         if (devinfo.Dprotocols & (1 << ISDN_P_FXO))
2829         {
2830                 pots = 1;
2831                 nt = 1;
2832         }
2833 #endif
2834         if (force_nt && !nt)
2835         {
2836                 PERROR_RUNTIME("Port %d does not support NT-mode.\n", port);
2837                 return(NULL);
2838         }
2839         if (bri && pri)
2840         {
2841                 PERROR_RUNTIME("Port %d supports BRI and PRI?? What kind of controller is that?. (Can't use this!)\n", port);
2842                 return(NULL);
2843         }
2844         if (pots && !bri && !pri)
2845         {
2846                 PERROR_RUNTIME("Port %d supports POTS, LCR does not!\n", port);
2847                 return(NULL);
2848         }
2849         if (!bri && !pri)
2850         {
2851                 PERROR_RUNTIME("Port %d does not support BRI nor PRI!\n", port);
2852                 return(NULL);
2853         }
2854         if (!nt && !te)
2855         {
2856                 PERROR_RUNTIME("Port %d does not support NT-mode nor TE-mode!\n", port);
2857                 return(NULL);
2858         }
2859         /* force nt, by turning off TE */
2860         if (force_nt && nt)
2861                 te = 0;
2862         /* if TE an NT is supported (and not forced to NT), turn off NT */
2863         if (te && nt)
2864                 nt = 0;
2865 #else
2866         ret = mISDN_get_stack_info(mISDNdevice, port, buff, sizeof(buff));
2867         if (ret < 0)
2868         {
2869                 PERROR_RUNTIME("Cannot get stack info for port %d (ret=%d)\n", port, ret);
2870                 return(NULL);
2871         }
2872         stinf = (stack_info_t *)&frm->data.p;
2873         switch(stinf->pid.protocol[0] & ~ISDN_PID_FEATURE_MASK)
2874         {
2875                 case ISDN_PID_L0_TE_S0:
2876                 PDEBUG(DEBUG_ISDN, "TE-mode BRI S/T interface line\n");
2877                 break;
2878                 case ISDN_PID_L0_NT_S0:
2879                 PDEBUG(DEBUG_ISDN, "NT-mode BRI S/T interface port\n");
2880                 nt = 1;
2881                 break;
2882                 case ISDN_PID_L0_TE_E1:
2883                 PDEBUG(DEBUG_ISDN, "TE-mode PRI E1  interface line\n");
2884                 pri = 1;
2885                 break;
2886                 case ISDN_PID_L0_NT_E1:
2887                 PDEBUG(DEBUG_ISDN, "LT-mode PRI E1  interface port\n");
2888                 pri = 1;
2889                 nt = 1;
2890                 break;
2891                 default:
2892                 PERROR_RUNTIME("unknown port(%d) type 0x%08x\n", port, stinf->pid.protocol[0]);
2893                 return(NULL);
2894         }
2895         if (nt)
2896         {
2897                 /* NT */
2898                 if (stinf->pid.protocol[1] == 0)
2899                 {
2900                         PERROR_RUNTIME("Given port %d: Missing layer 1 NT-mode protocol.\n", port);
2901                         return(NULL);
2902                 }
2903                 if (stinf->pid.protocol[2])
2904                 {
2905                         PERROR_RUNTIME("Given port %d: Layer 2 protocol 0x%08x is detected, but not allowed for NT lib.\n", port, stinf->pid.protocol[2]);
2906                         return(NULL);
2907                 }
2908         }
2909         if (te)
2910         {
2911                 /* TE */
2912                 if (stinf->pid.protocol[1] == 0)
2913                 {
2914                         PERROR_RUNTIME("Given port %d: Missing layer 1 protocol.\n", port);
2915                         return(NULL);
2916                 }
2917                 if (stinf->pid.protocol[2] == 0)
2918                 {
2919                         PERROR_RUNTIME("Given port %d: Missing layer 2 protocol.\n", port);
2920                         return(NULL);
2921                 }
2922                 if (stinf->pid.protocol[3] == 0)
2923                 {
2924                         PERROR_RUNTIME("Given port %d: Missing layer 3 protocol.\n", port);
2925                         return(NULL);
2926                 } else
2927                 {
2928                         switch(stinf->pid.protocol[3] & ~ISDN_PID_FEATURE_MASK)
2929                         {
2930                                 case ISDN_PID_L3_DSS1USER:
2931                                 break;
2932
2933                                 default:
2934                                 PERROR_RUNTIME("Given port %d: own protocol 0x%08x", port,stinf->pid.protocol[3]);
2935                                 return(NULL);
2936                         }
2937                 }
2938                 if (stinf->pid.protocol[4])
2939                 {
2940                         PERROR_RUNTIME("Given port %d: Layer 4 protocol not allowed.\n", port);
2941                         return(NULL);
2942                 }
2943         }
2944 #endif
2945
2946         /* add mISDNport structure */
2947         mISDNportp = &mISDNport_first;
2948         while(*mISDNportp)
2949                 mISDNportp = &((*mISDNportp)->next);
2950         mISDNport = (struct mISDNport *)MALLOC(sizeof(struct mISDNport));
2951         pmemuse++;
2952         *mISDNportp = mISDNport;
2953
2954         /* allocate ressources of port */
2955 #ifdef SOCKET_MISDN
2956         /* open layer 3 */
2957         protocol = (nt)?L3_PROTOCOL_DSS1_USER:L3_PROTOCOL_DSS1_NETWORK;
2958         prop = 0;
2959         if (ptp)
2960                prop |= FLG_PTP;
2961         if (ptmp && pri)
2962                prop |= FLG_FORCE_PTMP;
2963         mISDNport->ml3 = open_layer3(port-1, protocol, prop , do_dchannel, mISDNport);
2964         if (!mISDNport->ml3)
2965         {
2966                 PERROR_RUNTIME("Cannot get layer(%d) id of port %d\n", nt?2:4, port);
2967                 return(NULL);
2968         }
2969
2970 #if 0
2971         /* if ntmode, establish L1 to send the tei removal during start */
2972         if (mISDNport->ntmode)
2973         {
2974                 iframe_t act;
2975                 /* L1 */
2976                 act.prim = PH_ACTIVATE | REQUEST; 
2977                 act.addr = mISDNport->upper_id | FLG_MSG_DOWN;
2978                 printf("UPPER ID 0x%x, addr 0x%x\n",mISDNport->upper_id, act.addr);
2979                 act.dinfo = 0;
2980                 act.len = 0;
2981                 mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
2982                 usleep(10000); /* to be sure, that l1 is up */
2983         }
2984 #endif
2985
2986         SCPY(mISDNport->name, devinfo.name);
2987         mISDNport->b_num = devinfo.nrbchan;
2988 #else
2989         msg_queue_init(&mISDNport->downqueue);
2990         mISDNport->d_stid = stinf->id;
2991         PDEBUG(DEBUG_ISDN, "d_stid = 0x%x.\n", mISDNport->d_stid);
2992         if ((stinf->pid.protocol[2]&ISDN_PID_L2_DF_PTP) || (nt&&ptp) || pri)
2993         {
2994                 PDEBUG(DEBUG_ISDN, "Port is point-to-point.\n");
2995                 ptp = 1;
2996                 if (ptmp && nt)
2997                 {
2998                         PDEBUG(DEBUG_ISDN, "Port is forced to point-to-multipoint.\n");
2999                         ptp = 0;
3000                 }
3001         }
3002
3003         /* create layer intance */
3004         memset(&li, 0, sizeof(li));
3005         UCPY(&li.name[0], (nt)?"net l2":"pbx l4");
3006         li.object_id = -1;
3007         li.extentions = 0;
3008         li.pid.protocol[nt?2:4] = (nt)?ISDN_PID_L2_LAPD_NET:ISDN_PID_L4_CAPI20;
3009         li.pid.layermask = ISDN_LAYER((nt?2:4));
3010         li.st = mISDNport->d_stid;
3011         ret = mISDN_new_layer(mISDNdevice, &li);
3012         if (ret)
3013         {
3014                 PERROR("Cannot add layer %d of port %d (ret %d)\n", nt?2:4, port, ret);
3015                 closeport:
3016                 mISDNport_close(mISDNport);
3017                 return(NULL);
3018         }
3019         mISDNport->upper_id = li.id;
3020         ret = mISDN_register_layer(mISDNdevice, mISDNport->d_stid, mISDNport->upper_id);
3021         if (ret)
3022         {
3023                 PERROR("Cannot register layer %d of port %d\n", nt?2:4, port);
3024                 goto closeport;
3025         }
3026         mISDNport->lower_id = mISDN_get_layerid(mISDNdevice, mISDNport->d_stid, nt?1:3); // id of lower layer (nt=1, te=3)
3027         if (mISDNport->lower_id < 0)
3028         {
3029                 PERROR("Cannot get layer(%d) id of port %d\n", nt?1:3, port);
3030                 goto closeport;
3031         }
3032         mISDNport->upper_id = mISDN_get_layerid(mISDNdevice, mISDNport->d_stid, nt?2:4); // id of uppermost layer (nt=2, te=4)
3033         if (mISDNport->upper_id < 0)
3034         {
3035                 PERROR("Cannot get layer(%d) id of port %d\n", nt?2:4, port);
3036                 goto closeport;
3037         }
3038         PDEBUG(DEBUG_ISDN, "Layer %d of port %d added.\n", nt?2:4, port);
3039
3040         /* if ntmode, establish L1 to send the tei removal during start */
3041         if (mISDNport->ntmode)
3042         {
3043                 iframe_t act;
3044                 /* L1 */
3045                 act.prim = PH_ACTIVATE | REQUEST; 
3046                 act.addr = mISDNport->upper_id | FLG_MSG_DOWN;
3047                 printf("UPPER ID 0x%x, addr 0x%x\n",mISDNport->upper_id, act.addr);
3048                 act.dinfo = 0;
3049                 act.len = 0;
3050                 mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
3051                 usleep(10000); /* to be sure, that l1 is up */
3052         }
3053
3054         /* create nst (nt-mode only) */
3055         if (nt)
3056         {
3057                 mgr = &mISDNport->mgr;
3058                 nst = &mISDNport->nst;
3059
3060                 mgr->nst = nst;
3061                 nst->manager = mgr;
3062
3063                 nst->l3_manager = stack2manager_nt; /* messages from nt-mode */
3064                 nst->device = mISDNdevice;
3065                 nst->cardnr = port;
3066                 nst->d_stid = mISDNport->d_stid;
3067
3068                 nst->feature = FEATURE_NET_HOLD;
3069                 if (ptp)
3070                         nst->feature |= FEATURE_NET_PTP;
3071                 if (pri)
3072                         nst->feature |= FEATURE_NET_CRLEN2 | FEATURE_NET_EXTCID;
3073 #if 0
3074                 i = 0;
3075                 while(i < mISDNport->b_num)
3076                 {
3077                         nst->b_stid[i] = mISDNport->b_stid[i];
3078                         i++;
3079                 }
3080 #endif
3081                 nst->l1_id = mISDNport->lower_id;
3082                 nst->l2_id = mISDNport->upper_id;
3083
3084                 /* phd */       
3085                 msg_queue_init(&nst->down_queue);
3086
3087                 Isdnl2Init(nst);
3088                 Isdnl3Init(nst);
3089         }
3090
3091         mISDNport->b_num = stinf->childcnt;
3092 #endif
3093         mISDNport->portnum = port;
3094         mISDNport->ntmode = nt;
3095         mISDNport->pri = pri;
3096         mISDNport->ptp = ptp;
3097         PDEBUG(DEBUG_ISDN, "Port has %d b-channels.\n", mISDNport->b_num);
3098         i = 0;
3099         while(i < mISDNport->b_num)
3100         {
3101                 mISDNport->b_state[i] = B_STATE_IDLE;
3102 #ifdef SOCKET_MISDN
3103                 mISDNport->b_socket = -1;
3104 #else
3105                 mISDNport->b_stid[i] = stinf->child[i];
3106                 PDEBUG(DEBUG_ISDN, "b_stid[%d] = 0x%x.\n", i, mISDNport->b_stid[i]);
3107 #endif
3108                 i++;
3109         }
3110
3111         /* if te-mode, query state link */
3112         if (!mISDNport->ntmode)
3113         {
3114                 iframe_t act;
3115                 /* L2 */
3116                 PDEBUG(DEBUG_ISDN, "sending short status request for port %d.\n", port);
3117                 act.prim = MGR_SHORTSTATUS | REQUEST; 
3118                 act.addr = mISDNport->upper_id | MSG_BROADCAST;
3119                 act.dinfo = SSTATUS_BROADCAST_BIT | SSTATUS_ALL;
3120                 act.len = 0;
3121                 mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
3122         }
3123         /* if ptp AND te-mode, pull up the link */
3124         if (mISDNport->ptp && !mISDNport->ntmode)
3125         {
3126                 iframe_t act;
3127                 /* L2 */
3128                 act.prim = DL_ESTABLISH | REQUEST; 
3129                 act.addr = (mISDNport->upper_id & ~LAYER_ID_MASK) | 4 | FLG_MSG_DOWN;
3130                 act.dinfo = 0;
3131                 act.len = 0;
3132                 mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
3133         }
3134         /* if ptp AND nt-mode, pull up the link */
3135         if (mISDNport->ptp && mISDNport->ntmode)
3136         {
3137                 msg_t *dmsg;
3138                 /* L2 */
3139                 dmsg = create_l2msg(DL_ESTABLISH | REQUEST, 0, 0);
3140                 if (mISDNport->nst.manager_l3(&mISDNport->nst, dmsg))
3141                         free_msg(dmsg);
3142         }
3143         /* initially, we assume that the link is down, exept for nt-ptmp */
3144         mISDNport->l2link = (mISDNport->ntmode && !mISDNport->ptp)?1:0;
3145
3146         PDEBUG(DEBUG_BCHANNEL, "using 'mISDN_dsp.o' module\n");
3147
3148         start_trace(mISDNport->portnum,
3149                     interface,
3150                     NULL,
3151                     NULL,
3152                     DIRECTION_NONE,
3153                     CATEGORY_CH,
3154                     0,
3155                     "PORT (open)");
3156         add_trace("channels", NULL, "%d", mISDNport->b_num);
3157         end_trace();
3158         return(mISDNport);
3159 }
3160
3161
3162 /*
3163  * function to free ALL cards (ports)
3164  */
3165 void mISDNport_close_all(void)
3166 {
3167         /* free all ports */
3168         while(mISDNport_first)
3169                 mISDNport_close(mISDNport_first);
3170 }
3171
3172 /*
3173  * free only one port
3174  */
3175 void mISDNport_close(struct mISDNport *mISDNport)
3176 {
3177         struct mISDNport **mISDNportp;
3178         class Port *port;
3179         class PmISDN *isdnport;
3180         net_stack_t *nst;
3181         unsigned char buf[32];
3182         int i;
3183
3184         /* remove all port instance that are linked to this mISDNport */
3185         port = port_first;
3186         while(port)
3187         {
3188                 if ((port->p_type&PORT_CLASS_MASK) == PORT_CLASS_mISDN)
3189                 {
3190                         isdnport = (class PmISDN *)port;
3191                         if (isdnport->p_m_mISDNport)
3192                         {
3193                                 PDEBUG(DEBUG_ISDN, "port %s uses mISDNport %d, destroying it.\n", isdnport->p_name, mISDNport->portnum);
3194                                 delete isdnport;
3195                         }
3196                 }
3197                 port = port->next;
3198         }
3199
3200         /* only if we are already part of interface */
3201         if (mISDNport->ifport)
3202         {
3203                 start_trace(mISDNport->portnum,
3204                             mISDNport->ifport->interface,
3205                             NULL,
3206                             NULL,
3207                             DIRECTION_NONE,
3208                             CATEGORY_CH,
3209                             0,
3210                             "PORT (close)");
3211                 end_trace();
3212         }
3213
3214         /* free bchannels */
3215         i = 0;
3216         while(i < mISDNport->b_num)
3217         {
3218                 if (mISDNport->b_addr[i])
3219                 {
3220                         _bchannel_destroy(mISDNport, i);
3221                         PDEBUG(DEBUG_BCHANNEL, "freeing %s port %d bchannel (index %d).\n", (mISDNport->ntmode)?"NT":"TE", mISDNport->portnum, i);
3222                 }
3223                 i++;
3224         }
3225
3226 #ifdef SOCKET_MISDN
3227         close_layer3(mISDNport->ml3);
3228 #else
3229         /* free ressources of port */
3230         msg_queue_purge(&mISDNport->downqueue);
3231
3232         /* free stacks */
3233         if (mISDNport->ntmode)
3234         {
3235                 nst = &mISDNport->nst;
3236                 if (nst->manager) /* to see if initialized */
3237                 {
3238                         PDEBUG(DEBUG_STACK, "the following messages are ok: one L3 process always exists (broadcast process) and some L2 instances (broadcast + current telephone's instances)\n");
3239                         cleanup_Isdnl3(nst);
3240                         cleanup_Isdnl2(nst);
3241
3242                         /* phd */
3243                         msg_queue_purge(&nst->down_queue);
3244                         if (nst->phd_down_msg)
3245                                 FREE(nst->phd_down_msg, 0);
3246                 }
3247         }
3248
3249         PDEBUG(DEBUG_BCHANNEL, "freeing d-stack.\n");
3250         if (mISDNport->d_stid)
3251         {
3252                 if (mISDNport->upper_id)
3253                         mISDN_write_frame(mISDNdevice, buf, mISDNport->upper_id | FLG_MSG_DOWN, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
3254         }
3255 #endif
3256
3257         /* remove from list */
3258         mISDNportp = &mISDNport_first;
3259         while(*mISDNportp)
3260         {
3261                 if (*mISDNportp == mISDNport)
3262                 {
3263                         *mISDNportp = (*mISDNportp)->next;
3264                         mISDNportp = NULL;
3265                         break;
3266                 }
3267                 mISDNportp = &((*mISDNportp)->next);
3268         }
3269
3270         if (mISDNportp)
3271                 FATAL("mISDNport not in list\n");
3272         
3273         FREE(mISDNport, sizeof(struct mISDNport));
3274         pmemuse--;
3275
3276 }
3277
3278
3279 /*
3280  * global function to show all available isdn ports
3281  */
3282 void mISDN_port_info(void)
3283 {
3284         int ret;
3285         int i, ii, p;
3286         int useable, nt, te, pri, bri, pots;
3287         unsigned char buff[1025];
3288         iframe_t *frm = (iframe_t *)buff;
3289 #ifdef SOCKET_MISDN
3290         struct mISDN_devinfo devinfo;
3291         int socket;
3292
3293         /* open mISDN */
3294         socket = socket(PF_ISDN, SOCK_RAW, ISDN_P_BASE);
3295         if (socket < 0)
3296         {
3297                 fprintf(stderr, "Cannot open mISDN due to %s. (Does your Kernel support socket based mISDN?)\n", strerror(errno));
3298                 exit(EXIT_FAILURE);
3299         }
3300
3301         /* get number of stacks */
3302         i = 1;
3303         ret = ioctl(socket, IMGETCOUNT, &ii);
3304         if (ret < 0)
3305         {
3306                 fprintf(stderr, "Cannot get number of mISDN devices. (ioctl IMGETCOUNT failed ret=%d)\n", ret);
3307                 goto done;
3308         }
3309 #else
3310         stack_info_t *stinf;
3311         int device;
3312
3313         /* open mISDN */
3314         if ((device = mISDN_open()) < 0)
3315         {
3316                 fprintf(stderr, "Cannot open mISDN device ret=%d errno=%d (%s) Check for mISDN modules!\nAlso did you create \"/dev/mISDN\"? Do: \"mknod /dev/mISDN c 46 0\"\n", device, errno, strerror(errno));
3317                 exit(EXIT_FAILURE);
3318         }
3319
3320         /* get number of stacks */
3321         i = 1;
3322         ii = mISDN_get_stack_count(device);
3323 #endif
3324         printf("\n");
3325         if (ii <= 0)
3326         {
3327                 printf("Found no card. Please be sure to load card drivers.\n");
3328                 goto done;
3329         }
3330
3331         /* loop the number of cards and get their info */
3332         while(i <= ii)
3333         {
3334                 nt = te = bri = pri = pots = 0;
3335                 useable = 0;
3336
3337 #ifdef SOCKET_MISDN
3338                 devinfo.id = i - 1;
3339                 ret = ioctl(socket, IMGETDEVINFO, &devinfo);
3340                 if (ret <= 0)
3341                 {
3342                         fprintf(stderr, "Cannot get device information for port %d. (ioctl IMGETDEVINFO failed ret=%d)\n", i, ret);
3343                         break;
3344                 }
3345
3346                 /* output the port info */
3347                 printf("Port %2d name='%s': ", i, devinfo.name);
3348                 if (devinfo.Dprotocols & (1 << ISDN_P_TE_S0))
3349                 {
3350                         bri = 1;
3351                         te = 1;
3352                 }
3353                 if (devinfo.Dprotocols & (1 << ISDN_P_NT_S0))
3354                 {
3355                         bri = 1;
3356                         nt = 1;
3357                 }
3358 #ifdef ISDN_P_TE_E1
3359                 if (devinfo.Dprotocols & (1 << ISDN_P_TE_E1))
3360                 {
3361                         pri = 1;
3362                         te = 1;
3363                 }
3364 #endif
3365 #ifdef ISDN_P_NT_E1
3366                 if (devinfo.Dprotocols & (1 << ISDN_P_NT_E1))
3367                 {
3368                         pri = 1;
3369                         nt = 1;
3370                 }
3371 #endif
3372 #ifdef ISDN_P_FXS
3373                 if (devinfo.Dprotocols & (1 << ISDN_P_FXS))
3374                 {
3375                         pots = 1;
3376                         te = 1;
3377                 }
3378 #endif
3379 #ifdef ISDN_P_FXO
3380                 if (devinfo.Dprotocols & (1 << ISDN_P_FXO))
3381                 {
3382                         pots = 1;
3383                         nt = 1;
3384                 }
3385 #endif
3386                 if ((te || nt) && (bri || pri || ports))
3387                         usable = 1;
3388
3389                 if (te && bri)
3390                         printf("TE-mode BRI S/T interface line (for phone lines)");
3391                 if (nt && bri)
3392                         printf("NT-mode BRI S/T interface port (for phones)");
3393                 if (te && pri)
3394                         printf("TE-mode PRI E1  interface line (for phone lines)");
3395                 if (nt && pri)
3396                         printf("NT-mode PRI E1  interface port (for E1 terminals)");
3397                 if (te && pots)
3398                         printf("FXS     POTS    interface port (for analog lines)");
3399                 if (nt && pots)
3400                         printf("FXO     POTS    interface port (for analog phones)");
3401                 if (ports)
3402                 {
3403                         usable = 0;
3404                         printf("\n -> Analog interfaces are not supported.");
3405                 } else
3406                 if (!usable)
3407                 {
3408                         printf("unsupported interface protocol bits 0x%016x", devinfo.Dprotocols);
3409                 }
3410                 printf("\n");
3411
3412                 printf("  - %d B-channels\n", devinfo.nfbchan);
3413 #else
3414                 ret = mISDN_get_stack_info(device, i, buff, sizeof(buff));
3415                 if (ret <= 0)
3416                 {
3417                         fprintf(stderr, "mISDN_get_stack_info() failed: port=%d error=%d\n", i, ret);
3418                         break;
3419                 }
3420                 stinf = (stack_info_t *)&frm->data.p;
3421
3422                 /* output the port info */
3423                 printf("Port %2d: ", i);
3424                 switch(stinf->pid.protocol[0] & ~ISDN_PID_FEATURE_MASK)
3425                 {
3426                         case ISDN_PID_L0_TE_S0:
3427                         useable = 1;
3428                         te = 1;
3429                         bri = 1;
3430                         printf("TE-mode BRI S/T interface line (for phone lines)");
3431                         break;
3432                         case ISDN_PID_L0_NT_S0:
3433                         useable = 1;
3434                         nt = 1;
3435                         bri = 1;
3436                         printf("NT-mode BRI S/T interface port (for phones)");
3437                         break;
3438                         case ISDN_PID_L0_TE_E1:
3439                         useable = 1;
3440                         te = 1;
3441                         pri = 1;
3442                         printf("TE-mode PRI E1  interface line (for phone lines)");
3443                         break;
3444                         case ISDN_PID_L0_NT_E1:
3445                         useable = 1;
3446                         nt = 1;
3447                         pri = 1;
3448                         printf("NT-mode PRI E1  interface port (for E1 terminals)");
3449                         break;
3450                         default:
3451                         useable = 0;
3452                         printf("unknown type 0x%08x",stinf->pid.protocol[0]);
3453                 }
3454                 printf("\n");
3455
3456                 if (nt)
3457                 {
3458                         if (stinf->pid.protocol[1] == 0)
3459                         {
3460                                 useable = 0;
3461                                 printf(" -> Missing layer 1 NT-mode protocol.\n");
3462                         }
3463                         p = 2;
3464                         while(p <= MAX_LAYER_NR) {
3465                                 if (stinf->pid.protocol[p])
3466                                 {
3467                                         useable = 0;
3468                                         printf(" -> Layer %d protocol 0x%08x is detected, port already in use by another application.\n", p, stinf->pid.protocol[p]);
3469                                 }
3470                                 p++;
3471                         }
3472                         if (useable)
3473                         {
3474                                 if (pri)
3475                                         printf(" -> Interface is Point-To-Point (PRI).\n");
3476                                 else
3477                                         printf(" -> Interface can be Poin-To-Point/Multipoint.\n");
3478                         }
3479                 }
3480                 if (te)
3481                 {
3482                         if (stinf->pid.protocol[1] == 0)
3483                         {
3484                                 useable = 0;
3485                                 printf(" -> Missing layer 1 protocol.\n");
3486                         }
3487                         if (stinf->pid.protocol[2] == 0)
3488                         {
3489                                 useable = 0;
3490                                 printf(" -> Missing layer 2 protocol.\n");
3491                         }
3492                         if (stinf->pid.protocol[2] & ISDN_PID_L2_DF_PTP)
3493                         {
3494                                 printf(" -> Interface is Poin-To-Point.\n");
3495                         }
3496                         if (stinf->pid.protocol[3] == 0)
3497                         {
3498                                 useable = 0;
3499                                 printf(" -> Missing layer 3 protocol.\n");
3500                         } else
3501                         {
3502                                 printf(" -> Protocol: ");
3503                                 switch(stinf->pid.protocol[3] & ~ISDN_PID_FEATURE_MASK)
3504                                 {
3505                                         case ISDN_PID_L3_DSS1USER:
3506                                         printf("DSS1 (Euro ISDN)");
3507                                         break;
3508
3509                                         default:
3510                                         useable = 0;
3511                                         printf("unknown protocol 0x%08x",stinf->pid.protocol[3]);
3512                                 }
3513                                 printf("\n");
3514                         }
3515                         p = 4;
3516                         while(p <= MAX_LAYER_NR) {
3517                                 if (stinf->pid.protocol[p])
3518                                 {
3519                                         useable = 0;
3520                                         printf(" -> Layer %d protocol 0x%08x is detected, port already in use by another application.\n", p, stinf->pid.protocol[p]);
3521                                 }
3522                                 p++;
3523                         }
3524                 }
3525                 printf("  - %d B-channels\n", stinf->childcnt);
3526 #endif
3527
3528                 if (!useable)
3529                         printf(" * Port NOT useable for LCR\n");
3530
3531                 printf("--------\n");
3532
3533                 i++;
3534         }
3535         printf("\n");
3536
3537 done:
3538 #ifdef SOCKET_MISDN
3539         close(sd);
3540 #else
3541         /* close mISDN */
3542         if ((ret = mISDN_close(device)))
3543                 FATAL("mISDN_close() failed: err=%d '%s'\n", ret, strerror(ret));
3544 #endif
3545 }
3546
3547
3548 /*
3549  * enque data from upper buffer
3550  */
3551 void PmISDN::txfromup(unsigned char *data, int length)
3552 {
3553 #ifdef SOCKET_MISDN
3554         unsigned char buf[MISDN_HEADER_LEN+((length>ISDN_LOAD)?length:ISDN_LOAD)];
3555         struct mISDNhead *frm = (struct mISDNhead *)buf;
3556
3557         if (p_m_b_index < 0)
3558                 return;
3559         if (!p_m_mISDNport->b_socket[p_m_b_index])
3560                 return;
3561 #else
3562         unsigned char buf[mISDN_HEADER_LEN+((length>ISDN_LOAD)?length:ISDN_LOAD)];
3563         iframe_t *frm = (iframe_t *)buf;
3564
3565         if (p_m_b_index < 0)
3566                 return;
3567         if (!p_m_mISDNport->b_addr[p_m_b_index])
3568                 return;
3569 #endif
3570
3571         /* check if high priority tones exist
3572          * ignore data in this case
3573          */
3574         if (p_tone_name[0] || p_m_crypt_msg_loops)
3575                 return;
3576
3577         /* preload procedure
3578          * if transmit buffer in DSP module is empty,
3579          * preload it to DSP_LOAD to prevent jitter gaps.
3580          */
3581         if (p_m_load==0 && ISDN_LOAD>0)
3582         {
3583
3584                 memcpy(buf+mISDN_HEADER_LEN, data, ISDN_LOAD);
3585                 frm->len = ISDN_LOAD;
3586                 mISDN_write(mISDNdevice, frm, mISDN_HEADER_LEN+frm->len, TIMEOUT_1SEC);
3587                 p_m_load += frm->len;
3588         }
3589
3590         /* drop if load would exceed ISDN_MAXLOAD
3591          * this keeps the delay not too high
3592          */
3593         if (p_m_load+length > ISDN_MAXLOAD)
3594                 return;
3595
3596         /* make and send frame */
3597 #ifdef SOCKET_MISDN
3598         frm->prim = DL_DATA_REQ;
3599         frm->id = 0;
3600         memcpy(buf+MISDN_HEADER_LEN, data, length);
3601         ret = sendto(p_m_mISDNport->b_socket[p_m_b_index], buf, MISDN_HEADER_LEN+length, 0, NULL, 0);
3602         if (!ret)
3603                 PERROR("Failed to send to socket %d\n", handle);
3604 #else
3605         frm->prim = DL_DATA | REQUEST; 
3606         frm->addr = p_m_mISDNport->b_addr[p_m_b_index] | FLG_MSG_DOWN;
3607         frm->dinfo = 0;
3608         frm->len = length;
3609         memcpy(buf+mISDN_HEADER_LEN, data, length);
3610         mISDN_write(mISDNdevice, frm, mISDN_HEADER_LEN+frm->len, TIMEOUT_1SEC);
3611 #endif
3612         p_m_load += length;
3613 }
3614