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