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