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