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