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