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