unified socket application interface (for asterisk and maybe other apps)
[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 <stdio.h>
14 #include <string.h>
15 #include <stdlib.h>
16 #include "main.h"
17 #include <unistd.h>
18 #include <poll.h>
19 #include <errno.h>
20 #include <sys/ioctl.h>
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <fcntl.h>
24 extern "C" {
25 #include <net_l2.h>
26 }
27
28 #if 0
29 #ifndef ISDN_PID_L2_B_USER
30 #define ISDN_PID_L2_B_USER 0x420000ff
31 #endif
32 #ifndef ISDN_PID_L3_B_USER
33 #define ISDN_PID_L3_B_USER 0x430000ff
34 #endif
35 #endif
36 #ifndef ISDN_PID_L4_B_USER
37 #define ISDN_PID_L4_B_USER 0x440000ff
38 #endif
39
40 /* used for udevice */
41 int entity = 0;
42
43 /* noise randomizer */
44 unsigned char mISDN_rand[256];
45 int mISDN_rand_count = 0;
46
47 /* the device handler and port list */
48 int mISDNdevice = -1;
49
50 /* list of mISDN ports */
51 struct mISDNport *mISDNport_first;
52
53 /*
54  * constructor
55  */
56 PmISDN::PmISDN(int type, mISDNport *mISDNport, char *portname, struct port_settings *settings, int channel, int exclusive) : Port(type, portname, settings)
57 {
58         p_m_mISDNport = mISDNport;
59         p_m_portnum = mISDNport->portnum;
60         p_m_b_index = -1;
61         p_m_b_channel = 0;
62         p_m_b_exclusive = 0;
63         p_m_b_reserve = 0;
64         p_m_delete = 0;
65         p_m_hold = 0;
66         p_m_txvol = p_m_rxvol = 0;
67         p_m_conf = 0;
68         p_m_txdata = 0;
69         p_m_delay = 0;
70         p_m_echo = 0;
71         p_m_tone = 0;
72         p_m_rxoff = 0;
73         p_m_joindata = 0;
74         p_m_dtmf = !mISDNport->ifport->nodtmf;
75         p_m_timeout = 0;
76         p_m_timer = 0;
77
78         /* audio */
79         p_m_load = 0;
80         p_m_last_tv_sec = 0;
81
82         /* crypt */
83         p_m_crypt = 0;
84         p_m_crypt_listen = 0;
85         p_m_crypt_msg_loops = 0;
86         p_m_crypt_msg_loops = 0;
87         p_m_crypt_msg_len = 0;
88         p_m_crypt_msg[0] = '\0';
89         p_m_crypt_msg_current = 0;
90         p_m_crypt_key[0] = '\0';
91         p_m_crypt_key_len = 0;
92         p_m_crypt_listen = 0;
93         p_m_crypt_listen_state = 0;
94         p_m_crypt_listen_len = 0;
95         p_m_crypt_listen_msg[0] = '\0';
96         p_m_crypt_listen_crc = 0;
97
98         /* if any channel requested by constructor */
99         if (channel == CHANNEL_ANY)
100         {
101                 /* reserve channel */
102                 p_m_b_reserve = 1;
103                 mISDNport->b_reserved++;
104         }
105
106         /* reserve channel */
107         if (channel > 0) // only if constructor was called with a channel resevation
108                 seize_bchannel(channel, exclusive);
109
110         /* we increase the number of objects: */
111         mISDNport->use++;
112         PDEBUG(DEBUG_ISDN, "Created new mISDNPort(%s). Currently %d objects use, port #%d\n", portname, mISDNport->use, p_m_portnum);
113 }
114
115
116 /*
117  * destructor
118  */
119 PmISDN::~PmISDN()
120 {
121         struct message *message;
122
123         /* remove bchannel relation */
124         drop_bchannel();
125
126         /* release epoint */
127         while (p_epointlist)
128         {
129                 PDEBUG(DEBUG_ISDN, "destroy mISDNPort(%s). endpoint still exists, releaseing.\n", p_name);
130                 message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
131                 message->param.disconnectinfo.cause = 16;
132                 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
133                 message_put(message);
134                 /* remove from list */
135                 free_epointlist(p_epointlist);
136         }
137
138         /* we decrease the number of objects: */
139         p_m_mISDNport->use--;
140         PDEBUG(DEBUG_ISDN, "destroyed mISDNPort(%s). Currently %d objects\n", p_name, p_m_mISDNport->use);
141 }
142
143
144 /*
145  * trace
146  */
147 void chan_trace_header(struct mISDNport *mISDNport, class PmISDN *port, char *msgtext, int direction)
148 {
149         /* init trace with given values */
150         start_trace(mISDNport?mISDNport->portnum:0,
151                     (mISDNport)?((mISDNport->ifport)?mISDNport->ifport->interface:NULL):NULL,
152                     port?numberrize_callerinfo(port->p_callerinfo.id, port->p_callerinfo.ntype):NULL,
153                     port?port->p_dialinginfo.id:NULL,
154                     direction,
155                     CATEGORY_CH,
156                     port?port->p_serial:0,
157                     msgtext);
158 }
159
160
161 /*
162  * layer trace header
163  */
164 static struct isdn_message {
165         char *name;
166         unsigned long value;
167 } isdn_message[] = {
168         {"TIMEOUT", CC_TIMEOUT},
169         {"SETUP", CC_SETUP},
170         {"SETUP_ACK", CC_SETUP_ACKNOWLEDGE},
171         {"PROCEEDING", CC_PROCEEDING},
172         {"ALERTING", CC_ALERTING},
173         {"CONNECT", CC_CONNECT},
174         {"CONNECT RES", CC_CONNECT},
175         {"CONNECT_ACK", CC_CONNECT_ACKNOWLEDGE},
176         {"DISCONNECT", CC_DISCONNECT},
177         {"RELEASE", CC_RELEASE},
178         {"RELEASE_COMP", CC_RELEASE_COMPLETE},
179         {"INFORMATION", CC_INFORMATION},
180         {"PROGRESS", CC_PROGRESS},
181         {"NOTIFY", CC_NOTIFY},
182         {"SUSPEND", CC_SUSPEND},
183         {"SUSPEND_ACK", CC_SUSPEND_ACKNOWLEDGE},
184         {"SUSPEND_REJ", CC_SUSPEND_REJECT},
185         {"RESUME", CC_RESUME},
186         {"RESUME_ACK", CC_RESUME_ACKNOWLEDGE},
187         {"RESUME_REJ", CC_RESUME_REJECT},
188         {"HOLD", CC_HOLD},
189         {"HOLD_ACK", CC_HOLD_ACKNOWLEDGE},
190         {"HOLD_REJ", CC_HOLD_REJECT},
191         {"RETRIEVE", CC_RETRIEVE},
192         {"RETRIEVE_ACK", CC_RETRIEVE_ACKNOWLEDGE},
193         {"RETRIEVE_REJ", CC_RETRIEVE_REJECT},
194         {"FACILITY", CC_FACILITY},
195         {"STATUS", CC_STATUS},
196         {"RESTART", CC_RESTART},
197         {"RELEASE_CR", CC_RELEASE_CR},
198         {"NEW_CR", CC_NEW_CR},
199         {"DL_ESTABLISH", DL_ESTABLISH},
200         {"DL_RELEASE", DL_RELEASE},
201         {"PH_ACTIVATE", PH_ACTIVATE},
202         {"PH_DEACTIVATE", PH_DEACTIVATE},
203
204         {NULL, 0},
205 };
206 static char *isdn_prim[4] = {
207         " REQUEST",
208         " CONFIRM",
209         " INDICATION",
210         " RESPONSE",
211 };
212 void l1l2l3_trace_header(struct mISDNport *mISDNport, class PmISDN *port, unsigned long prim, int direction)
213 {
214         int i;
215         char msgtext[64] = "<<UNKNOWN MESSAGE>>";
216
217         /* select message and primitive text */
218         i = 0;
219         while(isdn_message[i].name)
220         {
221                 if (isdn_message[i].value == (prim&0xffffff00))
222                 {
223                         SCPY(msgtext, isdn_message[i].name);
224                         break;
225                 }
226                 i++;
227         }
228         SCAT(msgtext, isdn_prim[prim&0x00000003]);
229
230         /* add direction */
231         if (direction && (prim&0xffffff00)!=CC_NEW_CR && (prim&0xffffff00)!=CC_RELEASE_CR)
232         {
233                 if (mISDNport)
234                 {
235                         if (mISDNport->ntmode)
236                         {
237                                 if (direction == DIRECTION_OUT)
238                                         SCAT(msgtext, " N->U");
239                                 else
240                                         SCAT(msgtext, " N<-U");
241                         } else
242                         {
243                                 if (direction == DIRECTION_OUT)
244                                         SCAT(msgtext, " U->N");
245                                 else
246                                         SCAT(msgtext, " U<-N");
247                         }
248                 }
249         }
250
251         /* init trace with given values */
252         start_trace(mISDNport?mISDNport->portnum:0,
253                     mISDNport?mISDNport->ifport->interface:NULL,
254                     port?numberrize_callerinfo(port->p_callerinfo.id, port->p_callerinfo.ntype):NULL,
255                     port?port->p_dialinginfo.id:NULL,
256                     direction,
257                     CATEGORY_CH,
258                     port?port->p_serial:0,
259                     msgtext);
260 }
261
262
263 /*
264  * send control information to the channel (dsp-module)
265  */
266 void ph_control(struct mISDNport *mISDNport, class PmISDN *isdnport, unsigned long b_addr, int c1, int c2, char *trace_name, int trace_value)
267 {
268         unsigned char buffer[mISDN_HEADER_LEN+sizeof(int)+sizeof(int)];
269         iframe_t *ctrl = (iframe_t *)buffer; 
270         unsigned long *d = (unsigned long *)&ctrl->data.p;
271
272         ctrl->prim = PH_CONTROL | REQUEST;
273         ctrl->addr = b_addr | FLG_MSG_DOWN;
274         ctrl->dinfo = 0;
275         ctrl->len = sizeof(int)*2;
276         *d++ = c1;
277         *d++ = c2;
278         mISDN_write(mISDNdevice, ctrl, mISDN_HEADER_LEN+ctrl->len, TIMEOUT_1SEC);
279         chan_trace_header(mISDNport, isdnport, "BCHANNEL control", DIRECTION_OUT);
280         if (c1 == CMX_CONF_JOIN)
281                 add_trace(trace_name, NULL, "0x%08x", trace_value);
282         else
283                 add_trace(trace_name, NULL, "%d", trace_value);
284         end_trace();
285 }
286
287 void ph_control_block(struct mISDNport *mISDNport, class PmISDN *isdnport, unsigned long b_addr, int c1, void *c2, int c2_len, char *trace_name, int trace_value)
288 {
289         unsigned char buffer[mISDN_HEADER_LEN+sizeof(int)+c2_len];
290         iframe_t *ctrl = (iframe_t *)buffer;
291         unsigned long *d = (unsigned long *)&ctrl->data.p;
292
293         ctrl->prim = PH_CONTROL | REQUEST;
294         ctrl->addr = b_addr | FLG_MSG_DOWN;
295         ctrl->dinfo = 0;
296         ctrl->len = sizeof(int)+c2_len;
297         *d++ = c1;
298         memcpy(d, c2, c2_len);
299         mISDN_write(mISDNdevice, ctrl, mISDN_HEADER_LEN+ctrl->len, TIMEOUT_1SEC);
300         chan_trace_header(mISDNport, isdnport, "BCHANNEL control", DIRECTION_OUT);
301         add_trace(trace_name, NULL, "%d", trace_value);
302         end_trace();
303 }
304
305
306 /*
307  * subfunction for bchannel_event
308  * create stack
309  */
310 static int _bchannel_create(struct mISDNport *mISDNport, int i)
311 {
312         unsigned char buff[1024];
313         layer_info_t li;
314         mISDN_pid_t pid;
315         int ret;
316
317         if (!mISDNport->b_stid[i])
318         {
319                 PERROR("Error: no stack for index %d\n", i);
320                 return(0);
321         }
322         if (mISDNport->b_addr[i])
323         {
324                 PERROR("Error: stack already created for index %d\n", i);
325                 return(0);
326         }
327
328         /* create new layer */
329         PDEBUG(DEBUG_BCHANNEL, "creating new layer for bchannel %d (index %d).\n" , i+1+(i>=15), i);
330         memset(&li, 0, sizeof(li));
331         memset(&pid, 0, sizeof(pid));
332         li.object_id = -1;
333         li.extentions = 0;
334         li.st = mISDNport->b_stid[i];
335         UCPY(li.name, "B L4");
336         li.pid.layermask = ISDN_LAYER((4));
337         li.pid.protocol[4] = ISDN_PID_L4_B_USER;
338         ret = mISDN_new_layer(mISDNdevice, &li);
339         if (ret)
340         {
341                 failed_new_layer:
342                 PERROR("mISDN_new_layer() failed to add bchannel %d (index %d)\n", i+1+(i>=15), i);
343                 goto failed;
344         }
345         mISDNport->b_addr[i] = li.id;
346         if (!li.id)
347         {
348                 goto failed_new_layer;
349         }
350         PDEBUG(DEBUG_BCHANNEL, "new layer (b_addr=0x%x)\n", mISDNport->b_addr[i]);
351
352         /* create new stack */
353         pid.protocol[1] = ISDN_PID_L1_B_64TRANS;
354         pid.protocol[2] = ISDN_PID_L2_B_TRANS;
355         pid.protocol[3] = ISDN_PID_L3_B_DSP;
356         pid.protocol[4] = ISDN_PID_L4_B_USER;
357         pid.layermask = ISDN_LAYER((1)) | ISDN_LAYER((2)) | ISDN_LAYER((3)) | ISDN_LAYER((4));
358         ret = mISDN_set_stack(mISDNdevice, mISDNport->b_stid[i], &pid);
359         if (ret)
360         {
361                 stack_error:
362                 PERROR("mISDN_set_stack() failed (ret=%d) to add bchannel (index %d) stid=0x%x\n", ret, i, mISDNport->b_stid[i]);
363                 mISDN_write_frame(mISDNdevice, buff, mISDNport->b_addr[i], MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
364                 goto failed;
365         }
366         ret = mISDN_get_setstack_ind(mISDNdevice, mISDNport->b_addr[i]);
367         if (ret)
368                 goto stack_error;
369
370         /* get layer id */
371         mISDNport->b_addr[i] = mISDN_get_layerid(mISDNdevice, mISDNport->b_stid[i], 4);
372         if (!mISDNport->b_addr[i])
373                 goto stack_error;
374         chan_trace_header(mISDNport, mISDNport->b_port[i], "BCHANNEL create stack", DIRECTION_OUT);
375         add_trace("channel", NULL, "%d", i+1+(i>=15));
376         add_trace("stack", "id", "0x%08x", mISDNport->b_stid[i]);
377         add_trace("stack", "address", "0x%08x", mISDNport->b_addr[i]);
378         end_trace();
379
380         return(1);
381
382 failed:
383         mISDNport->b_addr[i] = 0;
384         return(0);
385 }
386
387
388 /*
389  * subfunction for bchannel_event
390  * activate request
391  */
392 static void _bchannel_activate(struct mISDNport *mISDNport, int i, int activate)
393 {
394         iframe_t act;
395
396         /* activate bchannel */
397         chan_trace_header(mISDNport, mISDNport->b_port[i], activate?(char*)"BCHANNEL activate":(char*)"BCHANNEL deactivate", DIRECTION_OUT);
398         add_trace("channel", NULL, "%d", i+1+(i>=15));
399         end_trace();
400         act.prim = (activate?DL_ESTABLISH:DL_RELEASE) | REQUEST; 
401         act.addr = mISDNport->b_addr[i] | FLG_MSG_DOWN;
402         act.dinfo = 0;
403         act.len = 0;
404         mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
405 }
406
407
408 /*
409  * subfunction for bchannel_event
410  * set features
411  */
412 static void _bchannel_configure(struct mISDNport *mISDNport, int i)
413 {
414         struct PmISDN *port;
415         int addr;
416
417         port = mISDNport->b_port[i];
418         addr = mISDNport->b_addr[i];
419         if (!port)
420         {
421                 PERROR("bchannel index i=%d not associated with a port object\n", i);
422                 return;
423         }
424
425         /* set dsp features */
426         if (port->p_m_txdata)
427                 ph_control(mISDNport, port, addr, (port->p_m_txdata)?CMX_TXDATA_ON:CMX_TXDATA_OFF, 0, "DSP-TXDATA", port->p_m_txdata);
428         if (port->p_m_delay)
429                 ph_control(mISDNport, port, addr, CMX_DELAY, port->p_m_delay, "DSP-DELAY", port->p_m_delay);
430         if (port->p_m_txvol)
431                 ph_control(mISDNport, port, addr, VOL_CHANGE_TX, port->p_m_txvol, "DSP-TXVOL", port->p_m_txvol);
432         if (port->p_m_rxvol)
433                 ph_control(mISDNport, port, addr, VOL_CHANGE_RX, port->p_m_rxvol, "DSP-RXVOL", port->p_m_rxvol);
434         if (port->p_m_conf)
435                 ph_control(mISDNport, port, addr, CMX_CONF_JOIN, port->p_m_conf, "DSP-CONF", port->p_m_conf);
436         if (port->p_m_echo)
437                 ph_control(mISDNport, port, addr, CMX_ECHO_ON, 0, "DSP-ECHO", 1);
438         if (port->p_m_tone)
439                 ph_control(mISDNport, port, addr, TONE_PATT_ON, port->p_m_tone, "DSP-TONE", port->p_m_tone);
440         if (port->p_m_rxoff)
441                 ph_control(mISDNport, port, addr, CMX_RECEIVE_OFF, 0, "DSP-RXOFF", 1);
442 //      if (port->p_m_txmix)
443 //              ph_control(mISDNport, port, addr, CMX_MIX_ON, 0, "DSP-MIX", 1);
444         if (port->p_m_dtmf)
445                 ph_control(mISDNport, port, addr, DTMF_TONE_START, 0, "DSP-DTMF", 1);
446         if (port->p_m_crypt)
447                 ph_control_block(mISDNport, port, addr, BF_ENABLE_KEY, port->p_m_crypt_key, port->p_m_crypt_key_len, "DSP-CRYPT", port->p_m_crypt_key_len);
448 }
449
450 /*
451  * subfunction for bchannel_event
452  * destroy stack
453  */
454 static void _bchannel_destroy(struct mISDNport *mISDNport, int i)
455 {
456         unsigned char buff[1024];
457
458         chan_trace_header(mISDNport, mISDNport->b_port[i], "BCHANNEL remove stack", DIRECTION_OUT);
459         add_trace("channel", NULL, "%d", i+1+(i>=15));
460         add_trace("stack", "id", "0x%08x", mISDNport->b_stid[i]);
461         add_trace("stack", "address", "0x%08x", mISDNport->b_addr[i]);
462         end_trace();
463         /* remove our stack only if set */
464         if (mISDNport->b_addr[i])
465         {
466                 PDEBUG(DEBUG_BCHANNEL, "free stack (b_addr=0x%x)\n", mISDNport->b_addr[i]);
467                 mISDN_clear_stack(mISDNdevice, mISDNport->b_stid[i]);
468                 mISDN_write_frame(mISDNdevice, buff, mISDNport->b_addr[i] | FLG_MSG_DOWN, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
469                 mISDNport->b_addr[i] = 0;
470         }
471 }
472
473
474 /*
475 bchannel procedure
476 ------------------
477
478 A bchannel goes through the following states in this order:
479
480 - B_STATE_IDLE
481 No one is using the bchannel.
482 It is available and not linked to Port class, nor reserved.
483
484 - B_STATE_ACTIVATING
485 The bchannel stack is created and an activation request is sent.
486 It MAY be linked to Port class, but already unlinked due to Port class removal.
487
488 - B_STATE_ACTIVE
489 The bchannel is active and cofigured to the Port class needs.
490 Also it is linked to a Port class, otherwhise it would be deactivated.
491
492 - B_STATE_DEACTIVATING
493 The bchannel is in deactivating state, due to deactivation request.
494 It may be linked to a Port class, that likes to reactivate it.
495
496 - B_STATE_IDLE
497 See above.
498 After deactivating bchannel, and if not used, the bchannel becomes idle again.
499
500
501 A bchannel can have the following events:
502
503 - B_EVENT_ACTIVATE
504 A bchannel is required by a Port class.
505
506 - B_EVENT_ACTIVATED
507 The bchannel beomes active.
508
509 - B_EVENT_DEACTIVATE
510 The bchannel is not required by Port class anymore
511
512 - B_EVENT_DEACTIVATED
513 The bchannel becomes inactive.
514
515 All actions taken on these events depend on the current bchannel's state and if it is linked to a Port class.
516
517 */
518
519 /*
520  * process bchannel events
521  * - mISDNport is a pointer to the port's structure
522  * - i is the index of the bchannel
523  * - event is the B_EVENT_* value
524  * - port is the PmISDN class pointer
525  */
526 void bchannel_event(struct mISDNport *mISDNport, int i, int event)
527 {
528         int state = mISDNport->b_state[i];
529
530         switch(event)
531         {
532                 case B_EVENT_ACTIVATE:
533                 /* port must be linked in order to allow activation */
534                 if (!mISDNport->b_port[i])
535                         FATAL("bchannel must be linked to a Port class\n");
536                 switch(state)
537                 {
538                         case B_STATE_IDLE:
539                         /* create stack and send activation request */
540                         if (_bchannel_create(mISDNport, i))
541                         {
542                                 _bchannel_activate(mISDNport, i, 1);
543                                 state = B_STATE_ACTIVATING;
544                         }
545                         break;
546
547                         case B_STATE_ACTIVATING:
548                         /* do nothing, because it is already activating */
549                         break;
550
551                         case B_STATE_DEACTIVATING:
552                         /* do nothing, because we must wait until we can reactivate */
553                         break;
554
555                         default:
556                         PERROR("Illegal event %d at state %d, please correct.\n", event, state);
557                 }
558                 break;
559
560                 case B_EVENT_ACTIVATED:
561                 switch(state)
562                 {
563                         case B_STATE_ACTIVATING:
564                         if (mISDNport->b_port[i])
565                         {
566                                 /* bchannel is active and used by Port class, so we configure bchannel */
567                                 _bchannel_configure(mISDNport, i);
568                                 state = B_STATE_ACTIVE;
569                         } else
570                         {
571                                 /* bchannel is active, but not used anymore (or has wrong stack config), so we deactivate */
572                                 _bchannel_activate(mISDNport, i, 0);
573                                 state = B_STATE_DEACTIVATING;
574                         }
575                         break;
576
577                         default:
578                         PERROR("Illegal event %d at state %d, please correct.\n", event, state);
579                 }
580                 break;
581
582                 case B_EVENT_DEACTIVATE:
583                 if (!mISDNport->b_port[i])
584                         FATAL("bchannel must be linked to a Port class\n");
585                 switch(state)
586                 {
587                         case B_STATE_IDLE:
588                         /* bchannel is idle due to an error, so we do nothing */
589                         break;
590
591                         case B_STATE_ACTIVATING:
592                         /* do nothing because we must wait until bchanenl is active before deactivating */
593                         break;
594
595                         case B_STATE_ACTIVE:
596                         /* bchannel is active, so we deactivate */
597                         _bchannel_activate(mISDNport, i, 0);
598                         state = B_STATE_DEACTIVATING;
599                         break;
600
601                         case B_STATE_DEACTIVATING:
602                         /* we may have taken an already deactivating bchannel, but do not require it anymore, so we do nothing */
603                         break;
604
605                         default:
606                         PERROR("Illegal event %d at state %d, please correct.\n", event, state);
607                 }
608                 break;
609
610                 case B_EVENT_DEACTIVATED:
611                 switch(state)
612                 {
613                         case B_STATE_IDLE:
614                         /* ignore due to deactivation confirm after unloading */
615                         break;
616
617                         case B_STATE_DEACTIVATING:
618                         _bchannel_destroy(mISDNport, i);
619                         state = B_STATE_IDLE;
620                         if (mISDNport->b_port[i])
621                         {
622                                 /* bchannel is now deactivate, but is requied by Port class, so we reactivate */
623                                 if (_bchannel_create(mISDNport, i))
624                                 {
625                                         _bchannel_activate(mISDNport, i, 1);
626                                         state = B_STATE_ACTIVATING;
627                                 }
628                         }
629                         break;
630
631                         default:
632                         PERROR("Illegal event %d at state %d, please correct.\n", event, state);
633                 }
634                 break;
635
636                 default:
637                 PERROR("Illegal event %d, please correct.\n", event);
638         }
639
640         mISDNport->b_state[i] = state;
641 }
642
643
644
645
646 /*
647  * check for available channel and reserve+set it.
648  * give channel number or SEL_CHANNEL_ANY or SEL_CHANNEL_NO
649  * give exclusiv flag
650  * returns -(cause value) or x = channel x or 0 = no channel
651  * NOTE: no activation is done here
652  */
653 int PmISDN::seize_bchannel(int channel, int exclusive)
654 {
655         int i;
656
657         /* the channel is what we have */
658         if (p_m_b_channel == channel)
659                 return(channel);
660
661         /* if channel already in use, release it */
662         if (p_m_b_channel)
663                 drop_bchannel();
664
665         /* if CHANNEL_NO */
666         if (channel==CHANNEL_NO || channel==0)
667                 return(0);
668         
669         /* is channel in range ? */
670         if (channel==16
671          || (channel>p_m_mISDNport->b_num && channel<16)
672          || ((channel-1)>p_m_mISDNport->b_num && channel>16)) /* channel-1 because channel 16 is not counted */
673                 return(-6); /* channel unacceptable */
674
675         /* request exclusive channel */
676         if (exclusive && channel>0)
677         {
678                 i = channel-1-(channel>16);
679                 if (p_m_mISDNport->b_port[i])
680                         return(-44); /* requested channel not available */
681                 goto seize;
682         }
683
684         /* ask for channel */
685         if (channel>0)
686         {
687                 i = channel-1-(channel>16);
688                 if (p_m_mISDNport->b_port[i] == NULL)
689                         goto seize;
690         }
691
692         /* search for channel */
693         i = 0;
694         while(i < p_m_mISDNport->b_num)
695         {
696                 if (!p_m_mISDNport->b_port[i])
697                 {
698                         channel = i+1+(i>=15);
699                         goto seize;
700                 }
701                 i++;
702         }
703         return(-34); /* no free channel */
704
705 seize:
706         PDEBUG(DEBUG_BCHANNEL, "PmISDN(%s) seizing bchannel %d (index %d)\n", p_name, channel, i);
707
708         /* link Port */
709         p_m_mISDNport->b_port[i] = this;
710         p_m_b_index = i;
711         p_m_b_channel = channel;
712         p_m_b_exclusive = exclusive;
713
714         /* reserve channel */
715         if (!p_m_b_reserve)
716         {
717                 p_m_b_reserve = 1;
718                 p_m_mISDNport->b_reserved++;
719         }
720
721         return(channel);
722 }
723
724 /*
725  * drop reserved channel and unset it.
726  * deactivation is also done
727  */
728 void PmISDN::drop_bchannel(void)
729 {
730         if (p_m_b_index < 0)
731                 return;
732
733         /* unreserve channel */
734         if (p_m_b_reserve)
735                 p_m_mISDNport->b_reserved--;
736         p_m_b_reserve = 0;
737
738         /* if not in use */
739         if (!p_m_b_channel)
740                 return;
741
742         PDEBUG(DEBUG_BCHANNEL, "PmISDN(%s) dropping bchannel\n", p_name);
743
744         if (p_m_mISDNport->b_state[p_m_b_index] != B_STATE_IDLE)
745                 bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_DEACTIVATE);
746         p_m_mISDNport->b_port[p_m_b_index] = NULL;
747         p_m_b_index = -1;
748         p_m_b_channel = 0;
749         p_m_b_exclusive = 0;
750 }
751
752
753 /*
754  * handler
755
756 audio transmission procedure:
757 -----------------------------
758
759 * priority
760 three sources of audio transmission:
761 - crypto-data high priority
762 - tones high priority (also high)
763 - remote-data low priority
764
765 * elapsed
766 a variable that temporarily shows the number of samples elapsed since last transmission process.
767 p_m_last_tv_* is used to store that last timestamp. this is used to calculate the time elapsed.
768
769 * load
770 a variable that is increased whenever data is transmitted.
771 it is decreased while time elapses. it stores the number of samples that
772 are currently loaded to dsp module.
773 since clock in dsp module is the same clock for user space process, these 
774 times have no skew.
775
776 * levels
777 there are two levels:
778 ISDN_LOAD will give the load that have to be kept in dsp.
779 ISDN_MAXLOAD will give the maximum load before dropping.
780
781 * procedure for low priority data
782 see txfromup() for procedure
783 in short: remote data is ignored during high priority tones
784
785 * procedure for high priority data
786 whenever load is below ISDN_LOAD, load is filled up to ISDN_LOAD
787 if no more data is available, load becomes empty again.
788
789 'load' variable:
790 0                    ISDN_LOAD           ISDN_MAXLOAD
791 +--------------------+----------------------+
792 |                    |                      |
793 +--------------------+----------------------+
794
795 on empty load or on load below ISDN_LOAD, the load is inceased to ISDN_LOAD:
796 0                    ISDN_LOAD           ISDN_MAXLOAD
797 +--------------------+----------------------+
798 |TTTTTTTTTTTTTTTTTTTT|                      |
799 +--------------------+----------------------+
800
801 on empty load, remote-audio causes the load with the remote audio to be increased to ISDN_LOAD.
802 0                    ISDN_LOAD           ISDN_MAXLOAD
803 +--------------------+----------------------+
804 |TTTTTTTTTTTTTTTTTTTTRRRRR                  |
805 +--------------------+----------------------+
806
807  */
808 int PmISDN::handler(void)
809 {
810         struct message *message;
811         int elapsed = 0;
812         int ret;
813
814         if ((ret = Port::handler()))
815                 return(ret);
816
817         /* get elapsed */
818         if (p_m_last_tv_sec)
819         {
820                 elapsed = 8000 * (now_tv.tv_sec - p_m_last_tv_sec)
821                         + 8 * (now_tv.tv_usec/1000 - p_m_last_tv_msec);
822         } else
823         {
824                 /* set clock of first process ever in this instance */
825                 p_m_last_tv_sec = now_tv.tv_sec;
826                 p_m_last_tv_msec = now_tv.tv_usec/1000;
827         }
828         /* process only if we have a minimum of samples, to make packets not too small */
829         if (elapsed >= ISDN_TRANSMIT)
830         {
831                 /* set clock of last process! */
832                 p_m_last_tv_sec = now_tv.tv_sec;
833                 p_m_last_tv_msec = now_tv.tv_usec/1000;
834
835                 /* update load */
836                 if (elapsed < p_m_load)
837                         p_m_load -= elapsed;
838                 else
839                         p_m_load = 0;
840
841                 /* to send data, tone must be active OR crypt messages must be on */
842                 if ((p_tone_name[0] || p_m_crypt_msg_loops) && p_m_load < ISDN_LOAD)
843                 {
844                         int tosend = ISDN_LOAD - p_m_load, length; 
845                         unsigned char buf[mISDN_HEADER_LEN+tosend];
846                         iframe_t *frm = (iframe_t *)buf;
847                         unsigned char *p = buf+mISDN_HEADER_LEN;
848
849                         /* copy crypto loops */
850                         while (p_m_crypt_msg_loops && tosend)
851                         {
852                                 /* how much do we have to send */
853                                 length = p_m_crypt_msg_len - p_m_crypt_msg_current;
854
855                                 /* clip tosend */
856                                 if (length > tosend)
857                                         length = tosend;
858
859                                 /* copy message (part) to buffer */
860                                 memcpy(p, p_m_crypt_msg+p_m_crypt_msg_current, length);
861
862                                 /* new position */
863                                 p_m_crypt_msg_current += length;
864                                 if (p_m_crypt_msg_current == p_m_crypt_msg_len)
865                                 {
866                                         /* next loop */
867                                         p_m_crypt_msg_current = 0;
868                                         p_m_crypt_msg_loops--;
869                                 }
870
871                                 /* new length */
872                                 tosend -= length;
873                         }
874
875                         /* copy tones */
876                         if (p_tone_name[0] && tosend)
877                         {
878                                 tosend -= read_audio(p, tosend);
879                         }
880
881                         /* send data */
882                         frm->prim = DL_DATA | REQUEST; 
883                         frm->addr = p_m_mISDNport->b_addr[p_m_b_index] | FLG_MSG_DOWN;
884                         frm->dinfo = 0;
885                         frm->len = ISDN_LOAD - p_m_load - tosend;
886                         if (frm->len)
887                                 mISDN_write(mISDNdevice, frm, mISDN_HEADER_LEN+frm->len, TIMEOUT_1SEC);
888                         p_m_load += frm->len;
889                 }
890         }
891
892         // NOTE: deletion is done by the child class
893
894         /* handle timeouts */
895         if (p_m_timeout)
896         {
897                 if (p_m_timer+p_m_timeout < now_d)
898                 {
899                         PDEBUG(DEBUG_ISDN, "(%s) timeout after %d seconds detected (state=%d).\n", p_name, p_m_timeout, p_state);
900                         p_m_timeout = 0;
901                         /* send timeout to endpoint */
902                         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_TIMEOUT);
903                         message->param.state = p_state;
904                         message_put(message);
905                         return(1);
906                 }
907         }
908         
909         return(0); /* nothing done */
910 }
911
912
913 /*
914  * whenever we get audio data from bchannel, we process it here
915  */
916 void PmISDN::bchannel_receive(iframe_t *frm)
917 {
918         unsigned char *data_temp;
919         unsigned long length_temp;
920         struct message *message;
921         unsigned char *p;
922         int l;
923         unsigned long cont;
924
925         if (frm->prim == (PH_CONTROL | INDICATION))
926         {
927                 if (frm->len < 4)
928                 {
929                         PERROR("SHORT READ OF PH_CONTROL INDICATION\n");
930                         return;
931                 }
932                 cont = *((unsigned long *)&frm->data.p);
933                 if ((cont&(~DTMF_TONE_MASK)) == DTMF_TONE_VAL)
934                 {
935                         chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
936                         add_trace("DTMF", NULL, "%c", cont & DTMF_TONE_MASK);
937                         end_trace();
938                         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_DTMF);
939                         message->param.dtmf = cont & DTMF_TONE_MASK;
940                         PDEBUG(DEBUG_PORT, "PmISDN(%s) PH_CONTROL INDICATION  DTMF digit '%c'\n", p_name, message->param.dtmf);
941                         message_put(message);
942                         return;
943                 }
944                 switch(cont)
945                 {
946                         case BF_REJECT:
947                         chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
948                         add_trace("DSP-CRYPT", NULL, "error");
949                         end_trace();
950                         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CRYPT);
951                         message->param.crypt.type = CC_ERROR_IND;
952                         PDEBUG(DEBUG_PORT, "PmISDN(%s) PH_CONTROL INDICATION  reject of blowfish.\n", p_name);
953                         message_put(message);
954                         break;
955
956                         case BF_ACCEPT:
957                         chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
958                         add_trace("DSP-CRYPT", NULL, "ok");
959                         end_trace();
960                         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CRYPT);
961                         message->param.crypt.type = CC_ACTBF_CONF;
962                         PDEBUG(DEBUG_PORT, "PmISDN(%s) PH_CONTROL INDICATION  accept of blowfish.\n", p_name);
963                         message_put(message);
964                         break;
965
966                         case CMX_TX_DATA:
967                         if (!p_m_txdata)
968                         {
969                                 /* if tx is off, it may happen that fifos send us pending informations, we just ignore them */
970                                 PDEBUG(DEBUG_BCHANNEL, "PmISDN(%s) ignoring tx data, because 'txdata' is turned off\n", p_name);
971                                 return;
972                         }
973                         if (p_record)
974                                 record((unsigned char *)(cont+1), frm->len - 4, 1); // from up
975                         break;
976
977                         default:
978                         chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
979                         add_trace("unknown", NULL, "0x%x", cont);
980                         end_trace();
981                 }
982                 return;
983         }
984         if (frm->prim != (PH_DATA | INDICATION) && frm->prim != (DL_DATA | INDICATION))
985         {
986                 PERROR("Bchannel received unknown primitve: 0x%x\n", frm->prim);
987                 return;
988         }
989
990         /* calls will not process any audio data unless
991          * the call is connected OR interface features audio during call setup.
992          */
993 //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);     
994 #ifndef DEBUG_COREBRIDGE
995         if (p_state!=PORT_STATE_CONNECT
996          && !p_m_mISDNport->earlyb)
997                 return;
998 #endif
999
1000         /* if rx is off, it may happen that fifos send us pending informations, we just ignore them */
1001         if (p_m_rxoff)
1002         {
1003                 PDEBUG(DEBUG_BCHANNEL, "PmISDN(%s) ignoring data, because rx is turned off\n", p_name);
1004                 return;
1005         }
1006
1007         /* record data */
1008         if (p_record)
1009                 record((unsigned char *)&frm->data.p, frm->len, 0); // from down
1010
1011         /* randomize and listen to crypt message if enabled */
1012         if (p_m_crypt_listen)
1013         {
1014                 /* the noisy randomizer */
1015                 p = (unsigned char *)&frm->data.p;
1016                 l = frm->len;
1017                 while(l--)
1018                         mISDN_rand[mISDN_rand_count & 0xff] += *p++;
1019
1020                 cryptman_listen_bch((unsigned char *)&frm->data.p, frm->len);
1021         }
1022
1023         p = (unsigned char *)&frm->data.p;
1024
1025         /* send data to epoint */
1026         if (p_m_joindata && ACTIVE_EPOINT(p_epointlist)) /* only if we have an epoint object */
1027         {
1028                 length_temp = frm->len;
1029                 data_temp = p;
1030                 while(length_temp)
1031                 {
1032                         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_DATA);
1033                         message->param.data.len = (length_temp>sizeof(message->param.data.data))?sizeof(message->param.data.data):length_temp;
1034                         memcpy(message->param.data.data, data_temp, message->param.data.len);
1035                         message_put(message);
1036                         if (length_temp <= sizeof(message->param.data.data))
1037                                 break;
1038                         data_temp += sizeof(message->param.data.data);
1039                         length_temp -= sizeof(message->param.data.data);
1040                 }
1041         }
1042 }
1043
1044
1045 /*
1046  * set echotest
1047  */
1048 void PmISDN::set_echotest(int echo)
1049 {
1050         if (p_m_echo != echo)
1051         {
1052                 p_m_echo = echo;
1053                 PDEBUG(DEBUG_ISDN, "we set echo to echo=%d.\n", p_m_echo);
1054                 if (p_m_b_channel)
1055                         if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1056                                 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);
1057         }
1058 }
1059
1060 /*
1061  * set tone
1062  */
1063 void PmISDN::set_tone(char *dir, char *tone)
1064 {
1065         int id;
1066
1067         if (!tone)
1068                 tone = "";
1069         PDEBUG(DEBUG_ISDN, "isdn port now plays tone:'%s'.\n", tone);
1070         if (!tone[0])
1071         {
1072                 id = TONE_OFF;
1073                 goto setdsp;
1074         }
1075
1076         /* check if we NOT really have to use a dsp-tone */
1077         if (!options.dsptones)
1078         {
1079                 nodsp:
1080                 if (p_m_tone)
1081                 if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1082                 {
1083                         PDEBUG(DEBUG_ISDN, "we reset tone from id=%d to OFF.\n", p_m_tone);
1084                         ph_control(p_m_mISDNport, this, p_m_mISDNport->b_addr[p_m_b_index], TONE_PATT_OFF, 0, "DSP-TONE", 0);
1085                 }
1086                 p_m_tone = 0;
1087                 Port::set_tone(dir, tone);
1088                 return;
1089         }
1090         if (p_tone_dir[0])
1091                 goto nodsp;
1092
1093         /* now we USE dsp-tone, convert name */
1094         else if (!strcmp(tone, "dialtone"))
1095         {
1096                 switch(options.dsptones) {
1097                 case DSP_AMERICAN: id = TONE_AMERICAN_DIALTONE; break;
1098                 case DSP_GERMAN: id = TONE_GERMAN_DIALTONE; break;
1099                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDDIALTONE; break;
1100                 }
1101         } else if (!strcmp(tone, "dialpbx"))
1102         {
1103                 switch(options.dsptones) {
1104                 case DSP_AMERICAN: id = TONE_AMERICAN_DIALPBX; break;
1105                 case DSP_GERMAN: id = TONE_GERMAN_DIALPBX; break;
1106                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDDIALPBX; break;
1107                 }
1108         } else if (!strcmp(tone, "ringing"))
1109         {
1110                 switch(options.dsptones) {
1111                 case DSP_AMERICAN: id = TONE_AMERICAN_RINGING; break;
1112                 case DSP_GERMAN: id = TONE_GERMAN_RINGING; break;
1113                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDRINGING; break;
1114                 }
1115         } else if (!strcmp(tone, "ringpbx"))
1116         {
1117                 switch(options.dsptones) {
1118                 case DSP_AMERICAN: id = TONE_AMERICAN_RINGPBX; break;
1119                 case DSP_GERMAN: id = TONE_GERMAN_RINGPBX; break;
1120                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDRINGPBX; break;
1121                 }
1122         } else if (!strcmp(tone, "busy"))
1123         {
1124                 busy:
1125                 switch(options.dsptones) {
1126                 case DSP_AMERICAN: id = TONE_AMERICAN_BUSY; break;
1127                 case DSP_GERMAN: id = TONE_GERMAN_BUSY; break;
1128                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDBUSY; break;
1129                 }
1130         } else if (!strcmp(tone, "release"))
1131         {
1132                 hangup:
1133                 switch(options.dsptones) {
1134                 case DSP_AMERICAN: id = TONE_AMERICAN_HANGUP; break;
1135                 case DSP_GERMAN: id = TONE_GERMAN_HANGUP; break;
1136                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDHANGUP; break;
1137                 }
1138         } else if (!strcmp(tone, "cause_10"))
1139                 goto hangup;
1140         else if (!strcmp(tone, "cause_11"))
1141                 goto busy;
1142         else if (!strcmp(tone, "cause_22"))
1143         {
1144                 switch(options.dsptones) {
1145                 case DSP_AMERICAN: id = TONE_SPECIAL_INFO; break;
1146                 case DSP_GERMAN: id = TONE_GERMAN_GASSENBESETZT; break;
1147                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDBUSY; break;
1148                 }
1149         } else if (!strncmp(tone, "cause_", 6))
1150                 id = TONE_SPECIAL_INFO;
1151         else
1152                 id = TONE_OFF;
1153
1154         /* if we have a tone that is not supported by dsp */
1155         if (id==TONE_OFF && tone[0])
1156                 goto nodsp;
1157
1158         setdsp:
1159         if (p_m_tone != id)
1160         {
1161                 /* set new tone */
1162                 p_m_tone = id;
1163                 PDEBUG(DEBUG_ISDN, "we set tone to id=%d.\n", p_m_tone);
1164                 if (p_m_b_channel)
1165                         if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1166                                 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);
1167         }
1168         /* turn user-space tones off in cases of no tone OR dsp tone */
1169         Port::set_tone("",NULL);
1170 }
1171
1172
1173 /* MESSAGE_mISDNSIGNAL */
1174 //extern struct message *dddebug;
1175 void PmISDN::message_mISDNsignal(unsigned long epoint_id, int message_id, union parameter *param)
1176 {
1177         switch(param->mISDNsignal.message)
1178         {
1179                 case mISDNSIGNAL_VOLUME:
1180                 if (p_m_txvol != param->mISDNsignal.txvol)
1181                 {
1182                         p_m_txvol = param->mISDNsignal.txvol;
1183                         PDEBUG(DEBUG_BCHANNEL, "we change tx-volume to shift=%d.\n", p_m_txvol);
1184                         if (p_m_b_channel)
1185                                 if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1186                                         ph_control(p_m_mISDNport, this, p_m_mISDNport->b_addr[p_m_b_index], VOL_CHANGE_TX, p_m_txvol, "DSP-TXVOL", p_m_txvol);
1187                 } else
1188                         PDEBUG(DEBUG_BCHANNEL, "we already have tx-volume shift=%d.\n", p_m_rxvol);
1189                 if (p_m_rxvol != param->mISDNsignal.rxvol)
1190                 {
1191                         p_m_rxvol = param->mISDNsignal.rxvol;
1192                         PDEBUG(DEBUG_BCHANNEL, "we change rx-volume to shift=%d.\n", p_m_rxvol);
1193                         if (p_m_b_channel)
1194                                 if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1195                                         ph_control(p_m_mISDNport, this, p_m_mISDNport->b_addr[p_m_b_index], VOL_CHANGE_RX, p_m_rxvol, "DSP-RXVOL", p_m_rxvol);
1196                 } else
1197                         PDEBUG(DEBUG_BCHANNEL, "we already have rx-volume shift=%d.\n", p_m_rxvol);
1198                 break;
1199
1200                 case mISDNSIGNAL_CONF:
1201 //if (dddebug) PDEBUG(DEBUG_ISDN, "dddebug = %d\n", dddebug->type);
1202 //tone          if (!p_m_tone && p_m_conf!=param->mISDNsignal.conf)
1203                 if (p_m_conf != param->mISDNsignal.conf)
1204                 {
1205                         p_m_conf = param->mISDNsignal.conf;
1206                         PDEBUG(DEBUG_BCHANNEL, "we change conference to conf=%d.\n", p_m_conf);
1207                         if (p_m_b_channel)
1208                                 if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1209                                         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);
1210                 } else
1211                         PDEBUG(DEBUG_BCHANNEL, "we already have conf=%d.\n", p_m_conf);
1212                 /* we must set, even if currently tone forbids conf */
1213                 p_m_conf = param->mISDNsignal.conf;
1214 //if (dddebug) PDEBUG(DEBUG_ISDN, "dddebug = %d\n", dddebug->type);
1215                 break;
1216
1217                 case mISDNSIGNAL_JOINDATA:
1218                 if (p_m_joindata != param->mISDNsignal.joindata)
1219                 {
1220                         p_m_joindata = param->mISDNsignal.joindata;
1221                         PDEBUG(DEBUG_BCHANNEL, "we change to joindata=%d.\n", p_m_joindata);
1222                 } else
1223                         PDEBUG(DEBUG_BCHANNEL, "we already have joindata=%d.\n", p_m_joindata);
1224                 break;
1225                 
1226                 case mISDNSIGNAL_DELAY:
1227                 if (p_m_delay != param->mISDNsignal.delay)
1228                 {
1229                         p_m_delay = param->mISDNsignal.delay;
1230                         PDEBUG(DEBUG_BCHANNEL, "we change delay mode to delay=%d.\n", p_m_delay);
1231                         if (p_m_b_channel)
1232                                 if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1233                                         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);
1234                 } else
1235                         PDEBUG(DEBUG_BCHANNEL, "we already have delay=%d.\n", p_m_delay);
1236                 break;
1237
1238                 default:
1239                 PERROR("PmISDN(%s) unsupported signal message %d.\n", p_name, param->mISDNsignal.message);
1240         }
1241 }
1242
1243 /* MESSAGE_CRYPT */
1244 void PmISDN::message_crypt(unsigned long epoint_id, int message_id, union parameter *param)
1245 {
1246         struct message *message;
1247
1248         switch(param->crypt.type)
1249         {
1250                 case CC_ACTBF_REQ:           /* activate blowfish */
1251                 p_m_crypt = 1;
1252                 p_m_crypt_key_len = param->crypt.len;
1253                 if (p_m_crypt_key_len > (int)sizeof(p_m_crypt_key))
1254                 {
1255                         PERROR("PmISDN(%s) key too long %d > %d\n", p_name, p_m_crypt_key_len, sizeof(p_m_crypt_key));
1256                         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CRYPT);
1257                         message->param.crypt.type = CC_ERROR_IND;
1258                         message_put(message);
1259                         break;
1260                 }
1261                 memcpy(p_m_crypt_key, param->crypt.data, p_m_crypt_key_len);
1262                 crypt_off:
1263                 PDEBUG(DEBUG_BCHANNEL, "we set encryption to crypt=%d. (0 means OFF)\n", p_m_crypt);
1264                 if (p_m_b_channel)
1265                         if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1266                                 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);
1267                 break;
1268
1269                 case CC_DACT_REQ:            /* deactivate session encryption */
1270                 p_m_crypt = 0;
1271                 goto crypt_off;
1272                 break;
1273
1274                 case CR_LISTEN_REQ:          /* start listening to messages */
1275                 p_m_crypt_listen = 1;
1276                 p_m_crypt_listen_state = 0;
1277                 break;
1278
1279                 case CR_UNLISTEN_REQ:        /* stop listening to messages */
1280                 p_m_crypt_listen = 0;
1281                 break;
1282
1283                 case CR_MESSAGE_REQ:         /* send message */
1284                 p_m_crypt_msg_len = cryptman_encode_bch(param->crypt.data, param->crypt.len, p_m_crypt_msg, sizeof(p_m_crypt_msg));
1285                 if (!p_m_crypt_msg_len)
1286                 {
1287                         PERROR("PmISDN(%s) message too long %d > %d\n", p_name, param->crypt.len-1, sizeof(p_m_crypt_msg));
1288                         break;
1289                 }
1290                 p_m_crypt_msg_current = 0; /* reset */
1291                 p_m_crypt_msg_loops = 3; /* enable */
1292 #if 0
1293                 /* disable txmix, or we get corrupt data due to audio process */
1294                 if (p_m_txmix)
1295                 {
1296                         PDEBUG(DEBUG_BCHANNEL, "for sending CR_MESSAGE_REQ, we reset txmix from txmix=%d.\n", p_m_txmix);
1297                         ph_control(p_m_mISDNport, this, p_mISDNport->b_addr[p_m_b_index], CMX_MIX_OFF, 0, "DSP-TXMIX", 0);
1298                 }
1299 #endif
1300                 break;
1301
1302                 default:
1303                 PERROR("PmISDN(%s) unknown crypt message %d\n", p_name, param->crypt.type);
1304         }
1305
1306 }
1307
1308 /*
1309  * endpoint sends messages to the port
1310  */
1311 int PmISDN::message_epoint(unsigned long epoint_id, int message_id, union parameter *param)
1312 {
1313         if (Port::message_epoint(epoint_id, message_id, param))
1314                 return(1);
1315
1316         switch(message_id)
1317         {
1318                 case MESSAGE_DATA: /* tx-data from upper layer */
1319                 txfromup(param->data.data, param->data.len);
1320                 return(1);
1321
1322                 case MESSAGE_mISDNSIGNAL: /* user command */
1323                 PDEBUG(DEBUG_ISDN, "PmISDN(%s) received special ISDN SIGNAL %d.\n", p_name, param->mISDNsignal.message);
1324                 message_mISDNsignal(epoint_id, message_id, param);
1325                 return(1);
1326
1327                 case MESSAGE_CRYPT: /* crypt control command */
1328                 PDEBUG(DEBUG_ISDN, "PmISDN(%s) received encryption command '%d'.\n", p_name, param->crypt.type);
1329                 message_crypt(epoint_id, message_id, param);
1330                 return(1);
1331         }
1332
1333         return(0);
1334 }
1335
1336
1337 /*
1338  * main loop for processing messages from mISDN device
1339  */
1340 int mISDN_handler(void)
1341 {
1342         int ret;
1343         msg_t *msg;
1344         iframe_t *frm;
1345         struct mISDNport *mISDNport;
1346         class PmISDN *isdnport;
1347         net_stack_t *nst;
1348         msg_t *dmsg;
1349         mISDNuser_head_t *hh;
1350         int i;
1351
1352         /* the que avoids loopbacks when replying to stack after receiving
1353          * from stack. */
1354         mISDNport = mISDNport_first;
1355         while(mISDNport)
1356         {
1357                 /* process turning on/off rx */
1358                 i = 0;
1359                 while(i < mISDNport->b_num)
1360                 {
1361                         isdnport=mISDNport->b_port[i];
1362                         if (isdnport)
1363                         {
1364                                 /* call bridges in user space OR crypto OR recording */
1365                                 if (isdnport->p_m_joindata || isdnport->p_m_crypt_msg_loops || isdnport->p_m_crypt_listen || isdnport->p_record)
1366                                 {
1367                                         /* rx IS required */
1368                                         if (isdnport->p_m_rxoff)
1369                                         {
1370                                                 /* turn on RX */
1371                                                 isdnport->p_m_rxoff = 0;
1372                                                 PDEBUG(DEBUG_BCHANNEL, "%s: receive data is required, so we turn them on\n");
1373                                                 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
1374                                                         ph_control(mISDNport, isdnport, mISDNport->b_addr[isdnport->p_m_b_index], CMX_RECEIVE_ON, 0, "DSP-RXOFF", 0);
1375                                                 return(1);
1376                                         }
1377                                 } else
1378                                 {
1379                                         /* rx NOT required */
1380                                         if (!isdnport->p_m_rxoff)
1381                                         {
1382                                                 /* turn off RX */
1383                                                 isdnport->p_m_rxoff = 1;
1384                                                 PDEBUG(DEBUG_BCHANNEL, "%s: receive data is not required, so we turn them off\n");
1385                                                 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
1386                                                         ph_control(mISDNport, isdnport, mISDNport->b_addr[isdnport->p_m_b_index], CMX_RECEIVE_OFF, 0, "DSP-RXOFF", 1);
1387                                                 return(1);
1388                                         }
1389                                 }
1390                                 /* recording */
1391                                 if (isdnport->p_record)
1392                                 {
1393                                         /* txdata IS required */
1394                                         if (!isdnport->p_m_txdata)
1395                                         {
1396                                                 /* turn on RX */
1397                                                 isdnport->p_m_txdata = 1;
1398                                                 PDEBUG(DEBUG_BCHANNEL, "%s: transmit data is required, so we turn them on\n");
1399                                                 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
1400                                                         ph_control(mISDNport, isdnport, mISDNport->b_addr[isdnport->p_m_b_index], CMX_TXDATA_ON, 0, "DSP-TXDATA", 1);
1401                                                 return(1);
1402                                         }
1403                                 } else
1404                                 {
1405                                         /* txdata NOT required */
1406                                         if (isdnport->p_m_txdata)
1407                                         {
1408                                                 /* turn off RX */
1409                                                 isdnport->p_m_txdata = 0;
1410                                                 PDEBUG(DEBUG_BCHANNEL, "%s: transmit data is not required, so we turn them off\n");
1411                                                 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
1412                                                         ph_control(mISDNport, isdnport, mISDNport->b_addr[isdnport->p_m_b_index], CMX_TXDATA_OFF, 0, "DSP-TXDATA", 0);
1413                                                 return(1);
1414                                         }
1415                                 }
1416                         }
1417                         i++;
1418                 }
1419 #if 0
1420                 if (mISDNport->l1timeout && now>mISDNport->l1timeout)
1421                 {
1422                         PDEBUG(DEBUG_ISDN, "the L1 establish timer expired, we release all pending messages.\n", mISDNport->portnum);
1423                         mISDNport->l1timeout = 0;
1424 #endif
1425
1426                 if (mISDNport->l2establish)
1427                 {
1428                         if (now-mISDNport->l2establish > 5)
1429                         {
1430                                 if (mISDNport->ntmode)
1431                                 {
1432                                         PDEBUG(DEBUG_ISDN, "the L2 establish timer expired, we try to establish the link NT portnum=%d.\n", mISDNport->portnum);
1433                                         time(&mISDNport->l2establish);
1434                                         /* establish */
1435                                         dmsg = create_l2msg(DL_ESTABLISH | REQUEST, 0, 0);
1436                                         if (mISDNport->nst.manager_l3(&mISDNport->nst, dmsg))
1437                                                 free_msg(dmsg);
1438                                 } else {
1439                                         PDEBUG(DEBUG_ISDN, "the L2 establish timer expired, we try to establish the link TE portnum=%d.\n", mISDNport->portnum);
1440                                         time(&mISDNport->l2establish);
1441                                         /* establish */
1442                                         iframe_t act;
1443                                         act.prim = DL_ESTABLISH | REQUEST; 
1444                                         act.addr = (mISDNport->upper_id & ~LAYER_ID_MASK) | 3 | FLG_MSG_DOWN;
1445                                         act.dinfo = 0;
1446                                         act.len = 0;
1447                                         mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
1448                                 }
1449                                 l1l2l3_trace_header(mISDNport, NULL, DL_ESTABLISH | REQUEST, DIRECTION_OUT);
1450                                 end_trace();
1451                                 return(1);
1452                         }
1453                 }
1454                 if ((dmsg = msg_dequeue(&mISDNport->downqueue)))
1455                 {
1456                         if (mISDNport->ntmode)
1457                         {
1458                                 hh = (mISDNuser_head_t *)dmsg->data;
1459                                 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);
1460                                 if (mISDNport->nst.manager_l3(&mISDNport->nst, dmsg))
1461                                         free_msg(dmsg);
1462                         } else
1463                         {
1464                                 frm = (iframe_t *)dmsg->data;
1465                                 frm->addr = mISDNport->upper_id | FLG_MSG_DOWN;
1466                                 frm->len = (dmsg->len) - mISDN_HEADER_LEN;
1467                                 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);
1468                                 mISDN_write(mISDNdevice, dmsg->data, dmsg->len, TIMEOUT_1SEC);
1469                                 free_msg(dmsg);
1470                         }
1471                         return(1);
1472                 }
1473                 mISDNport = mISDNport->next;
1474         } 
1475
1476         /* no device, no read */
1477         if (mISDNdevice < 0)
1478                 return(0);
1479
1480         /* get message from kernel */
1481         if (!(msg = alloc_msg(MAX_MSG_SIZE)))
1482                 return(1);
1483         ret = mISDN_read(mISDNdevice, msg->data, MAX_MSG_SIZE, 0);
1484         if (ret < 0)
1485         {
1486                 free_msg(msg);
1487                 if (errno == EAGAIN)
1488                         return(0);
1489                 FATAL("Failed to do mISDN_read()\n");
1490         }
1491         if (!ret)
1492         {
1493                 free_msg(msg);
1494 //              printf("%s: ERROR: mISDN_read() returns nothing\n");
1495                 return(0);
1496         }
1497         msg->len = ret;
1498         frm = (iframe_t *)msg->data;
1499
1500         /* global prim */
1501         switch(frm->prim)
1502         {
1503                 case MGR_DELLAYER | CONFIRM:
1504                 case MGR_INITTIMER | CONFIRM:
1505                 case MGR_ADDTIMER | CONFIRM:
1506                 case MGR_DELTIMER | CONFIRM:
1507                 case MGR_REMOVETIMER | CONFIRM:
1508                 free_msg(msg);
1509                 return(1);
1510         }
1511
1512         /* handle timer events from mISDN for NT-stack
1513          * note: they do not associate with a stack */
1514         if (frm->prim == (MGR_TIMER | INDICATION))
1515         {
1516                 itimer_t *it;
1517
1518                 /* find mISDNport */
1519                 mISDNport = mISDNport_first;
1520                 while(mISDNport)
1521                 {
1522                         /* nt mode only */
1523                         if (mISDNport->ntmode)
1524                         {
1525                                 it = mISDNport->nst.tlist;
1526                                 /* find timer */
1527                                 while(it)
1528                                 {
1529                                         if (it->id == (int)frm->addr)
1530                                                 break;
1531                                         it = it->next;
1532                                 }
1533                                 if (it)
1534                                         break;
1535                         }
1536                         mISDNport = mISDNport->next;
1537                 }
1538                 if (mISDNport)
1539                 {
1540                         mISDN_write_frame(mISDNdevice, msg->data, mISDNport->upper_id | FLG_MSG_DOWN,
1541                                 MGR_TIMER | RESPONSE, 0, 0, NULL, TIMEOUT_1SEC);
1542
1543                         PDEBUG(DEBUG_ISDN, "timer-indication port %d it=%p\n", mISDNport->portnum, it);
1544                         test_and_clear_bit(FLG_TIMER_RUNING, (long unsigned int *)&it->Flags);
1545                         ret = it->function(it->data);
1546                 } else
1547                 {
1548                         PDEBUG(DEBUG_ISDN, "timer-indication not handled\n");
1549                 }
1550                 goto out;
1551         }
1552
1553         /* find the mISDNport that belongs to the stack */
1554         mISDNport = mISDNport_first;
1555         while(mISDNport)
1556         {
1557                 if ((frm->addr&MASTER_ID_MASK) == (unsigned int)(mISDNport->upper_id&MASTER_ID_MASK))
1558                         break;
1559                 mISDNport = mISDNport->next;
1560         } 
1561         if (!mISDNport)
1562         {
1563                 PERROR("message belongs to no mISDNport: prim(0x%x) addr(0x%x) msg->len(%d)\n", frm->prim, frm->addr, msg->len);
1564                 goto out;
1565         }
1566
1567         /* master stack */
1568         if (!(frm->addr&FLG_CHILD_STACK))
1569         {
1570                 /* d-message */
1571                 switch(frm->prim)
1572                 {
1573                         case MGR_SHORTSTATUS | INDICATION:
1574                         case MGR_SHORTSTATUS | CONFIRM:
1575                         switch(frm->dinfo) {
1576                                 case SSTATUS_L1_ACTIVATED:
1577                                 l1l2l3_trace_header(mISDNport, NULL, PH_ACTIVATE | (frm->prim & 0x3), DIRECTION_IN);
1578                                 end_trace();
1579                                 goto ss_act;
1580                                 case SSTATUS_L1_DEACTIVATED:
1581                                 l1l2l3_trace_header(mISDNport, NULL, PH_DEACTIVATE | (frm->prim & 0x3), DIRECTION_IN);
1582                                 end_trace();
1583                                 goto ss_deact;
1584                                 case SSTATUS_L2_ESTABLISHED:
1585                                 l1l2l3_trace_header(mISDNport, NULL, DL_ESTABLISH | (frm->prim & 0x3), DIRECTION_IN);
1586                                 end_trace();
1587                                 goto ss_estab;
1588                                 case SSTATUS_L2_RELEASED:
1589                                 l1l2l3_trace_header(mISDNport, NULL, DL_RELEASE | (frm->prim & 0x3), DIRECTION_IN);
1590                                 end_trace();
1591                                 goto ss_rel;
1592                         }
1593                         break;
1594
1595                         case PH_ACTIVATE | CONFIRM:
1596                         case PH_ACTIVATE | INDICATION:
1597                         l1l2l3_trace_header(mISDNport, NULL, frm->prim, DIRECTION_IN);
1598                         end_trace();
1599                         if (mISDNport->ntmode)
1600                         {
1601                                 mISDNport->l1link = 1;
1602                                 setup_queue(mISDNport, 1);
1603                                 goto l1_msg;
1604                         }
1605                         ss_act:
1606                         mISDNport->l1link = 1;
1607                         setup_queue(mISDNport, 1);
1608                         break;
1609
1610                         case PH_DEACTIVATE | CONFIRM:
1611                         case PH_DEACTIVATE | INDICATION:
1612                         l1l2l3_trace_header(mISDNport, NULL, frm->prim, DIRECTION_IN);
1613                         end_trace();
1614                         if (mISDNport->ntmode)
1615                         {
1616                                 mISDNport->l1link = 0;
1617                                 setup_queue(mISDNport, 0);
1618                                 goto l1_msg;
1619                         }
1620                         ss_deact:
1621                         mISDNport->l1link = 0;
1622                         setup_queue(mISDNport, 0);
1623                         break;
1624
1625                         case PH_CONTROL | CONFIRM:
1626                         case PH_CONTROL | INDICATION:
1627                         PDEBUG(DEBUG_ISDN, "Received PH_CONTROL for port %d (%s).\n", mISDNport->portnum, mISDNport->ifport->interface->name);
1628                         break;
1629
1630                         case DL_ESTABLISH | INDICATION:
1631                         case DL_ESTABLISH | CONFIRM:
1632                         l1l2l3_trace_header(mISDNport, NULL, frm->prim, DIRECTION_IN);
1633                         end_trace();
1634                         if (!mISDNport->ntmode) break; /* !!!!!!!!!!!!!!!! */
1635                         ss_estab:
1636                         if (mISDNport->l2establish)
1637                         {
1638                                 mISDNport->l2establish = 0;
1639                                 PDEBUG(DEBUG_ISDN, "the link became active before l2establish timer expiry.\n");
1640                         }
1641                         mISDNport->l2link = 1;
1642                         break;
1643
1644                         case DL_RELEASE | INDICATION:
1645                         case DL_RELEASE | CONFIRM:
1646                         l1l2l3_trace_header(mISDNport, NULL, frm->prim, DIRECTION_IN);
1647                         end_trace();
1648                         if (!mISDNport->ntmode) break; /* !!!!!!!!!!!!!!!! */
1649                         ss_rel:
1650                         mISDNport->l2link = 0;
1651                         if (mISDNport->ptp)
1652                         {
1653                                 time(&mISDNport->l2establish);
1654                                 PDEBUG(DEBUG_ISDN, "because we are ptp, we set a l2establish timer.\n");
1655                         }
1656                         break;
1657
1658                         default:
1659                         l1_msg:
1660                         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);
1661                         if (frm->dinfo==(signed long)0xffffffff && frm->prim==(PH_DATA|CONFIRM))
1662                         {
1663                                 PERROR("SERIOUS BUG, dinfo == 0xffffffff, prim == PH_DATA | CONFIRM !!!!\n");
1664                         }
1665                         /* d-message */
1666                         if (mISDNport->ntmode)
1667                         {
1668                                 /* l1-data enters the nt-mode library */
1669                                 nst = &mISDNport->nst;
1670                                 if (nst->l1_l2(nst, msg))
1671                                         free_msg(msg);
1672                                 return(1);
1673                         } else
1674                         {
1675                                 /* l3-data is sent to pbx */
1676                                 if (stack2manager_te(mISDNport, msg))
1677                                         free_msg(msg);
1678                                 return(1);
1679                         }
1680                 }
1681         } else
1682         /* child stack */
1683         {
1684                 /* b-message */
1685                 switch(frm->prim)
1686                 {
1687                         /* we don't care about confirms, we use rx data to sync tx */
1688                         case PH_DATA | CONFIRM:
1689                         case DL_DATA | CONFIRM:
1690                         break;
1691
1692                         /* we receive audio data, we respond to it AND we send tones */
1693                         case PH_DATA | INDICATION:
1694                         case DL_DATA | INDICATION:
1695                         case PH_CONTROL | INDICATION:
1696                         i = 0;
1697                         while(i < mISDNport->b_num)
1698                         {
1699                                 if ((unsigned int)(mISDNport->b_addr[i]&STACK_ID_MASK) == (frm->addr&STACK_ID_MASK))
1700                                         break;
1701                                 i++;
1702                         }
1703                         if (i == mISDNport->b_num)
1704                         {
1705                                 PERROR("unhandled b-message (prim 0x%x address 0x%x).\n", frm->prim, frm->addr);
1706                                 break;
1707                         }
1708                         if (mISDNport->b_port[i])
1709                         {
1710 //PERROR("port sech: %s data\n", mISDNport->b_port[i]->p_name);
1711                                 mISDNport->b_port[i]->bchannel_receive(frm);
1712                         } else
1713                                 PDEBUG(DEBUG_BCHANNEL, "b-channel is not associated to an ISDNPort (address 0x%x), ignoring.\n", frm->addr);
1714                         break;
1715
1716                         case PH_ACTIVATE | INDICATION:
1717                         case DL_ESTABLISH | INDICATION:
1718                         case PH_ACTIVATE | CONFIRM:
1719                         case DL_ESTABLISH | CONFIRM:
1720                         PDEBUG(DEBUG_BCHANNEL, "DL_ESTABLISH confirm: bchannel is now activated (address 0x%x).\n", frm->addr);
1721                         i = 0;
1722                         while(i < mISDNport->b_num)
1723                         {
1724                                 if ((unsigned int)(mISDNport->b_addr[i]&STACK_ID_MASK) == (frm->addr&STACK_ID_MASK))
1725                                         break;
1726                                 i++;
1727                         }
1728                         if (i == mISDNport->b_num)
1729                         {
1730                                 PERROR("unhandled b-establish (prim 0x%x address 0x%x).\n", frm->prim, frm->addr);
1731                                 break;
1732                         }
1733                         bchannel_event(mISDNport, i, B_EVENT_ACTIVATED);
1734                         break;
1735
1736                         case PH_DEACTIVATE | INDICATION:
1737                         case DL_RELEASE | INDICATION:
1738                         case PH_DEACTIVATE | CONFIRM:
1739                         case DL_RELEASE | CONFIRM:
1740                         PDEBUG(DEBUG_BCHANNEL, "DL_RELEASE confirm: bchannel is now de-activated (address 0x%x).\n", frm->addr);
1741                         i = 0;
1742                         while(i < mISDNport->b_num)
1743                         {
1744                                 if ((unsigned int)(mISDNport->b_addr[i]&STACK_ID_MASK) == (frm->addr&STACK_ID_MASK))
1745                                         break;
1746                                 i++;
1747                         }
1748                         if (i == mISDNport->b_num)
1749                         {
1750                                 PERROR("unhandled b-release (prim 0x%x address 0x%x).\n", frm->prim, frm->addr);
1751                                 break;
1752                         }
1753                         bchannel_event(mISDNport, i, B_EVENT_DEACTIVATED);
1754                         break;
1755
1756                         default:
1757                         PERROR("child message not handled: prim(0x%x) addr(0x%x) msg->len(%d)\n", frm->prim, frm->addr, msg->len);
1758                 }
1759         }
1760
1761         out:
1762         free_msg(msg);
1763         return(1);
1764 }
1765
1766
1767 /*
1768  * global function to add a new card (port)
1769  */
1770 struct mISDNport *mISDNport_open(int port, int ptp, int ptmp, struct interface *interface)
1771 {
1772         int ret;
1773         unsigned char buff[1025];
1774         iframe_t *frm = (iframe_t *)buff;
1775         stack_info_t *stinf;
1776         struct mISDNport *mISDNport, **mISDNportp;
1777         int i, cnt;
1778 //      interface_info_t ii;
1779         net_stack_t *nst;
1780         manager_t *mgr;
1781         layer_info_t li;
1782         int pri = 0;
1783         int nt = 0;
1784
1785         /* open mISDNdevice if not already open */
1786         if (mISDNdevice < 0)
1787         {
1788                 ret = mISDN_open();
1789                 if (ret < 0)
1790                 {
1791                         PERROR("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));
1792                         return(NULL);
1793                 }
1794                 mISDNdevice = ret;
1795                 PDEBUG(DEBUG_ISDN, "mISDN device opened.\n");
1796
1797                 /* create entity for layer 3 TE-mode */
1798                 mISDN_write_frame(mISDNdevice, buff, 0, MGR_NEWENTITY | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
1799                 ret = mISDN_read_frame(mISDNdevice, frm, sizeof(iframe_t), 0, MGR_NEWENTITY | CONFIRM, TIMEOUT_1SEC);
1800                 if (ret < (int)mISDN_HEADER_LEN)
1801                 {
1802                         noentity:
1803                         FATAL("Cannot request MGR_NEWENTITY from mISDN. Exitting due to software bug.");
1804                 }
1805                 entity = frm->dinfo & 0xffff;
1806                 if (!entity)
1807                         goto noentity;
1808                 PDEBUG(DEBUG_ISDN, "our entity for l3-processes is %d.\n", entity);
1809         }
1810
1811         /* query port's requirements */
1812         cnt = mISDN_get_stack_count(mISDNdevice);
1813         if (cnt <= 0)
1814         {
1815                 PERROR("Found no card. Please be sure to load card drivers.\n");
1816                 return(NULL);
1817         }
1818         if (port>cnt || port<1)
1819         {
1820                 PERROR("Port (%d) given at 'ports' (options.conf) is out of existing port range (%d-%d)\n", port, 1, cnt);
1821                 return(NULL);
1822         }
1823         ret = mISDN_get_stack_info(mISDNdevice, port, buff, sizeof(buff));
1824         if (ret < 0)
1825         {
1826                 PERROR("Cannot get stack info for port %d (ret=%d)\n", port, ret);
1827                 return(NULL);
1828         }
1829         stinf = (stack_info_t *)&frm->data.p;
1830         switch(stinf->pid.protocol[0] & ~ISDN_PID_FEATURE_MASK)
1831         {
1832                 case ISDN_PID_L0_TE_S0:
1833                 PDEBUG(DEBUG_ISDN, "TE-mode BRI S/T interface line\n");
1834                 break;
1835                 case ISDN_PID_L0_NT_S0:
1836                 PDEBUG(DEBUG_ISDN, "NT-mode BRI S/T interface port\n");
1837                 nt = 1;
1838                 break;
1839                 case ISDN_PID_L0_TE_E1:
1840                 PDEBUG(DEBUG_ISDN, "TE-mode PRI E1  interface line\n");
1841                 pri = 1;
1842                 break;
1843                 case ISDN_PID_L0_NT_E1:
1844                 PDEBUG(DEBUG_ISDN, "LT-mode PRI E1  interface port\n");
1845                 pri = 1;
1846                 nt = 1;
1847                 break;
1848                 default:
1849                 PERROR("unknown port(%d) type 0x%08x\n", port, stinf->pid.protocol[0]);
1850                 return(NULL);
1851         }
1852         if (nt)
1853         {
1854                 /* NT */
1855                 if (stinf->pid.protocol[1] == 0)
1856                 {
1857                         PERROR("Given port %d: Missing layer 1 NT-mode protocol.\n", port);
1858                         return(NULL);
1859                 }
1860                 if (stinf->pid.protocol[2])
1861                 {
1862                         PERROR("Given port %d: Layer 2 protocol 0x%08x is detected, but not allowed for NT lib.\n", port, stinf->pid.protocol[2]);
1863                         return(NULL);
1864                 }
1865         } else
1866         {
1867                 /* TE */
1868                 if (stinf->pid.protocol[1] == 0)
1869                 {
1870                         PERROR("Given port %d: Missing layer 1 protocol.\n", port);
1871                         return(NULL);
1872                 }
1873                 if (stinf->pid.protocol[2] == 0)
1874                 {
1875                         PERROR("Given port %d: Missing layer 2 protocol.\n", port);
1876                         return(NULL);
1877                 }
1878                 if (stinf->pid.protocol[3] == 0)
1879                 {
1880                         PERROR("Given port %d: Missing layer 3 protocol.\n", port);
1881                         return(NULL);
1882                 } else
1883                 {
1884                         switch(stinf->pid.protocol[3] & ~ISDN_PID_FEATURE_MASK)
1885                         {
1886                                 case ISDN_PID_L3_DSS1USER:
1887                                 break;
1888
1889                                 default:
1890                                 PERROR("Given port %d: own protocol 0x%08x", port,stinf->pid.protocol[3]);
1891                                 return(NULL);
1892                         }
1893                 }
1894                 if (stinf->pid.protocol[4])
1895                 {
1896                         PERROR("Given port %d: Layer 4 protocol not allowed.\n", port);
1897                         return(NULL);
1898                 }
1899         }
1900
1901         /* add mISDNport structure */
1902         mISDNportp = &mISDNport_first;
1903         while(*mISDNportp)
1904                 mISDNportp = &((*mISDNportp)->next);
1905         mISDNport = (struct mISDNport *)MALLOC(sizeof(struct mISDNport));
1906         pmemuse++;
1907         *mISDNportp = mISDNport;
1908
1909         /* allocate ressources of port */
1910         msg_queue_init(&mISDNport->downqueue);
1911 //      SCPY(mISDNport->name, "noname");
1912         mISDNport->portnum = port;
1913         mISDNport->ntmode = nt;
1914         mISDNport->pri = pri;
1915         mISDNport->d_stid = stinf->id;
1916         PDEBUG(DEBUG_ISDN, "d_stid = 0x%x.\n", mISDNport->d_stid);
1917         mISDNport->b_num = stinf->childcnt;
1918         PDEBUG(DEBUG_ISDN, "Port has %d b-channels.\n", mISDNport->b_num);
1919         if ((stinf->pid.protocol[2]&ISDN_PID_L2_DF_PTP) || (nt&&ptp) || pri)
1920         {
1921                 PDEBUG(DEBUG_ISDN, "Port is point-to-point.\n");
1922                 mISDNport->ptp = ptp = 1;
1923                 if (ptmp && nt)
1924                 {
1925                         PDEBUG(DEBUG_ISDN, "Port is forced to point-to-multipoint.\n");
1926                         mISDNport->ptp = ptp = 0;
1927                 }
1928         }
1929         i = 0;
1930         while(i < stinf->childcnt)
1931         {
1932                 mISDNport->b_stid[i] = stinf->child[i];
1933                 mISDNport->b_state[i] = B_STATE_IDLE;
1934                 PDEBUG(DEBUG_ISDN, "b_stid[%d] = 0x%x.\n", i, mISDNport->b_stid[i]);
1935                 i++;
1936         }
1937         memset(&li, 0, sizeof(li));
1938         UCPY(&li.name[0], (nt)?"net l2":"pbx l4");
1939         li.object_id = -1;
1940         li.extentions = 0;
1941         li.pid.protocol[nt?2:4] = (nt)?ISDN_PID_L2_LAPD_NET:ISDN_PID_L4_CAPI20;
1942         li.pid.layermask = ISDN_LAYER((nt?2:4));
1943         li.st = mISDNport->d_stid;
1944         ret = mISDN_new_layer(mISDNdevice, &li);
1945         if (ret)
1946         {
1947                 PERROR("Cannot add layer %d of port %d (ret %d)\n", nt?2:4, port, ret);
1948                 closeport:
1949                 mISDNport_close(mISDNport);
1950                 return(NULL);
1951         }
1952         mISDNport->upper_id = li.id;
1953         ret = mISDN_register_layer(mISDNdevice, mISDNport->d_stid, mISDNport->upper_id);
1954         if (ret)
1955         {
1956                 PERROR("Cannot register layer %d of port %d\n", nt?2:4, port);
1957                 goto closeport;
1958         }
1959         mISDNport->lower_id = mISDN_get_layerid(mISDNdevice, mISDNport->d_stid, nt?1:3); // id of lower layer (nt=1, te=3)
1960         if (mISDNport->lower_id < 0)
1961         {
1962                 PERROR("Cannot get layer(%d) id of port %d\n", nt?1:3, port);
1963                 goto closeport;
1964         }
1965         mISDNport->upper_id = mISDN_get_layerid(mISDNdevice, mISDNport->d_stid, nt?2:4); // id of uppermost layer (nt=2, te=4)
1966         if (mISDNport->upper_id < 0)
1967         {
1968                 PERROR("Cannot get layer(%d) id of port %d\n", nt?2:4, port);
1969                 goto closeport;
1970         }
1971         PDEBUG(DEBUG_ISDN, "Layer %d of port %d added.\n", nt?2:4, port);
1972
1973         /* if ntmode, establish L1 to send the tei removal during start */
1974         if (mISDNport->ntmode)
1975         {
1976                 iframe_t act;
1977                 /* L1 */
1978                 act.prim = PH_ACTIVATE | REQUEST; 
1979                 act.addr = mISDNport->upper_id | FLG_MSG_DOWN;
1980                 printf("UPPER ID 0x%x, addr 0x%x\n",mISDNport->upper_id, act.addr);
1981                 act.dinfo = 0;
1982                 act.len = 0;
1983                 mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
1984                 usleep(10000); /* to be sure, that l1 is up */
1985         }
1986
1987         /* create nst (nt-mode only) */
1988         if (nt)
1989         {
1990                 mgr = &mISDNport->mgr;
1991                 nst = &mISDNport->nst;
1992
1993                 mgr->nst = nst;
1994                 nst->manager = mgr;
1995
1996                 nst->l3_manager = stack2manager_nt; /* messages from nt-mode */
1997                 nst->device = mISDNdevice;
1998                 nst->cardnr = port;
1999                 nst->d_stid = mISDNport->d_stid;
2000
2001                 nst->feature = FEATURE_NET_HOLD;
2002                 if (ptp)
2003                         nst->feature |= FEATURE_NET_PTP;
2004                 if (pri)
2005                         nst->feature |= FEATURE_NET_CRLEN2 | FEATURE_NET_EXTCID;
2006 #if 0
2007                 i = 0;
2008                 while(i < mISDNport->b_num)
2009                 {
2010                         nst->b_stid[i] = mISDNport->b_stid[i];
2011                         i++;
2012                 }
2013 #endif
2014                 nst->l1_id = mISDNport->lower_id;
2015                 nst->l2_id = mISDNport->upper_id;
2016
2017                 /* phd */       
2018                 msg_queue_init(&nst->down_queue);
2019
2020                 Isdnl2Init(nst);
2021                 Isdnl3Init(nst);
2022         }
2023
2024         /* if te-mode, query state link */
2025         if (!mISDNport->ntmode)
2026         {
2027                 iframe_t act;
2028                 /* L2 */
2029                 PDEBUG(DEBUG_ISDN, "sending short status request for port %d.\n", port);
2030                 act.prim = MGR_SHORTSTATUS | REQUEST; 
2031                 act.addr = mISDNport->upper_id | MSG_BROADCAST;
2032                 act.dinfo = SSTATUS_BROADCAST_BIT | SSTATUS_ALL;
2033                 act.len = 0;
2034                 mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
2035         }
2036         /* if ptp AND te-mode, pull up the link */
2037         if (mISDNport->ptp && !mISDNport->ntmode)
2038         {
2039                 iframe_t act;
2040                 /* L2 */
2041                 act.prim = DL_ESTABLISH | REQUEST; 
2042                 act.addr = (mISDNport->upper_id & ~LAYER_ID_MASK) | 4 | FLG_MSG_DOWN;
2043                 act.dinfo = 0;
2044                 act.len = 0;
2045                 mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
2046         }
2047         /* if ptp AND nt-mode, pull up the link */
2048         if (mISDNport->ptp && mISDNport->ntmode)
2049         {
2050                 msg_t *dmsg;
2051                 /* L2 */
2052                 dmsg = create_l2msg(DL_ESTABLISH | REQUEST, 0, 0);
2053                 if (mISDNport->nst.manager_l3(&mISDNport->nst, dmsg))
2054                         free_msg(dmsg);
2055         }
2056         /* initially, we assume that the link is down, exept for nt-ptmp */
2057         mISDNport->l2link = (mISDNport->ntmode && !mISDNport->ptp)?1:0;
2058
2059         PDEBUG(DEBUG_BCHANNEL, "using 'mISDN_dsp.o' module\n");
2060
2061         start_trace(mISDNport->portnum,
2062                     interface,
2063                     NULL,
2064                     NULL,
2065                     DIRECTION_NONE,
2066                     CATEGORY_CH,
2067                     0,
2068                     "PORT (open)");
2069         add_trace("channels", NULL, "%d", mISDNport->b_num);
2070         end_trace();
2071         return(mISDNport);
2072 }
2073
2074
2075 /*
2076  * function to free ALL cards (ports)
2077  */
2078 void mISDNport_close_all(void)
2079 {
2080         /* free all ports */
2081         while(mISDNport_first)
2082                 mISDNport_close(mISDNport_first);
2083 }
2084
2085 /*
2086  * free only one port
2087  */
2088 void mISDNport_close(struct mISDNport *mISDNport)
2089 {
2090         struct mISDNport **mISDNportp;
2091         class Port *port;
2092         class PmISDN *isdnport;
2093         net_stack_t *nst;
2094         unsigned char buf[32];
2095         int i;
2096
2097         /* remove all port instance that are linked to this mISDNport */
2098         port = port_first;
2099         while(port)
2100         {
2101                 if ((port->p_type&PORT_CLASS_MASK) == PORT_CLASS_mISDN)
2102                 {
2103                         isdnport = (class PmISDN *)port;
2104                         if (isdnport->p_m_mISDNport)
2105                         {
2106                                 PDEBUG(DEBUG_ISDN, "port %s uses mISDNport %d, destroying it.\n", isdnport->p_name, mISDNport->portnum);
2107                                 delete isdnport;
2108                         }
2109                 }
2110                 port = port->next;
2111         }
2112
2113         /* only if we are already part of interface */
2114         if (mISDNport->ifport)
2115         {
2116                 start_trace(mISDNport->portnum,
2117                             mISDNport->ifport->interface,
2118                             NULL,
2119                             NULL,
2120                             DIRECTION_NONE,
2121                             CATEGORY_CH,
2122                             0,
2123                             "PORT (close)");
2124                 end_trace();
2125         }
2126
2127         /* free bchannels */
2128         i = 0;
2129         while(i < mISDNport->b_num)
2130         {
2131                 if (mISDNport->b_addr[i])
2132                 {
2133                         _bchannel_destroy(mISDNport, i);
2134                         PDEBUG(DEBUG_BCHANNEL, "freeing %s port %d bchannel (index %d).\n", (mISDNport->ntmode)?"NT":"TE", mISDNport->portnum, i);
2135                 }
2136                 i++;
2137         }
2138
2139         /* free ressources of port */
2140         msg_queue_purge(&mISDNport->downqueue);
2141
2142         /* free stacks */
2143         if (mISDNport->ntmode)
2144         {
2145                 nst = &mISDNport->nst;
2146                 if (nst->manager) /* to see if initialized */
2147                 {
2148                         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");
2149                         cleanup_Isdnl3(nst);
2150                         cleanup_Isdnl2(nst);
2151
2152                         /* phd */
2153                         msg_queue_purge(&nst->down_queue);
2154                         if (nst->phd_down_msg)
2155                                 FREE(nst->phd_down_msg, 0);
2156                 }
2157         }
2158
2159         PDEBUG(DEBUG_BCHANNEL, "freeing d-stack.\n");
2160         if (mISDNport->d_stid)
2161         {
2162                 if (mISDNport->upper_id)
2163                         mISDN_write_frame(mISDNdevice, buf, mISDNport->upper_id | FLG_MSG_DOWN, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
2164         }
2165
2166         /* remove from list */
2167         mISDNportp = &mISDNport_first;
2168         while(*mISDNportp)
2169         {
2170                 if (*mISDNportp == mISDNport)
2171                 {
2172                         *mISDNportp = (*mISDNportp)->next;
2173                         mISDNportp = NULL;
2174                         break;
2175                 }
2176                 mISDNportp = &((*mISDNportp)->next);
2177         }
2178
2179         if (mISDNportp)
2180                 FATAL("mISDNport not in list\n");
2181         
2182         FREE(mISDNport, sizeof(struct mISDNport));
2183         pmemuse--;
2184
2185         /* close mISDNdevice, if no port */
2186         if (mISDNdevice>=0 && mISDNport_first==NULL)
2187         {
2188                 /* free entity */
2189                 mISDN_write_frame(mISDNdevice, buf, 0, MGR_DELENTITY | REQUEST, entity, 0, NULL, TIMEOUT_1SEC);
2190                 /* close device */
2191                 mISDN_close(mISDNdevice);
2192                 mISDNdevice = -1;
2193                 PDEBUG(DEBUG_ISDN, "mISDN device closed.\n");
2194         }
2195 }
2196
2197
2198 /*
2199  * global function to show all available isdn ports
2200  */
2201 void mISDN_port_info(void)
2202 {
2203         int err;
2204         int i, ii, p;
2205         int useable, nt, pri;
2206         unsigned char buff[1025];
2207         iframe_t *frm = (iframe_t *)buff;
2208         stack_info_t *stinf;
2209         int device;
2210
2211         /* open mISDN */
2212         if ((device = mISDN_open()) < 0)
2213         {
2214                 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));
2215                 exit(EXIT_FAILURE);
2216         }
2217
2218         /* get number of stacks */
2219         i = 1;
2220         ii = mISDN_get_stack_count(device);
2221         printf("\n");
2222         if (ii <= 0)
2223         {
2224                 printf("Found no card. Please be sure to load card drivers.\n");
2225         }
2226
2227         /* loop the number of cards and get their info */
2228         while(i <= ii)
2229         {
2230                 err = mISDN_get_stack_info(device, i, buff, sizeof(buff));
2231                 if (err <= 0)
2232                 {
2233                         fprintf(stderr, "mISDN_get_stack_info() failed: port=%d err=%d\n", i, err);
2234                         break;
2235                 }
2236                 stinf = (stack_info_t *)&frm->data.p;
2237
2238                 nt = pri = 0;
2239                 useable = 1;
2240
2241                 /* output the port info */
2242                 printf("Port %2d: ", i);
2243                 switch(stinf->pid.protocol[0] & ~ISDN_PID_FEATURE_MASK)
2244                 {
2245                         case ISDN_PID_L0_TE_S0:
2246                         printf("TE-mode BRI S/T interface line (for phone lines)");
2247 #if 0
2248                         if (stinf->pid.protocol[0] & ISDN_PID_L0_TE_S0_HFC & ISDN_PID_FEATURE_MASK)
2249                                 printf(" HFC multiport card");
2250 #endif
2251                         break;
2252                         case ISDN_PID_L0_NT_S0:
2253                         nt = 1;
2254                         printf("NT-mode BRI S/T interface port (for phones)");
2255 #if 0
2256                         if (stinf->pid.protocol[0] & ISDN_PID_L0_NT_S0_HFC & ISDN_PID_FEATURE_MASK)
2257                                 printf(" HFC multiport card");
2258 #endif
2259                         break;
2260                         case ISDN_PID_L0_TE_E1:
2261                         pri = 1;
2262                         printf("TE-mode PRI E1  interface line (for phone lines)");
2263 #if 0
2264                         if (stinf->pid.protocol[0] & ISDN_PID_L0_TE_E1_HFC & ISDN_PID_FEATURE_MASK)
2265                                 printf(" HFC-E1 card");
2266 #endif
2267                         break;
2268                         case ISDN_PID_L0_NT_E1:
2269                         nt = 1;
2270                         pri = 1;
2271                         printf("NT-mode PRI E1  interface port (for phones)");
2272 #if 0
2273                         if (stinf->pid.protocol[0] & ISDN_PID_L0_NT_E1_HFC & ISDN_PID_FEATURE_MASK)
2274                                 printf(" HFC-E1 card");
2275 #endif
2276                         break;
2277                         default:
2278                         useable = 0;
2279                         printf("unknown type 0x%08x",stinf->pid.protocol[0]);
2280                 }
2281                 printf("\n");
2282
2283                 if (nt)
2284                 {
2285                         if (stinf->pid.protocol[1] == 0)
2286                         {
2287                                 useable = 0;
2288                                 printf(" -> Missing layer 1 NT-mode protocol.\n");
2289                         }
2290                         p = 2;
2291                         while(p <= MAX_LAYER_NR) {
2292                                 if (stinf->pid.protocol[p])
2293                                 {
2294                                         useable = 0;
2295                                         printf(" -> Layer %d protocol 0x%08x is detected, port already in use by another application.\n", p, stinf->pid.protocol[p]);
2296                                 }
2297                                 p++;
2298                         }
2299                         if (useable)
2300                         {
2301                                 if (pri)
2302                                         printf(" -> Interface is Point-To-Point (PRI).\n");
2303                                 else
2304                                         printf(" -> Interface can be Poin-To-Point/Multipoint.\n");
2305                         }
2306                 } else
2307                 {
2308                         if (stinf->pid.protocol[1] == 0)
2309                         {
2310                                 useable = 0;
2311                                 printf(" -> Missing layer 1 protocol.\n");
2312                         }
2313                         if (stinf->pid.protocol[2] == 0)
2314                         {
2315                                 useable = 0;
2316                                 printf(" -> Missing layer 2 protocol.\n");
2317                         }
2318                         if (stinf->pid.protocol[2] & ISDN_PID_L2_DF_PTP)
2319                         {
2320                                 printf(" -> Interface is Poin-To-Point.\n");
2321                         }
2322                         if (stinf->pid.protocol[3] == 0)
2323                         {
2324                                 useable = 0;
2325                                 printf(" -> Missing layer 3 protocol.\n");
2326                         } else
2327                         {
2328                                 printf(" -> Protocol: ");
2329                                 switch(stinf->pid.protocol[3] & ~ISDN_PID_FEATURE_MASK)
2330                                 {
2331                                         case ISDN_PID_L3_DSS1USER:
2332                                         printf("DSS1 (Euro ISDN)");
2333                                         break;
2334
2335                                         default:
2336                                         useable = 0;
2337                                         printf("unknown protocol 0x%08x",stinf->pid.protocol[3]);
2338                                 }
2339                                 printf("\n");
2340                         }
2341                         p = 4;
2342                         while(p <= MAX_LAYER_NR) {
2343                                 if (stinf->pid.protocol[p])
2344                                 {
2345                                         useable = 0;
2346                                         printf(" -> Layer %d protocol 0x%08x is detected, port already in use by another application.\n", p, stinf->pid.protocol[p]);
2347                                 }
2348                                 p++;
2349                         }
2350                 }
2351                 printf("  - %d B-channels\n", stinf->childcnt);
2352
2353                 if (!useable)
2354                         printf(" * Port NOT useable for LCR\n");
2355
2356                 printf("--------\n");
2357
2358                 i++;
2359         }
2360         printf("\n");
2361
2362         /* close mISDN */
2363         if ((err = mISDN_close(device)))
2364                 FATAL("mISDN_close() failed: err=%d '%s'\n", err, strerror(err));
2365 }
2366
2367
2368 /*
2369  * enque data from upper buffer
2370  */
2371 void PmISDN::txfromup(unsigned char *data, int length)
2372 {
2373         unsigned char buf[mISDN_HEADER_LEN+((length>ISDN_LOAD)?length:ISDN_LOAD)];
2374         iframe_t *frm = (iframe_t *)buf;
2375
2376         /* configure frame */
2377         frm->prim = DL_DATA | REQUEST; 
2378         frm->addr = p_m_mISDNport->b_addr[p_m_b_index] | FLG_MSG_DOWN;
2379         frm->dinfo = 0;
2380
2381         /* check if high priority tones exist
2382          * ignore data in this case
2383          */
2384         if (p_tone_name[0] || p_m_crypt_msg_loops)
2385                 return;
2386
2387         /* preload procedure
2388          * if transmit buffer in DSP module is empty,
2389          * preload it to DSP_LOAD to prevent jitter gaps.
2390          */
2391         if (p_m_load==0 && ISDN_LOAD>0)
2392         {
2393
2394                 memcpy(buf+mISDN_HEADER_LEN, data, ISDN_LOAD);
2395                 frm->len = ISDN_LOAD;
2396                 mISDN_write(mISDNdevice, frm, mISDN_HEADER_LEN+frm->len, TIMEOUT_1SEC);
2397                 p_m_load += frm->len;
2398         }
2399
2400         /* drop if load would exceed ISDN_MAXLOAD
2401          * this keeps the delay not too high
2402          */
2403         if (p_m_load+length > ISDN_MAXLOAD)
2404                 return;
2405
2406         /* load data to buffer
2407          */
2408         memcpy(buf+mISDN_HEADER_LEN, data, length);
2409         frm->len = length;
2410         mISDN_write(mISDNdevice, frm, mISDN_HEADER_LEN+frm->len, TIMEOUT_1SEC);
2411         p_m_load += frm->len;
2412 }
2413