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