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