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