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