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