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