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