51295191dc73a8680531aa86bca848745ca35bd5
[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 <mISDNuser/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 mISDNsocket = -1;
48
49 int mISDN_initialize(void)
50 {
51         /* try to open raw socket to check kernel */
52         mISDNsocket = socket(PF_ISDN, SOCK_RAW, ISDN_P_BASE);
53         if (mISDNsocket < 0)
54         {
55                 fprintf(stderr, "Cannot open mISDN due to %s. (Does your Kernel support socket based mISDN?)\n", strerror(errno));
56                 return(-1);
57         }
58
59         /* initialize stuff of the NT lib */
60         if (options.deb & DEBUG_STACK)
61         {
62                 global_debug = 0xffffffff & ~DBGM_MSG;
63 //              global_debug = DBGM_L3DATA;
64         } else
65                 global_debug = DBGM_MAN;
66         SPRINT(debug_log, "%s/debug.log", INSTALL_DATA);
67         if (options.deb & DEBUG_LOG)
68                 mISDN_debug_init(global_debug, debug_log, debug_log, debug_log);
69         else
70                 mISDN_debug_init(global_debug, NULL, NULL, NULL);
71
72         /* init mlayer3 */
73         init_layer3(4); // buffer of 4
74
75         return(0);
76 }
77
78 void mISDN_deinitialize(void)
79 {
80         cleanup_layer3();
81
82         mISDN_debug_close();
83
84         if (mISDNsocket > -1)
85                 close(mISDNsocket);
86 }
87 #else
88 int entity = 0; /* used for udevice */
89 int mISDNdevice = -1; /* the device handler and port list */
90
91 int mISDN_initialize(void)
92 {
93         char debug_log[128];
94         unsigned char buff[1025];
95         iframe_t *frm = (iframe_t *)buff;
96         int ret;
97
98         /* initialize stuff of the NT lib */
99         if (options.deb & DEBUG_STACK)
100         {
101                 global_debug = 0xffffffff & ~DBGM_MSG;
102 //              global_debug = DBGM_L3DATA;
103         } else
104                 global_debug = DBGM_MAN;
105         SPRINT(debug_log, "%s/debug.log", INSTALL_DATA);
106         if (options.deb & DEBUG_LOG)
107                 debug_init(global_debug, debug_log, debug_log, debug_log);
108         else
109                 debug_init(global_debug, NULL, NULL, NULL);
110         msg_init();
111
112         /* open mISDNdevice if not already open */
113         if (mISDNdevice < 0)
114         {
115                 ret = mISDN_open();
116                 if (ret < 0)
117                 {
118                         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));
119                         return(-1);
120                 }
121                 mISDNdevice = ret;
122                 PDEBUG(DEBUG_ISDN, "mISDN device opened.\n");
123
124                 /* create entity for layer 3 TE-mode */
125                 mISDN_write_frame(mISDNdevice, buff, 0, MGR_NEWENTITY | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
126                 ret = mISDN_read_frame(mISDNdevice, frm, sizeof(iframe_t), 0, MGR_NEWENTITY | CONFIRM, TIMEOUT_1SEC);
127                 if (ret < (int)mISDN_HEADER_LEN)
128                 {
129                         noentity:
130                         FATAL("Cannot request MGR_NEWENTITY from mISDN. Exitting due to software bug.");
131                 }
132                 entity = frm->dinfo & 0xffff;
133                 if (!entity)
134                         goto noentity;
135                 PDEBUG(DEBUG_ISDN, "our entity for l3-processes is %d.\n", entity);
136         }
137         return(0);
138 }
139
140 void mISDN_deinitialize(void)
141 {
142         unsigned char buff[1025];
143
144         debug_close();
145
146         if (mISDNdevice >= 0)
147         {
148                 /* free entity */
149                 mISDN_write_frame(mISDNdevice, buff, 0, MGR_DELENTITY | REQUEST, entity, 0, NULL, TIMEOUT_1SEC);
150                 /* close device */
151                 mISDN_close(mISDNdevice);
152                 mISDNdevice = -1;
153                 PDEBUG(DEBUG_ISDN, "mISDN device closed.\n");
154         }
155 }
156 #endif
157
158 /*
159  * constructor
160  */
161 PmISDN::PmISDN(int type, mISDNport *mISDNport, char *portname, struct port_settings *settings, int channel, int exclusive) : Port(type, portname, settings)
162 {
163         p_m_mISDNport = mISDNport;
164         p_m_portnum = mISDNport->portnum;
165         p_m_b_index = -1;
166         p_m_b_channel = 0;
167         p_m_b_exclusive = 0;
168         p_m_b_reserve = 0;
169         p_m_delete = 0;
170         p_m_hold = 0;
171         p_m_txvol = p_m_rxvol = 0;
172         p_m_conf = 0;
173         p_m_txdata = 0;
174         p_m_delay = 0;
175         p_m_echo = 0;
176         p_m_tone = 0;
177         p_m_rxoff = 0;
178         p_m_joindata = 0;
179         p_m_dtmf = !mISDNport->ifport->nodtmf;
180         p_m_timeout = 0;
181         p_m_timer = 0;
182         p_m_remote_ref = 0; /* channel shall be exported to given remote */
183         p_m_remote_id = 0; /* channel shall be exported to given remote */
184
185         /* audio */
186         p_m_load = 0;
187         p_m_last_tv_sec = 0;
188
189         /* crypt */
190         p_m_crypt = 0;
191         p_m_crypt_listen = 0;
192         p_m_crypt_msg_loops = 0;
193         p_m_crypt_msg_loops = 0;
194         p_m_crypt_msg_len = 0;
195         p_m_crypt_msg[0] = '\0';
196         p_m_crypt_msg_current = 0;
197         p_m_crypt_key[0] = '\0';
198         p_m_crypt_key_len = 0;
199         p_m_crypt_listen = 0;
200         p_m_crypt_listen_state = 0;
201         p_m_crypt_listen_len = 0;
202         p_m_crypt_listen_msg[0] = '\0';
203         p_m_crypt_listen_crc = 0;
204
205         /* if any channel requested by constructor */
206         if (channel == CHANNEL_ANY)
207         {
208                 /* reserve channel */
209                 p_m_b_reserve = 1;
210                 mISDNport->b_reserved++;
211         }
212
213         /* reserve channel */
214         if (channel > 0) // only if constructor was called with a channel resevation
215                 seize_bchannel(channel, exclusive);
216
217         /* we increase the number of objects: */
218         mISDNport->use++;
219         PDEBUG(DEBUG_ISDN, "Created new mISDNPort(%s). Currently %d objects use, port #%d\n", portname, mISDNport->use, p_m_portnum);
220 }
221
222
223 /*
224  * destructor
225  */
226 PmISDN::~PmISDN()
227 {
228         struct message *message;
229
230         /* remove bchannel relation */
231         drop_bchannel();
232
233         /* release epoint */
234         while (p_epointlist)
235         {
236                 PDEBUG(DEBUG_ISDN, "destroy mISDNPort(%s). endpoint still exists, releaseing.\n", p_name);
237                 message = message_create(p_serial, p_epointlist->epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
238                 message->param.disconnectinfo.cause = 16;
239                 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
240                 message_put(message);
241                 /* remove from list */
242                 free_epointlist(p_epointlist);
243         }
244
245         /* we decrease the number of objects: */
246         p_m_mISDNport->use--;
247         PDEBUG(DEBUG_ISDN, "destroyed mISDNPort(%s). Currently %d objects\n", p_name, p_m_mISDNport->use);
248 }
249
250
251 /*
252  * trace
253  */
254 void chan_trace_header(struct mISDNport *mISDNport, class PmISDN *port, char *msgtext, int direction)
255 {
256         /* init trace with given values */
257         start_trace(mISDNport?mISDNport->portnum:0,
258                     (mISDNport)?((mISDNport->ifport)?mISDNport->ifport->interface:NULL):NULL,
259                     port?numberrize_callerinfo(port->p_callerinfo.id, port->p_callerinfo.ntype):NULL,
260                     port?port->p_dialinginfo.id:NULL,
261                     direction,
262                     CATEGORY_CH,
263                     port?port->p_serial:0,
264                     msgtext);
265 }
266
267
268 /*
269  * layer trace header
270  */
271 static struct isdn_message {
272         char *name;
273         unsigned long value;
274 } isdn_message[] = {
275         {"TIMEOUT", CC_TIMEOUT},
276         {"SETUP", CC_SETUP},
277         {"SETUP_ACK", CC_SETUP_ACKNOWLEDGE},
278         {"PROCEEDING", CC_PROCEEDING},
279         {"ALERTING", CC_ALERTING},
280         {"CONNECT", CC_CONNECT},
281         {"CONNECT RES", CC_CONNECT},
282         {"CONNECT_ACK", CC_CONNECT_ACKNOWLEDGE},
283         {"DISCONNECT", CC_DISCONNECT},
284         {"RELEASE", CC_RELEASE},
285         {"RELEASE_COMP", CC_RELEASE_COMPLETE},
286         {"INFORMATION", CC_INFORMATION},
287         {"PROGRESS", CC_PROGRESS},
288         {"NOTIFY", CC_NOTIFY},
289         {"SUSPEND", CC_SUSPEND},
290         {"SUSPEND_ACK", CC_SUSPEND_ACKNOWLEDGE},
291         {"SUSPEND_REJ", CC_SUSPEND_REJECT},
292         {"RESUME", CC_RESUME},
293         {"RESUME_ACK", CC_RESUME_ACKNOWLEDGE},
294         {"RESUME_REJ", CC_RESUME_REJECT},
295         {"HOLD", CC_HOLD},
296         {"HOLD_ACK", CC_HOLD_ACKNOWLEDGE},
297         {"HOLD_REJ", CC_HOLD_REJECT},
298         {"RETRIEVE", CC_RETRIEVE},
299         {"RETRIEVE_ACK", CC_RETRIEVE_ACKNOWLEDGE},
300         {"RETRIEVE_REJ", CC_RETRIEVE_REJECT},
301         {"FACILITY", CC_FACILITY},
302         {"STATUS", CC_STATUS},
303         {"RESTART", CC_RESTART},
304         {"RELEASE_CR", CC_RELEASE_CR},
305         {"NEW_CR", CC_NEW_CR},
306         {"DL_ESTABLISH", DL_ESTABLISH},
307         {"DL_RELEASE", DL_RELEASE},
308         {"PH_ACTIVATE", PH_ACTIVATE},
309         {"PH_DEACTIVATE", PH_DEACTIVATE},
310
311         {NULL, 0},
312 };
313 static char *isdn_prim[4] = {
314         " REQUEST",
315         " CONFIRM",
316         " INDICATION",
317         " RESPONSE",
318 };
319 void l1l2l3_trace_header(struct mISDNport *mISDNport, class PmISDN *port, unsigned long prim, int direction)
320 {
321         int i;
322         char msgtext[64] = "<<UNKNOWN MESSAGE>>";
323
324         /* select message and primitive text */
325         i = 0;
326         while(isdn_message[i].name)
327         {
328                 if (isdn_message[i].value == (prim&0xffffff00))
329                 {
330                         SCPY(msgtext, isdn_message[i].name);
331                         break;
332                 }
333                 i++;
334         }
335         SCAT(msgtext, isdn_prim[prim&0x00000003]);
336
337         /* add direction */
338         if (direction && (prim&0xffffff00)!=CC_NEW_CR && (prim&0xffffff00)!=CC_RELEASE_CR)
339         {
340                 if (mISDNport)
341                 {
342                         if (mISDNport->ntmode)
343                         {
344                                 if (direction == DIRECTION_OUT)
345                                         SCAT(msgtext, " N->U");
346                                 else
347                                         SCAT(msgtext, " N<-U");
348                         } else
349                         {
350                                 if (direction == DIRECTION_OUT)
351                                         SCAT(msgtext, " U->N");
352                                 else
353                                         SCAT(msgtext, " U<-N");
354                         }
355                 }
356         }
357
358         /* init trace with given values */
359         start_trace(mISDNport?mISDNport->portnum:0,
360                     mISDNport?mISDNport->ifport->interface:NULL,
361                     port?numberrize_callerinfo(port->p_callerinfo.id, port->p_callerinfo.ntype):NULL,
362                     port?port->p_dialinginfo.id:NULL,
363                     direction,
364                     CATEGORY_CH,
365                     port?port->p_serial:0,
366                     msgtext);
367 }
368
369
370 /*
371  * send control information to the channel (dsp-module)
372  */
373 void ph_control(struct mISDNport *mISDNport, class PmISDN *isdnport, unsigned long handle, unsigned long c1, unsigned long c2, char *trace_name, int trace_value)
374 {
375 #ifdef SOCKET_MISDN
376         unsigned char buffer[MISDN_HEADER_LEN+sizeof(int)+sizeof(int)];
377         struct mISDNhead *ctrl = (struct mISDNhead *)buffer;
378         unsigned long *d = buffer+MISDN_HEADER_LEN;
379         int ret;
380
381         ctrl->prim = PH_CONTROL_REQ;
382         ctrl->id = 0;
383         *d++ = c1;
384         *d++ = c2;
385         ret = sendto(handle, buffer, MISDN_HEADER_LEN+sizeof(int)*2, 0, NULL, 0);
386         if (!ret)
387                 PERROR("Failed to send to socket %d\n", handle);
388 #else
389         unsigned char buffer[mISDN_HEADER_LEN+sizeof(int)+sizeof(int)];
390         iframe_t *ctrl = (iframe_t *)buffer; 
391         unsigned long *d = (unsigned long *)&ctrl->data.p;
392
393         ctrl->prim = PH_CONTROL | REQUEST;
394         ctrl->addr = handle | FLG_MSG_DOWN;
395         ctrl->dinfo = 0;
396         ctrl->len = sizeof(int)*2;
397         *d++ = c1;
398         *d++ = c2;
399         mISDN_write(mISDNdevice, ctrl, mISDN_HEADER_LEN+ctrl->len, TIMEOUT_1SEC);
400 #endif
401         chan_trace_header(mISDNport, isdnport, "BCHANNEL control", DIRECTION_OUT);
402         if (c1 == CMX_CONF_JOIN)
403                 add_trace(trace_name, NULL, "0x%08x", trace_value);
404         else
405                 add_trace(trace_name, NULL, "%d", trace_value);
406         end_trace();
407 }
408
409 void ph_control_block(struct mISDNport *mISDNport, class PmISDN *isdnport, unsigned long handle, unsigned long c1, void *c2, int c2_len, char *trace_name, int trace_value)
410 {
411 #ifdef SOCKET_MISDN
412         unsigned char buffer[MISDN_HEADER_LEN+sizeof(int)+c2_len];
413         struct mISDNhead *ctrl = (struct mISDNhead *)buffer;
414         unsigned long *d = buffer+MISDN_HEADER_LEN;
415         int ret;
416
417         ctrl->prim = PH_CONTROL_REQ;
418         ctrl->id = 0;
419         *d++ = c1;
420         memcpy(d, c2, c2_len);
421         ret = sendto(handle, buffer, MISDN_HEADER_LEN+sizeof(int)+c2_len, 0, NULL, 0);
422         if (!ret)
423                 PERROR("Failed to send to socket %d\n", handle);
424 #else
425         unsigned char buffer[mISDN_HEADER_LEN+sizeof(int)+c2_len];
426         iframe_t *ctrl = (iframe_t *)buffer;
427         unsigned long *d = (unsigned long *)&ctrl->data.p;
428
429         ctrl->prim = PH_CONTROL | REQUEST;
430         ctrl->addr = handle | FLG_MSG_DOWN;
431         ctrl->dinfo = 0;
432         ctrl->len = sizeof(int)+c2_len;
433         *d++ = c1;
434         memcpy(d, c2, c2_len);
435         mISDN_write(mISDNdevice, ctrl, mISDN_HEADER_LEN+ctrl->len, TIMEOUT_1SEC);
436 #endif
437         chan_trace_header(mISDNport, isdnport, "BCHANNEL control", DIRECTION_OUT);
438         add_trace(trace_name, NULL, "%d", trace_value);
439         end_trace();
440 }
441
442
443 /*
444  * subfunction for bchannel_event
445  * create stack
446  */
447 static int _bchannel_create(struct mISDNport *mISDNport, int i)
448 {
449         unsigned char buff[1024];
450         int ret;
451 #ifdef SOCKET_MISDN
452         unsigned long on = 1;
453         struct sockadd_mISDN addr;
454
455         if (mISDNport->b_socket[i])
456         {
457                 PERROR("Error: Socket already created for index %d\n", i);
458                 return(0);
459         }
460
461         /* open socket */
462         mISDNport->b_socket[i] = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_B_L2DSP);
463         if (mISDNport->b_socket[i])
464         {
465                 PERROR("Error: Failed to open bchannel-socket for index %d with mISDN-DSP layer. Did you load mISDNdsp.ko?\n", i);
466                 return(0);
467         }
468         
469         /* set nonblocking io */
470         ret = ioctl(mISDNport->b_socket[i], FIONBIO, &on);
471         if (ret < 0)
472         {
473                 PERROR("Error: Failed to set bchannel-socket index %d into nonblocking IO\n", i);
474                 close(mISDNport->b_socket[i]);
475                 mISDNport->b_socket[i] = -1;
476                 return(0);
477         }
478
479         /* bind socket to bchannel */
480         addr.family = AF_ISDN;
481         addr.dev = mISDNport->port-1;
482         addr.channel = i+1+(i>=15);
483         ret = bind(di->bchan, (struct sockaddr *)&addr, sizeof(addr));
484         if (ret < 0)
485         {
486                 PERROR("Error: Failed to bind bchannel-socket for index %d with mISDN-DSP layer. Did you load mISDNdsp.ko?\n", i);
487                 close(mISDNport->b_socket[i]);
488                 mISDNport->b_socket[i] = -1;
489                 return(0);
490         }
491
492         chan_trace_header(mISDNport, mISDNport->b_port[i], "BCHANNEL create socket", DIRECTION_OUT);
493         add_trace("channel", NULL, "%d", i+1+(i>=15));
494         add_trace("socket", NULL, "%d", mISDNport->b_socket[i]);
495         end_trace();
496 #else
497         layer_info_t li;
498         mISDN_pid_t pid;
499
500         if (!mISDNport->b_stid[i])
501         {
502                 PERROR("Error: no stack for index %d\n", i);
503                 return(0);
504         }
505         if (mISDNport->b_addr[i])
506         {
507                 PERROR("Error: stack already created for index %d\n", i);
508                 return(0);
509         }
510
511         /* create new layer */
512         PDEBUG(DEBUG_BCHANNEL, "creating new layer for bchannel %d (index %d).\n" , i+1+(i>=15), i);
513         memset(&li, 0, sizeof(li));
514         memset(&pid, 0, sizeof(pid));
515         li.object_id = -1;
516         li.extentions = 0;
517         li.st = mISDNport->b_stid[i];
518         UCPY(li.name, "B L4");
519         li.pid.layermask = ISDN_LAYER((4));
520         li.pid.protocol[4] = ISDN_PID_L4_B_USER;
521         ret = mISDN_new_layer(mISDNdevice, &li);
522         if (ret)
523         {
524                 failed_new_layer:
525                 PERROR("mISDN_new_layer() failed to add bchannel %d (index %d)\n", i+1+(i>=15), i);
526                 goto failed;
527         }
528         mISDNport->b_addr[i] = li.id;
529         if (!li.id)
530         {
531                 goto failed_new_layer;
532         }
533         PDEBUG(DEBUG_BCHANNEL, "new layer (b_addr=0x%x)\n", mISDNport->b_addr[i]);
534
535         /* create new stack */
536         pid.protocol[1] = ISDN_PID_L1_B_64TRANS;
537         pid.protocol[2] = ISDN_PID_L2_B_TRANS;
538         pid.protocol[3] = ISDN_PID_L3_B_DSP;
539         pid.protocol[4] = ISDN_PID_L4_B_USER;
540         pid.layermask = ISDN_LAYER((1)) | ISDN_LAYER((2)) | ISDN_LAYER((3)) | ISDN_LAYER((4));
541         ret = mISDN_set_stack(mISDNdevice, mISDNport->b_stid[i], &pid);
542         if (ret)
543         {
544                 stack_error:
545                 PERROR("mISDN_set_stack() failed (ret=%d) to add bchannel (index %d) stid=0x%x\n", ret, i, mISDNport->b_stid[i]);
546                 mISDN_write_frame(mISDNdevice, buff, mISDNport->b_addr[i], MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
547                 goto failed;
548         }
549         ret = mISDN_get_setstack_ind(mISDNdevice, mISDNport->b_addr[i]);
550         if (ret)
551                 goto stack_error;
552
553         /* get layer id */
554         mISDNport->b_addr[i] = mISDN_get_layerid(mISDNdevice, mISDNport->b_stid[i], 4);
555         if (!mISDNport->b_addr[i])
556                 goto stack_error;
557         chan_trace_header(mISDNport, mISDNport->b_port[i], "BCHANNEL create stack", DIRECTION_OUT);
558         add_trace("channel", NULL, "%d", i+1+(i>=15));
559         add_trace("stack", "id", "0x%08x", mISDNport->b_stid[i]);
560         add_trace("stack", "address", "0x%08x", mISDNport->b_addr[i]);
561         end_trace();
562 #endif
563
564         return(1);
565
566 failed:
567         mISDNport->b_addr[i] = 0;
568         return(0);
569 }
570
571
572 /*
573  * subfunction for bchannel_event
574  * activate / deactivate request
575  */
576 static void _bchannel_activate(struct mISDNport *mISDNport, int i, int activate)
577 {
578 #ifdef SOCKET_MISDN
579         struct mISDNhead act;
580         int ret;
581
582         act.prim = (activate)?DL_ESTABLISH_REQ:DL_RELEASE_REQ; 
583         act.id = 0;
584         ret = sendto(mISDNport->b_socket[i], &act, MISDN_HEADER_LEN, 0, NULL, 0);
585         if (!ret)
586                 PERROR("Failed to send to socket %d\n", mISDNport->b_socket[i]);
587 #else
588         iframe_t act;
589
590         /* activate bchannel */
591         act.prim = (activate?DL_ESTABLISH:DL_RELEASE) | REQUEST; 
592         act.addr = mISDNport->b_addr[i] | FLG_MSG_DOWN;
593         act.dinfo = 0;
594         act.len = 0;
595         mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
596 #endif
597
598         /* trace */
599         chan_trace_header(mISDNport, mISDNport->b_port[i], activate?(char*)"BCHANNEL activate":(char*)"BCHANNEL deactivate", DIRECTION_OUT);
600         add_trace("channel", NULL, "%d", i+1+(i>=15));
601         end_trace();
602 }
603
604
605 /*
606  * subfunction for bchannel_event
607  * set features
608  */
609 static void _bchannel_configure(struct mISDNport *mISDNport, int i)
610 {
611         struct PmISDN *port;
612 #ifdef SOCKET_MISDN
613         int handle;
614
615         handle = mISDNport->b_socket[i];
616 #else
617         unsigned long handle;
618
619         handle = mISDNport->b_addr[i];
620 #endif
621         port = mISDNport->b_port[i];
622         if (!port)
623         {
624                 PERROR("bchannel index i=%d not associated with a port object\n", i);
625                 return;
626         }
627
628         /* set dsp features */
629         if (port->p_m_txdata)
630                 ph_control(mISDNport, port, handle, (port->p_m_txdata)?CMX_TXDATA_ON:CMX_TXDATA_OFF, 0, "DSP-TXDATA", port->p_m_txdata);
631         if (port->p_m_delay)
632                 ph_control(mISDNport, port, handle, CMX_DELAY, port->p_m_delay, "DSP-DELAY", port->p_m_delay);
633         if (port->p_m_txvol)
634                 ph_control(mISDNport, port, handle, VOL_CHANGE_TX, port->p_m_txvol, "DSP-TXVOL", port->p_m_txvol);
635         if (port->p_m_rxvol)
636                 ph_control(mISDNport, port, handle, VOL_CHANGE_RX, port->p_m_rxvol, "DSP-RXVOL", port->p_m_rxvol);
637         if (port->p_m_conf)
638                 ph_control(mISDNport, port, handle, CMX_CONF_JOIN, port->p_m_conf, "DSP-CONF", port->p_m_conf);
639         if (port->p_m_echo)
640                 ph_control(mISDNport, port, handle, CMX_ECHO_ON, 0, "DSP-ECHO", 1);
641         if (port->p_m_tone)
642                 ph_control(mISDNport, port, handle, TONE_PATT_ON, port->p_m_tone, "DSP-TONE", port->p_m_tone);
643         if (port->p_m_rxoff)
644                 ph_control(mISDNport, port, handle, CMX_RECEIVE_OFF, 0, "DSP-RXOFF", 1);
645 //      if (port->p_m_txmix)
646 //              ph_control(mISDNport, port, handle, CMX_MIX_ON, 0, "DSP-MIX", 1);
647         if (port->p_m_dtmf)
648                 ph_control(mISDNport, port, handle, DTMF_TONE_START, 0, "DSP-DTMF", 1);
649         if (port->p_m_crypt)
650                 ph_control_block(mISDNport, port, handle, BF_ENABLE_KEY, port->p_m_crypt_key, port->p_m_crypt_key_len, "DSP-CRYPT", port->p_m_crypt_key_len);
651 }
652
653 /*
654  * subfunction for bchannel_event
655  * destroy stack
656  */
657 static void _bchannel_destroy(struct mISDNport *mISDNport, int i)
658 {
659 #ifdef SOCKET_MISDN
660         chan_trace_header(mISDNport, mISDNport->b_port[i], "BCHANNEL remove socket", DIRECTION_OUT);
661         add_trace("channel", NULL, "%d", i+1+(i>=15));
662         add_trace("socket", NULL, "%d", mISDNport->b_socket[i]);
663         end_trace();
664         if (mISDNport->b_socket[i] > -1)
665         {
666                 close(mISDNport->b_socket[i]);
667                 mISDNport->b_socket[i] = -1;
668         }
669 #else
670         unsigned char buff[1024];
671
672         chan_trace_header(mISDNport, mISDNport->b_port[i], "BCHANNEL remove stack", DIRECTION_OUT);
673         add_trace("channel", NULL, "%d", i+1+(i>=15));
674         add_trace("stack", "id", "0x%08x", mISDNport->b_stid[i]);
675         add_trace("stack", "address", "0x%08x", mISDNport->b_addr[i]);
676         end_trace();
677         /* remove our stack only if set */
678         if (mISDNport->b_addr[i])
679         {
680                 PDEBUG(DEBUG_BCHANNEL, "free stack (b_addr=0x%x)\n", mISDNport->b_addr[i]);
681                 mISDN_clear_stack(mISDNdevice, mISDNport->b_stid[i]);
682                 mISDN_write_frame(mISDNdevice, buff, mISDNport->b_addr[i] | FLG_MSG_DOWN, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
683                 mISDNport->b_addr[i] = 0;
684         }
685 #endif
686 }
687
688
689 /*
690 bchannel procedure
691 ------------------
692
693 A bchannel goes through the following states in this order:
694
695 - B_STATE_IDLE
696 No one is using the bchannel.
697 It is available and not linked to Port class, nor reserved.
698
699 - B_STATE_ACTIVATING
700 The bchannel stack is created and an activation request is sent.
701 It MAY be linked to Port class, but already unlinked due to Port class removal.
702
703 - B_STATE_ACTIVE
704 The bchannel is active and cofigured to the Port class needs.
705 Also it is linked to a Port class, otherwhise it would be deactivated.
706
707 - B_STATE_DEACTIVATING
708 The bchannel is in deactivating state, due to deactivation request.
709 It may be linked to a Port class, that likes to reactivate it.
710
711 - B_STATE_IDLE
712 See above.
713 After deactivating bchannel, and if not used, the bchannel becomes idle again.
714
715 Also the bchannel may be exported, but only if the state is or becomes idle:
716
717 - B_STATE_EXPORTING
718 The bchannel assignment has been sent to the remove application.
719
720 - B_STATE_REMOTE
721 The bchannel assignment is acknowledged by the remote application.
722
723 - B_STATE_IMPORTING
724 The bchannel is re-imported by mISDN port object.
725
726 - B_STATE_IDLE
727 See above.
728 After re-importing bchannel, and if not used, the bchannel becomes idle again.
729
730
731 A bchannel can have the following events:
732
733 - B_EVENT_USE
734 A bchannel is required by a Port class.
735 The bchannel shall be exported to the remote application.
736
737 - B_EVENT_ACTIVATED
738 The bchannel beomes active.
739
740 - B_EVENT_DROP
741 The bchannel is not required by Port class anymore
742
743 - B_EVENT_DEACTIVATED
744 The bchannel becomes inactive.
745
746 - B_EVENT_EXPORTED
747 The bchannel is now used by remote application.
748
749 - B_EVENT_IMPORTED
750 The bchannel is not used by remote application.
751
752 All actions taken on these events depend on the current bchannel's state and if it is linked to a Port class.
753
754 if an export request is receive by remote application, p_m_remote_* is set.
755 the b_remote_*[index] indicates if and where the channel is exported to. (set from the point on, where export is initiated, until imported is acknowledged.)
756 - set on export request from remote application (if port is assigned)
757 - set on channel use, if requested by remote application (p_m_remote_*)
758 - cleared on drop request
759
760 the bchannel will be exported with ref and stack given. remote application uses the ref to link bchannel to the call.
761 the bchannel will be imported with stack given only. remote application must store stack id with the bchannel process.
762 the bchannel import/export is acknowledged with stack given.
763
764 if exporting, b_remote_*[index] is set to the remote socket id.
765 if importing has been acknowledged. b_remote_*[index] is cleared.
766
767 */
768
769 /*
770  * process bchannel events
771  * - mISDNport is a pointer to the port's structure
772  * - i is the index of the bchannel
773  * - event is the B_EVENT_* value
774  * - port is the PmISDN class pointer
775  */
776 void bchannel_event(struct mISDNport *mISDNport, int i, int event)
777 {
778         class PmISDN *b_port = mISDNport->b_port[i];
779         int state = mISDNport->b_state[i];
780         unsigned long p_m_remote_ref = 0;
781         unsigned long p_m_remote_id = 0;
782 #ifdef SOCKET_MISDN
783         unsigned long portid = (mISDNport->portnum<<8) + i+1+(i>=15);
784 #else
785         unsigned long portid = mISDNport->b_addr[i];
786 #endif
787
788         if (b_port)
789         {
790                 p_m_remote_id = b_port->p_m_remote_id;
791                 p_m_remote_ref = b_port->p_m_remote_ref;
792         }
793
794         switch(event)
795         {
796                 case B_EVENT_USE:
797                 /* port must be linked in order to allow activation */
798                 if (!b_port)
799                         FATAL("bchannel must be linked to a Port class\n");
800                 switch(state)
801                 {
802                         case B_STATE_IDLE:
803                         if (p_m_remote_ref)
804                         {
805                                 /* export bchannel */
806                                 message_bchannel_to_join(p_m_remote_id, p_m_remote_ref, BCHANNEL_ASSIGN, portid);
807                                 chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
808                                 add_trace("type", NULL, "assign");
809 #ifdef SOCKET_MISDN
810                                 add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff);
811 #else
812                                 add_trace("socket", "id", "%d", portid);
813 #endif
814                                 end_trace();
815                                 state = B_STATE_EXPORTING;
816                                 mISDNport->b_remote_id[i] = p_m_remote_id;
817                                 mISDNport->b_remote_ref[i] = p_m_remote_ref;
818                         } else
819                         {
820                                 /* create stack and send activation request */
821                                 if (_bchannel_create(mISDNport, i))
822                                 {
823                                         _bchannel_activate(mISDNport, i, 1);
824                                         state = B_STATE_ACTIVATING;
825                                 }
826                         }
827                         break;
828
829                         case B_STATE_ACTIVATING:
830                         case B_STATE_EXPORTING:
831                         /* do nothing, because it is already activating */
832                         break;
833
834                         case B_STATE_DEACTIVATING:
835                         case B_STATE_IMPORTING:
836                         /* do nothing, because we must wait until we can reactivate */
837                         break;
838
839                         default:
840                         /* problems that might ocurr:
841                          * B_EVENT_USE is received when channel already in use.
842                          * bchannel exported, but not freed by other port
843                          */
844                         PERROR("Illegal event %d at state %d, please correct.\n", event, state);
845                 }
846                 break;
847
848                 case B_EVENT_EXPORTREQUEST:
849                 /* special case where the bchannel is requested by remote */
850                 if (!p_m_remote_ref)
851                 {
852                         PERROR("export request without remote channel set, please correct.\n");
853                         break;
854                 }
855                 switch(state)
856                 {
857                         case B_STATE_IDLE:
858                         /* in case, the bchannel is exported right after seize_bchannel */
859                         /* export bchannel */
860                         /* p_m_remote_id is set, when this event happens. */
861                         message_bchannel_to_join(p_m_remote_id, p_m_remote_ref, BCHANNEL_ASSIGN, portid);
862                         chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
863                         add_trace("type", NULL, "assign");
864 #ifdef SOCKET_MISDN
865                         add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff);
866 #else
867                         add_trace("socket", "id", "%d", portid);
868 #endif
869                         end_trace();
870                         state = B_STATE_EXPORTING;
871                         mISDNport->b_remote_id[i] = p_m_remote_id;
872                         mISDNport->b_remote_ref[i] = p_m_remote_ref;
873                         break;
874
875                         case B_STATE_ACTIVATING:
876                         case B_STATE_EXPORTING:
877                         /* do nothing, because it is already activating */
878                         break;
879
880                         case B_STATE_DEACTIVATING:
881                         case B_STATE_IMPORTING:
882                         /* do nothing, because we must wait until we can reactivate */
883                         break;
884
885                         case B_STATE_ACTIVE:
886                         /* bchannel is active, so we deactivate */
887                         _bchannel_activate(mISDNport, i, 0);
888                         state = B_STATE_DEACTIVATING;
889                         break;
890
891                         default:
892                         /* problems that might ocurr:
893                          * ... when channel already in use.
894                          * bchannel exported, but not freed by other port
895                          */
896                         PERROR("Illegal event %d at state %d, please correct.\n", event, state);
897                 }
898                 break;
899
900                 case B_EVENT_ACTIVATED:
901                 switch(state)
902                 {
903                         case B_STATE_ACTIVATING:
904                         if (b_port && !p_m_remote_id)
905                         {
906                                 /* bchannel is active and used by Port class, so we configure bchannel */
907                                 _bchannel_configure(mISDNport, i);
908                                 state = B_STATE_ACTIVE;
909                         } else
910                         {
911                                 /* bchannel is active, but exported OR not used anymore (or has wrong stack config), so we deactivate */
912                                 _bchannel_activate(mISDNport, i, 0);
913                                 state = B_STATE_DEACTIVATING;
914                         }
915                         break;
916
917                         default:
918                         PERROR("Illegal event %d at state %d, please correct.\n", event, state);
919                 }
920                 break;
921
922                 case B_EVENT_EXPORTED:
923                 switch(state)
924                 {
925                         case B_STATE_EXPORTING:
926                         if (b_port && p_m_remote_ref && p_m_remote_ref==mISDNport->b_remote_ref[i])
927                         {
928                                 /* remote export done */
929                                 state = B_STATE_REMOTE;
930                         } else
931                         {
932                                 /* bchannel is now exported, but we need bchannel back
933                                  * OR bchannel is not used anymore
934                                  * OR bchannel has been exported to an obsolete ref,
935                                  * so reimport, to later export to new remote */
936                                 message_bchannel_to_join(mISDNport->b_remote_id[i], 0, BCHANNEL_REMOVE, portid);
937                                 chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
938                                 add_trace("type", NULL, "remove");
939 #ifdef SOCKET_MISDN
940                                 add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff);
941 #else
942                                 add_trace("socket", "id", "%d", portid);
943 #endif
944                                 end_trace();
945                                 state = B_STATE_IMPORTING;
946                         }
947                         break;
948
949                         default:
950                         PERROR("Illegal event %d at state %d, please correct.\n", event, state);
951                 }
952                 break;
953
954                 case B_EVENT_DROP:
955                 if (!b_port)
956                         FATAL("bchannel must be linked to a Port class\n");
957                 switch(state)
958                 {
959                         case B_STATE_IDLE:
960                         /* bchannel is idle due to an error, so we do nothing */
961                         break;
962
963                         case B_STATE_ACTIVATING:
964                         case B_STATE_EXPORTING:
965                         /* do nothing because we must wait until bchanenl is active before deactivating */
966                         break;
967
968                         case B_STATE_ACTIVE:
969                         /* bchannel is active, so we deactivate */
970                         _bchannel_activate(mISDNport, i, 0);
971                         state = B_STATE_DEACTIVATING;
972                         break;
973
974                         case B_STATE_REMOTE:
975                         /* bchannel is exported, so we re-import */
976                         message_bchannel_to_join(mISDNport->b_remote_id[i], 0, BCHANNEL_REMOVE, portid);
977                         chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
978                         add_trace("type", NULL, "remove");
979 #ifdef SOCKET_MISDN
980                         add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff);
981 #else
982                         add_trace("socket", "id", "%d", portid);
983 #endif
984                         end_trace();
985                         state = B_STATE_IMPORTING;
986                         break;
987
988                         case B_STATE_DEACTIVATING:
989                         case B_STATE_IMPORTING:
990                         /* we may have taken an already deactivating bchannel, but do not require it anymore, so we do nothing */
991                         break;
992
993                         default:
994                         PERROR("Illegal event %d at state %d, please correct.\n", event, state);
995                 }
996                 break;
997
998                 case B_EVENT_DEACTIVATED:
999                 switch(state)
1000                 {
1001                         case B_STATE_IDLE:
1002                         /* ignore due to deactivation confirm after unloading */
1003                         break;
1004
1005                         case B_STATE_DEACTIVATING:
1006                         _bchannel_destroy(mISDNport, i);
1007                         state = B_STATE_IDLE;
1008                         if (b_port)
1009                         {
1010                                 /* bchannel is now deactivate, but is requied by Port class, so we reactivate / export */
1011                                 if (p_m_remote_ref)
1012                                 {
1013                                         message_bchannel_to_join(p_m_remote_id, p_m_remote_ref, BCHANNEL_ASSIGN, portid);
1014                                         chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
1015                                         add_trace("type", NULL, "assign");
1016 #ifdef SOCKET_MISDN
1017                                         add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff);
1018 #else
1019                                         add_trace("socket", "id", "%d", portid);
1020 #endif
1021                                         end_trace();
1022                                         state = B_STATE_EXPORTING;
1023                                         mISDNport->b_remote_id[i] = p_m_remote_id;
1024                                         mISDNport->b_remote_ref[i] = p_m_remote_ref;
1025                                 } else
1026                                 {
1027                                         if (_bchannel_create(mISDNport, i))
1028                                         {
1029                                                 _bchannel_activate(mISDNport, i, 1);
1030                                                 state = B_STATE_ACTIVATING;
1031                                         }
1032                                 }
1033                         }
1034                         break;
1035
1036                         default:
1037                         PERROR("Illegal event %d at state %d, please correct.\n", event, state);
1038                 }
1039                 break;
1040
1041                 case B_EVENT_IMPORTED:
1042                 switch(state)
1043                 {
1044                         case B_STATE_IMPORTING:
1045                         state = B_STATE_IDLE;
1046                         mISDNport->b_remote_id[i] = 0;
1047                         mISDNport->b_remote_ref[i] = 0;
1048                         if (b_port)
1049                         {
1050                                 /* bchannel is now imported, but is requied by Port class, so we reactivate / export */
1051                                 if (p_m_remote_ref)
1052                                 {
1053                                         message_bchannel_to_join(p_m_remote_id, p_m_remote_ref, BCHANNEL_ASSIGN, portid);
1054                                         chan_trace_header(mISDNport, b_port, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
1055                                         add_trace("type", NULL, "assign");
1056 #ifdef SOCKET_MISDN
1057                                         add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff);
1058 #else
1059                                         add_trace("socket", "id", "%d", portid);
1060 #endif
1061                                         end_trace();
1062                                         state = B_STATE_EXPORTING;
1063                                         mISDNport->b_remote_id[i] = p_m_remote_id;
1064                                         mISDNport->b_remote_ref[i] = p_m_remote_ref;
1065                                 } else
1066                                 {
1067                                         if (_bchannel_create(mISDNport, i))
1068                                         {
1069                                                 _bchannel_activate(mISDNport, i, 1);
1070                                                 state = B_STATE_ACTIVATING;
1071                                         }
1072                                 }
1073                         }
1074                         break;
1075
1076                         default:
1077                         /* ignore, because not assigned */
1078                         ;
1079                 }
1080                 break;
1081
1082                 default:
1083                 PERROR("Illegal event %d, please correct.\n", event);
1084         }
1085
1086         mISDNport->b_state[i] = state;
1087 }
1088
1089
1090
1091
1092 /*
1093  * check for available channel and reserve+set it.
1094  * give channel number or SEL_CHANNEL_ANY or SEL_CHANNEL_NO
1095  * give exclusiv flag
1096  * returns -(cause value) or x = channel x or 0 = no channel
1097  * NOTE: no activation is done here
1098  */
1099 int PmISDN::seize_bchannel(int channel, int exclusive)
1100 {
1101         int i;
1102
1103         /* the channel is what we have */
1104         if (p_m_b_channel == channel)
1105                 return(channel);
1106
1107         /* if channel already in use, release it */
1108         if (p_m_b_channel)
1109                 drop_bchannel();
1110
1111         /* if CHANNEL_NO */
1112         if (channel==CHANNEL_NO || channel==0)
1113                 return(0);
1114         
1115         /* is channel in range ? */
1116         if (channel==16
1117          || (channel>p_m_mISDNport->b_num && channel<16)
1118          || ((channel-1)>p_m_mISDNport->b_num && channel>16)) /* channel-1 because channel 16 is not counted */
1119                 return(-6); /* channel unacceptable */
1120
1121         /* request exclusive channel */
1122         if (exclusive && channel>0)
1123         {
1124                 i = channel-1-(channel>16);
1125                 if (p_m_mISDNport->b_port[i])
1126                         return(-44); /* requested channel not available */
1127                 goto seize;
1128         }
1129
1130         /* ask for channel */
1131         if (channel>0)
1132         {
1133                 i = channel-1-(channel>16);
1134                 if (p_m_mISDNport->b_port[i] == NULL)
1135                         goto seize;
1136         }
1137
1138         /* search for channel */
1139         i = 0;
1140         while(i < p_m_mISDNport->b_num)
1141         {
1142                 if (!p_m_mISDNport->b_port[i])
1143                 {
1144                         channel = i+1+(i>=15);
1145                         goto seize;
1146                 }
1147                 i++;
1148         }
1149         return(-34); /* no free channel */
1150
1151 seize:
1152         PDEBUG(DEBUG_BCHANNEL, "PmISDN(%s) seizing bchannel %d (index %d)\n", p_name, channel, i);
1153
1154         /* link Port */
1155         p_m_mISDNport->b_port[i] = this;
1156         p_m_b_index = i;
1157         p_m_b_channel = channel;
1158         p_m_b_exclusive = exclusive;
1159
1160         /* reserve channel */
1161         if (!p_m_b_reserve)
1162         {
1163                 p_m_b_reserve = 1;
1164                 p_m_mISDNport->b_reserved++;
1165         }
1166
1167         return(channel);
1168 }
1169
1170 /*
1171  * drop reserved channel and unset it.
1172  * deactivation is also done
1173  */
1174 void PmISDN::drop_bchannel(void)
1175 {
1176         /* unreserve channel */
1177         if (p_m_b_reserve)
1178                 p_m_mISDNport->b_reserved--;
1179         p_m_b_reserve = 0;
1180
1181         /* if not in use */
1182         if (p_m_b_index < 0)
1183                 return;
1184         if (!p_m_b_channel)
1185                 return;
1186
1187         PDEBUG(DEBUG_BCHANNEL, "PmISDN(%s) dropping bchannel\n", p_name);
1188
1189         if (p_m_mISDNport->b_state[p_m_b_index] != B_STATE_IDLE)
1190                 bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_DROP);
1191         p_m_mISDNport->b_port[p_m_b_index] = NULL;
1192         p_m_b_index = -1;
1193         p_m_b_channel = 0;
1194         p_m_b_exclusive = 0;
1195 }
1196
1197 /* process bchannel export/import message from join */
1198 void message_bchannel_from_join(class JoinRemote *joinremote, int type, unsigned long handle)
1199 {
1200         class Endpoint *epoint;
1201         class Port *port;
1202         class PmISDN *isdnport;
1203         struct mISDNport *mISDNport;
1204         int i, ii;
1205
1206         switch(type)
1207         {
1208                 case BCHANNEL_REQUEST:
1209                 /* find the port object for the join object ref */
1210                 if (!(epoint = find_epoint_id(joinremote->j_epoint_id)))
1211                 {
1212                         PDEBUG(DEBUG_BCHANNEL, "join %d has no endpoint (anymore)\n", joinremote->j_serial);
1213                         return;
1214                 }
1215                 if (!epoint->ep_portlist)
1216                 {
1217                         PDEBUG(DEBUG_BCHANNEL, "join %d has no port (anymore in portlist)\n", joinremote->j_serial);
1218                         return;
1219                 }
1220                 if (epoint->ep_portlist->next)
1221                 {
1222                         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);
1223                 }
1224                 if (!(port = find_port_id(epoint->ep_portlist->port_id)))
1225                 {
1226                         PDEBUG(DEBUG_BCHANNEL, "join %d has no port (anymore as object)\n", joinremote->j_serial);
1227                         return;
1228                 }
1229                 if (!((port->p_type&PORT_CLASS_MASK) != PORT_CLASS_mISDN))
1230                 {
1231                         PERROR("join %d has port %d not of mISDN type. This shall not happen.\n", joinremote->j_serial, port->p_serial);
1232                 }
1233                 isdnport = (class PmISDN *)port;
1234
1235                 /* assign */
1236                 if (isdnport->p_m_remote_id)
1237                 {
1238                         PERROR("join %d recevied bchannel request from remote, but channel is already assinged.\n", joinremote->j_serial);
1239                         break;
1240                 }
1241                 mISDNport = isdnport->p_m_mISDNport;
1242                 i = isdnport->p_m_b_index;
1243                 chan_trace_header(mISDNport, isdnport, "MESSAGE_BCHANNEL (from remote application)", DIRECTION_NONE);
1244                 add_trace("type", NULL, "export request");
1245                 isdnport->p_m_remote_ref = joinremote->j_serial;
1246                 isdnport->p_m_remote_id = joinremote->j_remote_id;
1247                 if (mISDNport && i>=0)
1248                 {
1249                         bchannel_event(mISDNport, i, B_EVENT_EXPORTREQUEST);
1250                 }
1251                 end_trace();
1252                 break;
1253
1254                 case BCHANNEL_ASSIGN_ACK:
1255                 case BCHANNEL_REMOVE_ACK:
1256                 /* find mISDNport for stack ID */
1257                 mISDNport = mISDNport_first;
1258                 while(mISDNport)
1259                 {
1260                         i = 0;
1261                         ii = mISDNport->b_num;
1262                         while(i < ii)
1263                         {
1264 #ifdef SOCKET_MISDN
1265                                 if (mISDNport->b_socket[i] == handle)
1266 #else
1267                                 if ((unsigned long)(mISDNport->portnum<<8)+i+1+(i>=15) == handle)
1268 #endif
1269                                         break;
1270                                 i++;
1271                         }
1272                         if (i != ii)
1273                                 break;
1274                         mISDNport = mISDNport->next;
1275                 }
1276                 if (!mISDNport)
1277                 {
1278                         PERROR("received assign/remove ack for handle=%x, but handle does not exist in any mISDNport structure.\n", handle);
1279                         break;
1280                 }
1281                 /* mISDNport may now be set or NULL */
1282                 
1283                 /* set */
1284                 chan_trace_header(mISDNport, mISDNport->b_port[i], "MESSAGE_BCHANNEL (from remote application)", DIRECTION_NONE);
1285                 add_trace("type", NULL, (type==BCHANNEL_ASSIGN_ACK)?"assign_ack":"remove_ack");
1286                 if (mISDNport && i>=0)
1287                         bchannel_event(mISDNport, i, (type==BCHANNEL_ASSIGN_ACK)?B_EVENT_EXPORTED:B_EVENT_IMPORTED);
1288                 end_trace();
1289                 break;
1290                 default:
1291                 PERROR("received wrong bchannel message type %d from remote\n", type);
1292         }
1293 }
1294
1295
1296 /*
1297  * handler
1298
1299 audio transmission procedure:
1300 -----------------------------
1301
1302 * priority
1303 three sources of audio transmission:
1304 - crypto-data high priority
1305 - tones high priority (also high)
1306 - remote-data low priority
1307
1308 * elapsed
1309 a variable that temporarily shows the number of samples elapsed since last transmission process.
1310 p_m_last_tv_* is used to store that last timestamp. this is used to calculate the time elapsed.
1311
1312 * load
1313 a variable that is increased whenever data is transmitted.
1314 it is decreased while time elapses. it stores the number of samples that
1315 are currently loaded to dsp module.
1316 since clock in dsp module is the same clock for user space process, these 
1317 times have no skew.
1318
1319 * levels
1320 there are two levels:
1321 ISDN_LOAD will give the load that have to be kept in dsp.
1322 ISDN_MAXLOAD will give the maximum load before dropping.
1323
1324 * procedure for low priority data
1325 see txfromup() for procedure
1326 in short: remote data is ignored during high priority tones
1327
1328 * procedure for high priority data
1329 whenever load is below ISDN_LOAD, load is filled up to ISDN_LOAD
1330 if no more data is available, load becomes empty again.
1331
1332 'load' variable:
1333 0                    ISDN_LOAD           ISDN_MAXLOAD
1334 +--------------------+----------------------+
1335 |                    |                      |
1336 +--------------------+----------------------+
1337
1338 on empty load or on load below ISDN_LOAD, the load is inceased to ISDN_LOAD:
1339 0                    ISDN_LOAD           ISDN_MAXLOAD
1340 +--------------------+----------------------+
1341 |TTTTTTTTTTTTTTTTTTTT|                      |
1342 +--------------------+----------------------+
1343
1344 on empty load, remote-audio causes the load with the remote audio to be increased to ISDN_LOAD.
1345 0                    ISDN_LOAD           ISDN_MAXLOAD
1346 +--------------------+----------------------+
1347 |TTTTTTTTTTTTTTTTTTTTRRRRR                  |
1348 +--------------------+----------------------+
1349
1350  */
1351 int PmISDN::handler(void)
1352 {
1353         struct message *message;
1354         int elapsed = 0;
1355         int ret;
1356
1357         if ((ret = Port::handler()))
1358                 return(ret);
1359
1360         /* get elapsed */
1361         if (p_m_last_tv_sec)
1362         {
1363                 elapsed = 8000 * (now_tv.tv_sec - p_m_last_tv_sec)
1364                         + 8 * (now_tv.tv_usec/1000 - p_m_last_tv_msec);
1365         } else
1366         {
1367                 /* set clock of first process ever in this instance */
1368                 p_m_last_tv_sec = now_tv.tv_sec;
1369                 p_m_last_tv_msec = now_tv.tv_usec/1000;
1370         }
1371         /* process only if we have a minimum of samples, to make packets not too small */
1372         if (elapsed >= ISDN_TRANSMIT)
1373         {
1374                 /* set clock of last process! */
1375                 p_m_last_tv_sec = now_tv.tv_sec;
1376                 p_m_last_tv_msec = now_tv.tv_usec/1000;
1377
1378                 /* update load */
1379                 if (elapsed < p_m_load)
1380                         p_m_load -= elapsed;
1381                 else
1382                         p_m_load = 0;
1383
1384                 /* to send data, tone must be active OR crypt messages must be on */
1385                 if ((p_tone_name[0] || p_m_crypt_msg_loops) && p_m_load < ISDN_LOAD)
1386                 {
1387                         int tosend = ISDN_LOAD - p_m_load, length; 
1388 #ifdef SOCKET_MISDN
1389                         unsigned char buf[MISDN_HEADER_LEN+tosend];
1390                         struct mISDNhead *frm = (struct mISDNhead *)buf;
1391                         unsigned long *d = buf+MISDN_HEADER_LEN;
1392 #else
1393                         unsigned char buf[mISDN_HEADER_LEN+tosend];
1394                         iframe_t *frm = (iframe_t *)buf;
1395                         unsigned char *p = buf+mISDN_HEADER_LEN;
1396 #endif
1397
1398                         /* copy crypto loops */
1399                         while (p_m_crypt_msg_loops && tosend)
1400                         {
1401                                 /* how much do we have to send */
1402                                 length = p_m_crypt_msg_len - p_m_crypt_msg_current;
1403
1404                                 /* clip tosend */
1405                                 if (length > tosend)
1406                                         length = tosend;
1407
1408                                 /* copy message (part) to buffer */
1409                                 memcpy(p, p_m_crypt_msg+p_m_crypt_msg_current, length);
1410
1411                                 /* new position */
1412                                 p_m_crypt_msg_current += length;
1413                                 if (p_m_crypt_msg_current == p_m_crypt_msg_len)
1414                                 {
1415                                         /* next loop */
1416                                         p_m_crypt_msg_current = 0;
1417                                         p_m_crypt_msg_loops--;
1418                                 }
1419
1420                                 /* new length */
1421                                 tosend -= length;
1422                         }
1423
1424                         /* copy tones */
1425                         if (p_tone_name[0] && tosend)
1426                         {
1427                                 tosend -= read_audio(p, tosend);
1428                         }
1429
1430                         /* send data */
1431 #ifdef SOCKET_MISDN
1432                         frm->prim = DL_DATA_REQ;
1433                         frm->id = 0;
1434                         ret = sendto(handle, buffer, MISDN_HEADER_LEN+ISDN_LOAD-p_m_load-tosend, 0, NULL, 0);
1435                         if (!ret)
1436                                 PERROR("Failed to send to socket %d\n", handle);
1437 #else
1438                         frm->prim = DL_DATA | REQUEST; 
1439                         frm->addr = p_m_mISDNport->b_addr[p_m_b_index] | FLG_MSG_DOWN;
1440                         frm->dinfo = 0;
1441                         frm->len = ISDN_LOAD - p_m_load - tosend;
1442 #endif
1443                         if (frm->len)
1444                                 mISDN_write(mISDNdevice, frm, mISDN_HEADER_LEN+frm->len, TIMEOUT_1SEC);
1445                         p_m_load += frm->len;
1446                 }
1447         }
1448
1449         // NOTE: deletion is done by the child class
1450
1451         /* handle timeouts */
1452         if (p_m_timeout)
1453         {
1454                 if (p_m_timer+p_m_timeout < now_d)
1455                 {
1456                         PDEBUG(DEBUG_ISDN, "(%s) timeout after %d seconds detected (state=%d).\n", p_name, p_m_timeout, p_state);
1457                         p_m_timeout = 0;
1458                         /* send timeout to endpoint */
1459                         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_TIMEOUT);
1460                         message->param.state = p_state;
1461                         message_put(message);
1462                         return(1);
1463                 }
1464         }
1465         
1466         return(0); /* nothing done */
1467 }
1468
1469
1470 /*
1471  * whenever we get audio data from bchannel, we process it here
1472  */
1473 #ifdef SOCKET_MISDN
1474 void PmISDN::bchannel_receive(mISDNhead *hh, unsigned char *data, int len)
1475 {
1476         unsigned long cont = *((unsigned long *)data);
1477 #else
1478 void PmISDN::bchannel_receive(iframe_t *frm)
1479 {
1480         int len = frm->len;
1481         unsigned long cont = *((unsigned long *)&frm->data.p);
1482         unsigned char *data =(unsigned char *)&frm->data.p;
1483 #endif
1484         unsigned char *data_temp;
1485         unsigned long length_temp;
1486         struct message *message;
1487         unsigned char *p;
1488         int l;
1489
1490 #ifdef SOCKET_MISDN
1491         if (hh->prim == PH_CONTROL_IND)
1492 #else
1493         if (frm->prim == (PH_CONTROL | INDICATION))
1494 #endif
1495         {
1496                 if (len < 4)
1497                 {
1498                         PERROR("SHORT READ OF PH_CONTROL INDICATION\n");
1499                         return;
1500                 }
1501                 if ((cont&(~DTMF_TONE_MASK)) == DTMF_TONE_VAL)
1502                 {
1503                         chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
1504                         add_trace("DTMF", NULL, "%c", cont & DTMF_TONE_MASK);
1505                         end_trace();
1506                         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_DTMF);
1507                         message->param.dtmf = cont & DTMF_TONE_MASK;
1508                         PDEBUG(DEBUG_PORT, "PmISDN(%s) PH_CONTROL INDICATION  DTMF digit '%c'\n", p_name, message->param.dtmf);
1509                         message_put(message);
1510                         return;
1511                 }
1512                 switch(cont)
1513                 {
1514                         case BF_REJECT:
1515                         chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
1516                         add_trace("DSP-CRYPT", NULL, "error");
1517                         end_trace();
1518                         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CRYPT);
1519                         message->param.crypt.type = CC_ERROR_IND;
1520                         PDEBUG(DEBUG_PORT, "PmISDN(%s) PH_CONTROL INDICATION  reject of blowfish.\n", p_name);
1521                         message_put(message);
1522                         break;
1523
1524                         case BF_ACCEPT:
1525                         chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
1526                         add_trace("DSP-CRYPT", NULL, "ok");
1527                         end_trace();
1528                         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CRYPT);
1529                         message->param.crypt.type = CC_ACTBF_CONF;
1530                         PDEBUG(DEBUG_PORT, "PmISDN(%s) PH_CONTROL INDICATION  accept of blowfish.\n", p_name);
1531                         message_put(message);
1532                         break;
1533
1534                         default:
1535                         chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
1536                         add_trace("unknown", NULL, "0x%x", cont);
1537                         end_trace();
1538                 }
1539                 return;
1540         }
1541 #ifdef SOCKET_MISDN
1542         if (hh->prim == PH_SIGNAL_IND)
1543 #else
1544         if (frm->prim == (PH_SIGNAL | INDICATION))
1545 #endif
1546         {
1547                 switch(frm->dinfo)
1548                 {
1549                         case CMX_TX_DATA:
1550                         if (!p_m_txdata)
1551                         {
1552                                 /* if tx is off, it may happen that fifos send us pending informations, we just ignore them */
1553                                 PDEBUG(DEBUG_BCHANNEL, "PmISDN(%s) ignoring tx data, because 'txdata' is turned off\n", p_name);
1554                                 return;
1555                         }
1556                         /* see below (same condition) */
1557                         if (p_state!=PORT_STATE_CONNECT
1558                                  && !p_m_mISDNport->tones)
1559                                 break;
1560 //                      printf(".");fflush(stdout);return;
1561                         if (p_record)
1562                                 record(data, len, 1); // from up
1563                         break;
1564
1565                         default:
1566                         chan_trace_header(p_m_mISDNport, this, "BCHANNEL signal", DIRECTION_IN);
1567                         add_trace("unknown", NULL, "0x%x", frm->dinfo);
1568                         end_trace();
1569                 }
1570                 return;
1571         }
1572 #ifdef SOCKET_MISDN
1573         if (hh->prim != PH_DATA_IND && hh->prim != DL_DATA_IND)
1574         {
1575                 PERROR("Bchannel received unknown primitve: 0x%x\n", hh->prim);
1576 #else
1577         if (frm->prim != (PH_DATA | INDICATION) && frm->prim != (DL_DATA | INDICATION))
1578         {
1579                 PERROR("Bchannel received unknown primitve: 0x%x\n", frm->prim);
1580 #endif
1581                 return;
1582         }
1583         /* calls will not process any audio data unless
1584          * the call is connected OR interface features audio during call setup.
1585          */
1586 //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);     
1587 #ifndef DEBUG_COREBRIDGE
1588         if (p_state!=PORT_STATE_CONNECT
1589          && !p_m_mISDNport->tones)
1590                 return;
1591 #endif
1592
1593         /* if rx is off, it may happen that fifos send us pending informations, we just ignore them */
1594         if (p_m_rxoff)
1595         {
1596                 PDEBUG(DEBUG_BCHANNEL, "PmISDN(%s) ignoring data, because rx is turned off\n", p_name);
1597                 return;
1598         }
1599
1600         /* record data */
1601         if (p_record)
1602                 record(data, len, 0); // from down
1603
1604         /* randomize and listen to crypt message if enabled */
1605         if (p_m_crypt_listen)
1606         {
1607                 /* the noisy randomizer */
1608                 p = data;
1609                 l = len;
1610                 while(l--)
1611                         mISDN_rand[mISDN_rand_count & 0xff] += *p++;
1612
1613                 cryptman_listen_bch(data, len);
1614         }
1615
1616         p = data;
1617
1618         /* send data to epoint */
1619         if (p_m_joindata && ACTIVE_EPOINT(p_epointlist)) /* only if we have an epoint object */
1620         {
1621                 length_temp = len;
1622                 data_temp = p;
1623                 while(length_temp)
1624                 {
1625                         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_DATA);
1626                         message->param.data.len = (length_temp>sizeof(message->param.data.data))?sizeof(message->param.data.data):length_temp;
1627                         memcpy(message->param.data.data, data_temp, message->param.data.len);
1628                         message_put(message);
1629                         if (length_temp <= sizeof(message->param.data.data))
1630                                 break;
1631                         data_temp += sizeof(message->param.data.data);
1632                         length_temp -= sizeof(message->param.data.data);
1633                 }
1634         }
1635 }
1636
1637
1638 /*
1639  * set echotest
1640  */
1641 void PmISDN::set_echotest(int echo)
1642 {
1643         if (p_m_echo != echo)
1644         {
1645                 p_m_echo = echo;
1646                 PDEBUG(DEBUG_ISDN, "we set echo to echo=%d.\n", p_m_echo);
1647                 if (p_m_b_channel)
1648                         if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1649 #ifdef SOCKET_MISDN
1650                                 ph_control(p_m_mISDNport, this, p_m_mISDNport->b_socket[p_m_b_index], p_m_echo?CMX_ECHO_ON:CMX_ECHO_OFF, 0, "DSP-ECHO", p_m_echo);
1651 #else
1652                                 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);
1653 #endif
1654         }
1655 }
1656
1657 /*
1658  * set tone
1659  */
1660 void PmISDN::set_tone(char *dir, char *tone)
1661 {
1662         int id;
1663
1664         if (!tone)
1665                 tone = "";
1666         PDEBUG(DEBUG_ISDN, "isdn port now plays tone:'%s'.\n", tone);
1667         if (!tone[0])
1668         {
1669                 id = TONE_OFF;
1670                 goto setdsp;
1671         }
1672
1673         /* check if we NOT really have to use a dsp-tone */
1674         if (!options.dsptones)
1675         {
1676                 nodsp:
1677                 if (p_m_tone)
1678                 if (p_m_b_index >= 0)
1679                 if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1680                 {
1681                         PDEBUG(DEBUG_ISDN, "we reset tone from id=%d to OFF.\n", p_m_tone);
1682 #ifdef SOCKET_MISDN
1683                         ph_control(p_m_mISDNport, this, p_m_mISDNport->b_socket[p_m_b_index], TONE_PATT_OFF, 0, "DSP-TONE", 0);
1684 #else
1685                         ph_control(p_m_mISDNport, this, p_m_mISDNport->b_addr[p_m_b_index], TONE_PATT_OFF, 0, "DSP-TONE", 0);
1686 #endif
1687                 }
1688                 p_m_tone = 0;
1689                 Port::set_tone(dir, tone);
1690                 return;
1691         }
1692         if (p_tone_dir[0])
1693                 goto nodsp;
1694
1695         /* now we USE dsp-tone, convert name */
1696         else if (!strcmp(tone, "dialtone"))
1697         {
1698                 switch(options.dsptones) {
1699                 case DSP_AMERICAN: id = TONE_AMERICAN_DIALTONE; break;
1700                 case DSP_GERMAN: id = TONE_GERMAN_DIALTONE; break;
1701                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDDIALTONE; break;
1702                 }
1703         } else if (!strcmp(tone, "dialpbx"))
1704         {
1705                 switch(options.dsptones) {
1706                 case DSP_AMERICAN: id = TONE_AMERICAN_DIALPBX; break;
1707                 case DSP_GERMAN: id = TONE_GERMAN_DIALPBX; break;
1708                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDDIALPBX; break;
1709                 }
1710         } else if (!strcmp(tone, "ringing"))
1711         {
1712                 switch(options.dsptones) {
1713                 case DSP_AMERICAN: id = TONE_AMERICAN_RINGING; break;
1714                 case DSP_GERMAN: id = TONE_GERMAN_RINGING; break;
1715                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDRINGING; break;
1716                 }
1717         } else if (!strcmp(tone, "ringpbx"))
1718         {
1719                 switch(options.dsptones) {
1720                 case DSP_AMERICAN: id = TONE_AMERICAN_RINGPBX; break;
1721                 case DSP_GERMAN: id = TONE_GERMAN_RINGPBX; break;
1722                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDRINGPBX; break;
1723                 }
1724         } else if (!strcmp(tone, "busy"))
1725         {
1726                 busy:
1727                 switch(options.dsptones) {
1728                 case DSP_AMERICAN: id = TONE_AMERICAN_BUSY; break;
1729                 case DSP_GERMAN: id = TONE_GERMAN_BUSY; break;
1730                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDBUSY; break;
1731                 }
1732         } else if (!strcmp(tone, "release"))
1733         {
1734                 hangup:
1735                 switch(options.dsptones) {
1736                 case DSP_AMERICAN: id = TONE_AMERICAN_HANGUP; break;
1737                 case DSP_GERMAN: id = TONE_GERMAN_HANGUP; break;
1738                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDHANGUP; break;
1739                 }
1740         } else if (!strcmp(tone, "cause_10"))
1741                 goto hangup;
1742         else if (!strcmp(tone, "cause_11"))
1743                 goto busy;
1744         else if (!strcmp(tone, "cause_22"))
1745         {
1746                 switch(options.dsptones) {
1747                 case DSP_AMERICAN: id = TONE_SPECIAL_INFO; break;
1748                 case DSP_GERMAN: id = TONE_GERMAN_GASSENBESETZT; break;
1749                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDBUSY; break;
1750                 }
1751         } else if (!strncmp(tone, "cause_", 6))
1752                 id = TONE_SPECIAL_INFO;
1753         else
1754                 id = TONE_OFF;
1755
1756         /* if we have a tone that is not supported by dsp */
1757         if (id==TONE_OFF && tone[0])
1758                 goto nodsp;
1759
1760         setdsp:
1761         if (p_m_tone != id)
1762         {
1763                 /* set new tone */
1764                 p_m_tone = id;
1765                 PDEBUG(DEBUG_ISDN, "we set tone to id=%d.\n", p_m_tone);
1766                 if (p_m_b_index >= 0)
1767                 if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1768 #ifdef SOCKET_MISDN
1769                         ph_control(p_m_mISDNport, this, p_m_mISDNport->b_socket[p_m_b_index], p_m_tone?TONE_PATT_ON:TONE_PATT_OFF, p_m_tone, "DSP-TONE", p_m_tone);
1770 #else
1771                         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);
1772 #endif
1773         }
1774         /* turn user-space tones off in cases of no tone OR dsp tone */
1775         Port::set_tone("",NULL);
1776 }
1777
1778
1779 /* MESSAGE_mISDNSIGNAL */
1780 //extern struct message *dddebug;
1781 void PmISDN::message_mISDNsignal(unsigned long epoint_id, int message_id, union parameter *param)
1782 {
1783         switch(param->mISDNsignal.message)
1784         {
1785                 case mISDNSIGNAL_VOLUME:
1786                 if (p_m_txvol != param->mISDNsignal.txvol)
1787                 {
1788                         p_m_txvol = param->mISDNsignal.txvol;
1789                         PDEBUG(DEBUG_BCHANNEL, "we change tx-volume to shift=%d.\n", p_m_txvol);
1790                         if (p_m_b_index >= 0)
1791                         if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1792 #ifdef SOCKET_MISDN
1793                                 ph_control(p_m_mISDNport, this, p_m_mISDNport->b_socket[p_m_b_index], VOL_CHANGE_TX, p_m_txvol, "DSP-TXVOL", p_m_txvol);
1794 #else
1795                                 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);
1796 #endif
1797                 } else
1798                         PDEBUG(DEBUG_BCHANNEL, "we already have tx-volume shift=%d.\n", p_m_rxvol);
1799                 if (p_m_rxvol != param->mISDNsignal.rxvol)
1800                 {
1801                         p_m_rxvol = param->mISDNsignal.rxvol;
1802                         PDEBUG(DEBUG_BCHANNEL, "we change rx-volume to shift=%d.\n", p_m_rxvol);
1803                         if (p_m_b_index >= 0)
1804                         if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1805 #ifdef SOCKET_MISDN
1806                                 ph_control(p_m_mISDNport, this, p_m_mISDNport->b_socket[p_m_b_index], VOL_CHANGE_RX, p_m_rxvol, "DSP-RXVOL", p_m_rxvol);
1807 #else
1808                                 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);
1809 #endif
1810                 } else
1811                         PDEBUG(DEBUG_BCHANNEL, "we already have rx-volume shift=%d.\n", p_m_rxvol);
1812                 break;
1813
1814                 case mISDNSIGNAL_CONF:
1815 //if (dddebug) PDEBUG(DEBUG_ISDN, "dddebug = %d\n", dddebug->type);
1816 //tone          if (!p_m_tone && p_m_conf!=param->mISDNsignal.conf)
1817                 if (p_m_conf != param->mISDNsignal.conf)
1818                 {
1819                         p_m_conf = param->mISDNsignal.conf;
1820                         PDEBUG(DEBUG_BCHANNEL, "we change conference to conf=%d.\n", p_m_conf);
1821                         if (p_m_b_index >= 0)
1822                         if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1823 #ifdef SOCKET_MISDN
1824                                 ph_control(p_m_mISDNport, this, p_m_mISDNport->b_socket[p_m_b_index], (p_m_conf)?CMX_CONF_JOIN:CMX_CONF_SPLIT, p_m_conf, "DSP-CONF", p_m_conf);
1825 #else
1826                                 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);
1827 #endif
1828                 } else
1829                         PDEBUG(DEBUG_BCHANNEL, "we already have conf=%d.\n", p_m_conf);
1830                 /* we must set, even if currently tone forbids conf */
1831                 p_m_conf = param->mISDNsignal.conf;
1832 //if (dddebug) PDEBUG(DEBUG_ISDN, "dddebug = %d\n", dddebug->type);
1833                 break;
1834
1835                 case mISDNSIGNAL_JOINDATA:
1836                 if (p_m_joindata != param->mISDNsignal.joindata)
1837                 {
1838                         p_m_joindata = param->mISDNsignal.joindata;
1839                         PDEBUG(DEBUG_BCHANNEL, "we change to joindata=%d.\n", p_m_joindata);
1840                 } else
1841                         PDEBUG(DEBUG_BCHANNEL, "we already have joindata=%d.\n", p_m_joindata);
1842                 break;
1843                 
1844                 case mISDNSIGNAL_DELAY:
1845                 if (p_m_delay != param->mISDNsignal.delay)
1846                 {
1847                         p_m_delay = param->mISDNsignal.delay;
1848                         PDEBUG(DEBUG_BCHANNEL, "we change delay mode to delay=%d.\n", p_m_delay);
1849                         if (p_m_b_index >= 0)
1850                         if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1851 #ifdef SOCKET_MISDN
1852                                 ph_control(p_m_mISDNport, this, p_m_mISDNport->b_socket[p_m_b_index], p_m_delay?CMX_DELAY:CMX_JITTER, p_m_delay, "DSP-DELAY", p_m_delay);
1853 #else
1854                                 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);
1855 #endif
1856                 } else
1857                         PDEBUG(DEBUG_BCHANNEL, "we already have delay=%d.\n", p_m_delay);
1858                 break;
1859
1860                 default:
1861                 PERROR("PmISDN(%s) unsupported signal message %d.\n", p_name, param->mISDNsignal.message);
1862         }
1863 }
1864
1865 /* MESSAGE_CRYPT */
1866 void PmISDN::message_crypt(unsigned long epoint_id, int message_id, union parameter *param)
1867 {
1868         struct message *message;
1869
1870         switch(param->crypt.type)
1871         {
1872                 case CC_ACTBF_REQ:           /* activate blowfish */
1873                 p_m_crypt = 1;
1874                 p_m_crypt_key_len = param->crypt.len;
1875                 if (p_m_crypt_key_len > (int)sizeof(p_m_crypt_key))
1876                 {
1877                         PERROR("PmISDN(%s) key too long %d > %d\n", p_name, p_m_crypt_key_len, sizeof(p_m_crypt_key));
1878                         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CRYPT);
1879                         message->param.crypt.type = CC_ERROR_IND;
1880                         message_put(message);
1881                         break;
1882                 }
1883                 memcpy(p_m_crypt_key, param->crypt.data, p_m_crypt_key_len);
1884                 crypt_off:
1885                 PDEBUG(DEBUG_BCHANNEL, "we set encryption to crypt=%d. (0 means OFF)\n", p_m_crypt);
1886                 if (p_m_b_index >= 0)
1887                 if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1888 #ifdef SOCKET_MISDN
1889                         ph_control_block(p_m_mISDNport, this, p_m_mISDNport->b_socket[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);
1890 #else
1891                         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);
1892 #endif
1893                 break;
1894
1895                 case CC_DACT_REQ:            /* deactivate session encryption */
1896                 p_m_crypt = 0;
1897                 goto crypt_off;
1898                 break;
1899
1900                 case CR_LISTEN_REQ:          /* start listening to messages */
1901                 p_m_crypt_listen = 1;
1902                 p_m_crypt_listen_state = 0;
1903                 break;
1904
1905                 case CR_UNLISTEN_REQ:        /* stop listening to messages */
1906                 p_m_crypt_listen = 0;
1907                 break;
1908
1909                 case CR_MESSAGE_REQ:         /* send message */
1910                 p_m_crypt_msg_len = cryptman_encode_bch(param->crypt.data, param->crypt.len, p_m_crypt_msg, sizeof(p_m_crypt_msg));
1911                 if (!p_m_crypt_msg_len)
1912                 {
1913                         PERROR("PmISDN(%s) message too long %d > %d\n", p_name, param->crypt.len-1, sizeof(p_m_crypt_msg));
1914                         break;
1915                 }
1916                 p_m_crypt_msg_current = 0; /* reset */
1917                 p_m_crypt_msg_loops = 3; /* enable */
1918 #if 0
1919                 /* disable txmix, or we get corrupt data due to audio process */
1920                 if (p_m_txmix && p_m_b_index>=0)
1921                 {
1922                         PDEBUG(DEBUG_BCHANNEL, "for sending CR_MESSAGE_REQ, we reset txmix from txmix=%d.\n", p_m_txmix);
1923 #ifdef SOCKET_MISDN
1924                         ph_control(p_m_mISDNport, this, p_mISDNport->b_socket[p_m_b_index], CMX_MIX_OFF, 0, "DSP-TXMIX", 0);
1925 #else
1926                         ph_control(p_m_mISDNport, this, p_mISDNport->b_addr[p_m_b_index], CMX_MIX_OFF, 0, "DSP-TXMIX", 0);
1927 #endif
1928                 }
1929 #endif
1930                 break;
1931
1932                 default:
1933                 PERROR("PmISDN(%s) unknown crypt message %d\n", p_name, param->crypt.type);
1934         }
1935
1936 }
1937
1938 /*
1939  * endpoint sends messages to the port
1940  */
1941 int PmISDN::message_epoint(unsigned long epoint_id, int message_id, union parameter *param)
1942 {
1943         if (Port::message_epoint(epoint_id, message_id, param))
1944                 return(1);
1945
1946         switch(message_id)
1947         {
1948                 case MESSAGE_DATA: /* tx-data from upper layer */
1949                 txfromup(param->data.data, param->data.len);
1950                 return(1);
1951
1952                 case MESSAGE_mISDNSIGNAL: /* user command */
1953                 PDEBUG(DEBUG_ISDN, "PmISDN(%s) received special ISDN SIGNAL %d.\n", p_name, param->mISDNsignal.message);
1954                 message_mISDNsignal(epoint_id, message_id, param);
1955                 return(1);
1956
1957                 case MESSAGE_CRYPT: /* crypt control command */
1958                 PDEBUG(DEBUG_ISDN, "PmISDN(%s) received encryption command '%d'.\n", p_name, param->crypt.type);
1959                 message_crypt(epoint_id, message_id, param);
1960                 return(1);
1961         }
1962
1963         return(0);
1964 }
1965
1966
1967 /*
1968  * main loop for processing messages from mISDN
1969  */
1970 #ifdef SOCKET_MISDN
1971 int mISDN_handler(void)
1972 {
1973         int ret;
1974         struct mISDNport *mISDNport;
1975         class PmISDN *isdnport;
1976         int i;
1977         char buffer[2048+MISDN_HEADER_LEN];
1978         struct mISDNhead *hh = (struct mISDNhead *)buffer;
1979
1980         /* process all ports */
1981         mISDNport = mISDNport_first;
1982         while(mISDNport)
1983         {
1984                 /* process all bchannels */
1985                 i = 0;
1986                 while(i < mISDNport->b_num)
1987                 {
1988                         /* handle port of bchannel */
1989                         isdnport=mISDNport->b_port[i];
1990                         if (isdnport)
1991                         {
1992                                 /* call bridges in user space OR crypto OR recording */
1993                                 if (isdnport->p_m_joindata || isdnport->p_m_crypt_msg_loops || isdnport->p_m_crypt_listen || isdnport->p_record)
1994                                 {
1995                                         /* rx IS required */
1996                                         if (isdnport->p_m_rxoff)
1997                                         {
1998                                                 /* turn on RX */
1999                                                 isdnport->p_m_rxoff = 0;
2000                                                 PDEBUG(DEBUG_BCHANNEL, "%s: receive data is required, so we turn them on\n");
2001                                                 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
2002                                                         ph_control(mISDNport, isdnport, mISDNport->b_socket[isdnport->p_m_b_index], CMX_RECEIVE_ON, 0, "DSP-RXOFF", 0);
2003                                                 return(1);
2004                                         }
2005                                 } else
2006                                 {
2007                                         /* rx NOT required */
2008                                         if (!isdnport->p_m_rxoff)
2009                                         {
2010                                                 /* turn off RX */
2011                                                 isdnport->p_m_rxoff = 1;
2012                                                 PDEBUG(DEBUG_BCHANNEL, "%s: receive data is not required, so we turn them off\n");
2013                                                 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
2014                                                         ph_control(mISDNport, isdnport, mISDNport->b_socket[isdnport->p_m_b_index], CMX_RECEIVE_OFF, 0, "DSP-RXOFF", 1);
2015                                                 return(1);
2016                                         }
2017                                 }
2018                                 /* recording */
2019                                 if (isdnport->p_record)
2020                                 {
2021                                         /* txdata IS required */
2022                                         if (!isdnport->p_m_txdata)
2023                                         {
2024                                                 /* turn on RX */
2025                                                 isdnport->p_m_txdata = 1;
2026                                                 PDEBUG(DEBUG_BCHANNEL, "%s: transmit data is required, so we turn them on\n");
2027                                                 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
2028                                                         ph_control(mISDNport, isdnport, mISDNport->b_socket[isdnport->p_m_b_index], CMX_TXDATA_ON, 0, "DSP-TXDATA", 1);
2029                                                 return(1);
2030                                         }
2031                                 } else
2032                                 {
2033                                         /* txdata NOT required */
2034                                         if (isdnport->p_m_txdata)
2035                                         {
2036                                                 /* turn off RX */
2037                                                 isdnport->p_m_txdata = 0;
2038                                                 PDEBUG(DEBUG_BCHANNEL, "%s: transmit data is not required, so we turn them off\n");
2039                                                 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
2040                                                         ph_control(mISDNport, isdnport, mISDNport->b_socket[isdnport->p_m_b_index], CMX_TXDATA_OFF, 0, "DSP-TXDATA", 0);
2041                                                 return(1);
2042                                         }
2043                                 }
2044                         }
2045
2046                         /* handle message from bchannel */
2047                         if (mISDNport->b_stack[i] > -1)
2048                         {
2049                                 ret = recv(mISDNport->b_stack[i], buffer, sizeof(buffer), 0);
2050                                 if (ret >= MISDN_HEADER_LEN)
2051                                 {
2052                                         switch(hh->prim)
2053                                         {
2054                                                 /* we don't care about confirms, we use rx data to sync tx */
2055                                                 case PH_DATA_CONF:
2056                                                 case DL_DATA_CONF:
2057                                                 break;
2058
2059                                                 /* we receive audio data, we respond to it AND we send tones */
2060                                                 case PH_DATA_IND:
2061                                                 case DL_DATA_IND:
2062                                                 case PH_CONTROL_IND:
2063                                                 if (mISDNport->b_port[i])
2064                                                         mISDNport->b_port[i]->bchannel_receive(hh, buffer+MISDN_HEADER_LEN, ret-MISDN_HEADER_LEN);
2065                                                 else
2066                                                         PDEBUG(DEBUG_BCHANNEL, "b-channel is not associated to an ISDNPort (socket %d), ignoring.\n", mISDNport->b_stack[i]);
2067                                                 break;
2068
2069                                                 case PH_ACTIVATE_IND:
2070                                                 case DL_ESTABLISH_IND:
2071                                                 case PH_ACTIVATE_CONF:
2072                                                 case DL_ESTABLISH_CONF:
2073                                                 PDEBUG(DEBUG_BCHANNEL, "DL_ESTABLISH confirm: bchannel is now activated (socket %d).\n", mISDNport->b_socket[i]);
2074                                                 bchannel_event(mISDNport, i, B_EVENT_ACTIVATED);
2075                                                 break;
2076
2077                                                 case PH_DEACTIVATE_IND:
2078                                                 case DL_RELEASE_IND:
2079                                                 case PH_DEACTIVATE_CONF:
2080                                                 case DL_RELEASE_CONF:
2081                                                 PDEBUG(DEBUG_BCHANNEL, "DL_RELEASE confirm: bchannel is now de-activated (socket %d).\n", mISDNport->b_socket[i]);
2082                                                 bchannel_event(mISDNport, i, B_EVENT_DEACTIVATED);
2083                                                 break;
2084
2085                                                 default:
2086                                                 PERROR("child message not handled: prim(0x%x) socket(%d) msg->len(%d)\n", hh->prim, mISDNport->b_socket[i], msg->len);
2087                                         }
2088                                 } else
2089                                 {
2090                                         if (ret < 0 && errno != EWOULDBLOCK)
2091                                                 PERROR("Read from port %d, index %d failed with return code %d\n", mISDNport->portnum, i, ret);
2092                                 }
2093                         }
2094                         
2095                         i++;
2096                 }
2097 #if 0
2098                 if (mISDNport->l1timeout && now>mISDNport->l1timeout)
2099                 { ---}
2100                         PDEBUG(DEBUG_ISDN, "the L1 establish timer expired, we release all pending messages.\n", mISDNport->portnum);
2101                         mISDNport->l1timeout = 0;
2102 #endif
2103
2104                 /* layer 2 establish timer */
2105                 if (mISDNport->l2establish)
2106                 {
2107                         if (now-mISDNport->l2establish > 5)
2108                         {
2109
2110                                 PDEBUG(DEBUG_ISDN, "the L2 establish timer expired, we try to establish the link portnum=%d.\n", mISDNport->portnum);
2111                                 mISDNport->ml3->to_layer2(mISDNport->ml3, DL_ESTABLISH_REQ);
2112                                 l1l2l3_trace_header(mISDNport, NULL, DL_ESTABLISH_REQ, DIRECTION_OUT);
2113                                 end_trace();
2114                                 return(1);
2115                         }
2116                 }
2117
2118
2119                 mISDNport = mISDNport->next;
2120         }
2121
2122 }
2123 #else
2124 int mISDN_handler(void)
2125 {
2126         int ret;
2127         struct mISDNport *mISDNport;
2128         class PmISDN *isdnport;
2129         int i;
2130         msg_t *msg;
2131         iframe_t *frm;
2132         msg_t *dmsg;
2133         mISDNuser_head_t *hh;
2134         net_stack_t *nst;
2135
2136         /* the que avoids loopbacks when replying to stack after receiving
2137          * from stack. */
2138         mISDNport = mISDNport_first;
2139         while(mISDNport)
2140         {
2141                 /* process turning on/off rx */
2142                 i = 0;
2143                 while(i < mISDNport->b_num)
2144                 {
2145                         isdnport=mISDNport->b_port[i];
2146                         if (isdnport)
2147                         {
2148                                 /* call bridges in user space OR crypto OR recording */
2149                                 if (isdnport->p_m_joindata || isdnport->p_m_crypt_msg_loops || isdnport->p_m_crypt_listen || isdnport->p_record)
2150                                 {
2151                                         /* rx IS required */
2152                                         if (isdnport->p_m_rxoff)
2153                                         {
2154                                                 /* turn on RX */
2155                                                 isdnport->p_m_rxoff = 0;
2156                                                 PDEBUG(DEBUG_BCHANNEL, "%s: receive data is required, so we turn them on\n");
2157                                                 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
2158                                                         ph_control(mISDNport, isdnport, mISDNport->b_addr[isdnport->p_m_b_index], CMX_RECEIVE_ON, 0, "DSP-RXOFF", 0);
2159                                                 return(1);
2160                                         }
2161                                 } else
2162                                 {
2163                                         /* rx NOT required */
2164                                         if (!isdnport->p_m_rxoff)
2165                                         {
2166                                                 /* turn off RX */
2167                                                 isdnport->p_m_rxoff = 1;
2168                                                 PDEBUG(DEBUG_BCHANNEL, "%s: receive data is not required, so we turn them off\n");
2169                                                 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
2170                                                         ph_control(mISDNport, isdnport, mISDNport->b_addr[isdnport->p_m_b_index], CMX_RECEIVE_OFF, 0, "DSP-RXOFF", 1);
2171                                                 return(1);
2172                                         }
2173                                 }
2174                                 /* recording */
2175                                 if (isdnport->p_record)
2176                                 {
2177                                         /* txdata IS required */
2178                                         if (!isdnport->p_m_txdata)
2179                                         {
2180                                                 /* turn on RX */
2181                                                 isdnport->p_m_txdata = 1;
2182                                                 PDEBUG(DEBUG_BCHANNEL, "%s: transmit data is required, so we turn them on\n");
2183                                                 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
2184                                                         ph_control(mISDNport, isdnport, mISDNport->b_addr[isdnport->p_m_b_index], CMX_TXDATA_ON, 0, "DSP-TXDATA", 1);
2185                                                 return(1);
2186                                         }
2187                                 } else
2188                                 {
2189                                         /* txdata NOT required */
2190                                         if (isdnport->p_m_txdata)
2191                                         {
2192                                                 /* turn off RX */
2193                                                 isdnport->p_m_txdata = 0;
2194                                                 PDEBUG(DEBUG_BCHANNEL, "%s: transmit data is not required, so we turn them off\n");
2195                                                 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
2196                                                         ph_control(mISDNport, isdnport, mISDNport->b_addr[isdnport->p_m_b_index], CMX_TXDATA_OFF, 0, "DSP-TXDATA", 0);
2197                                                 return(1);
2198                                         }
2199                                 }
2200                         }
2201                         i++;
2202                 }
2203 #if 0
2204                 if (mISDNport->l1timeout && now>mISDNport->l1timeout)
2205                 { ---}
2206                         PDEBUG(DEBUG_ISDN, "the L1 establish timer expired, we release all pending messages.\n", mISDNport->portnum);
2207                         mISDNport->l1timeout = 0;
2208 #endif
2209
2210                 if (mISDNport->l2establish)
2211                 {
2212                         if (now-mISDNport->l2establish > 5)
2213                         {
2214                                 if (mISDNport->ntmode)
2215                                 {
2216                                         PDEBUG(DEBUG_ISDN, "the L2 establish timer expired, we try to establish the link NT portnum=%d.\n", mISDNport->portnum);
2217                                         time(&mISDNport->l2establish);
2218                                         /* establish */
2219                                         dmsg = create_l2msg(DL_ESTABLISH | REQUEST, 0, 0);
2220                                         if (mISDNport->nst.manager_l3(&mISDNport->nst, dmsg))
2221                                                 free_msg(dmsg);
2222                                 } else {
2223                                         iframe_t act;
2224
2225                                         PDEBUG(DEBUG_ISDN, "the L2 establish timer expired, we try to establish the link TE portnum=%d.\n", mISDNport->portnum);
2226                                         time(&mISDNport->l2establish);
2227                                         /* establish */
2228                                         act.prim = DL_ESTABLISH | REQUEST; 
2229                                         act.addr = (mISDNport->upper_id & ~LAYER_ID_MASK) | 3 | FLG_MSG_DOWN;
2230                                         act.dinfo = 0;
2231                                         act.len = 0;
2232                                         mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
2233                                 }
2234                                 l1l2l3_trace_header(mISDNport, NULL, DL_ESTABLISH | REQUEST, DIRECTION_OUT);
2235                                 end_trace();
2236                                 return(1);
2237                         }
2238                 }
2239                 if ((dmsg = msg_dequeue(&mISDNport->downqueue)))
2240                 {
2241                         if (mISDNport->ntmode)
2242                         {
2243                                 hh = (mISDNuser_head_t *)dmsg->data;
2244                                 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);
2245                                 if (mISDNport->nst.manager_l3(&mISDNport->nst, dmsg))
2246                                         free_msg(dmsg);
2247                         } else
2248                         {
2249                                 frm = (iframe_t *)dmsg->data;
2250                                 frm->addr = mISDNport->upper_id | FLG_MSG_DOWN;
2251                                 frm->len = (dmsg->len) - mISDN_HEADER_LEN;
2252                                 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);
2253                                 mISDN_write(mISDNdevice, dmsg->data, dmsg->len, TIMEOUT_1SEC);
2254                                 free_msg(dmsg);
2255                         }
2256                         return(1);
2257                 }
2258                 mISDNport = mISDNport->next;
2259         } 
2260
2261         /* no device, no read */
2262         if (mISDNdevice < 0)
2263                 return(0);
2264
2265         /* get message from kernel */
2266         if (!(msg = alloc_msg(MAX_MSG_SIZE)))
2267                 return(1);
2268         ret = mISDN_read(mISDNdevice, msg->data, MAX_MSG_SIZE, 0);
2269         if (ret < 0)
2270         {
2271                 free_msg(msg);
2272                 if (errno == EAGAIN)
2273                         return(0);
2274                 FATAL("Failed to do mISDN_read()\n");
2275         }
2276         if (!ret)
2277         {
2278                 free_msg(msg);
2279 //              printf("%s: ERROR: mISDN_read() returns nothing\n");
2280                 return(0);
2281         }
2282         msg->len = ret;
2283         frm = (iframe_t *)msg->data;
2284
2285         /* global prim */
2286         switch(frm->prim)
2287         {
2288                 case MGR_DELLAYER | CONFIRM:
2289                 case MGR_INITTIMER | CONFIRM:
2290                 case MGR_ADDTIMER | CONFIRM:
2291                 case MGR_DELTIMER | CONFIRM:
2292                 case MGR_REMOVETIMER | CONFIRM:
2293                 free_msg(msg);
2294                 return(1);
2295         }
2296
2297         /* handle timer events from mISDN for NT-stack
2298          * note: they do not associate with a stack */
2299         if (frm->prim == (MGR_TIMER | INDICATION))
2300         {
2301                 itimer_t *it;
2302
2303                 /* find mISDNport */
2304                 mISDNport = mISDNport_first;
2305                 while(mISDNport)
2306                 {
2307                         /* nt mode only */
2308                         if (mISDNport->ntmode)
2309                         {
2310                                 it = mISDNport->nst.tlist;
2311                                 /* find timer */
2312                                 while(it)
2313                                 {
2314                                         if (it->id == (int)frm->addr)
2315                                                 break;
2316                                         it = it->next;
2317                                 }
2318                                 if (it)
2319                                         break;
2320                         }
2321                         mISDNport = mISDNport->next;
2322                 }
2323                 if (mISDNport)
2324                 {
2325                         mISDN_write_frame(mISDNdevice, msg->data, mISDNport->upper_id | FLG_MSG_DOWN,
2326                                 MGR_TIMER | RESPONSE, 0, 0, NULL, TIMEOUT_1SEC);
2327
2328                         PDEBUG(DEBUG_ISDN, "timer-indication port %d it=%p\n", mISDNport->portnum, it);
2329                         test_and_clear_bit(FLG_TIMER_RUNING, (long unsigned int *)&it->Flags);
2330                         ret = it->function(it->data);
2331                 } else
2332                 {
2333                         PDEBUG(DEBUG_ISDN, "timer-indication not handled\n");
2334                 }
2335                 goto out;
2336         }
2337
2338         /* find the mISDNport that belongs to the stack */
2339         mISDNport = mISDNport_first;
2340         while(mISDNport)
2341         {
2342                 if ((frm->addr&MASTER_ID_MASK) == (unsigned int)(mISDNport->upper_id&MASTER_ID_MASK))
2343                         break;
2344                 mISDNport = mISDNport->next;
2345         } 
2346         if (!mISDNport)
2347         {
2348                 PERROR("message belongs to no mISDNport: prim(0x%x) addr(0x%x) msg->len(%d)\n", frm->prim, frm->addr, msg->len);
2349                 goto out;
2350         }
2351
2352         /* master stack */
2353         if (!(frm->addr&FLG_CHILD_STACK))
2354         {
2355                 /* d-message */
2356                 switch(frm->prim)
2357                 {
2358                         case MGR_SHORTSTATUS | INDICATION:
2359                         case MGR_SHORTSTATUS | CONFIRM:
2360                         switch(frm->dinfo) {
2361                                 case SSTATUS_L1_ACTIVATED:
2362                                 l1l2l3_trace_header(mISDNport, NULL, PH_ACTIVATE | (frm->prim & 0x3), DIRECTION_IN);
2363                                 end_trace();
2364                                 goto ss_act;
2365                                 case SSTATUS_L1_DEACTIVATED:
2366                                 l1l2l3_trace_header(mISDNport, NULL, PH_DEACTIVATE | (frm->prim & 0x3), DIRECTION_IN);
2367                                 end_trace();
2368                                 goto ss_deact;
2369                                 case SSTATUS_L2_ESTABLISHED:
2370                                 l1l2l3_trace_header(mISDNport, NULL, DL_ESTABLISH | (frm->prim & 0x3), DIRECTION_IN);
2371                                 end_trace();
2372                                 goto ss_estab;
2373                                 case SSTATUS_L2_RELEASED:
2374                                 l1l2l3_trace_header(mISDNport, NULL, DL_RELEASE | (frm->prim & 0x3), DIRECTION_IN);
2375                                 end_trace();
2376                                 goto ss_rel;
2377                         }
2378                         break;
2379
2380                         case PH_ACTIVATE | CONFIRM:
2381                         case PH_ACTIVATE | INDICATION:
2382                         l1l2l3_trace_header(mISDNport, NULL, frm->prim, DIRECTION_IN);
2383                         end_trace();
2384                         if (mISDNport->ntmode)
2385                         {
2386                                 mISDNport->l1link = 1;
2387                                 setup_queue(mISDNport, 1);
2388                                 goto l1_msg;
2389                         }
2390                         ss_act:
2391                         mISDNport->l1link = 1;
2392                         setup_queue(mISDNport, 1);
2393                         break;
2394
2395                         case PH_DEACTIVATE | CONFIRM:
2396                         case PH_DEACTIVATE | INDICATION:
2397                         l1l2l3_trace_header(mISDNport, NULL, frm->prim, DIRECTION_IN);
2398                         end_trace();
2399                         if (mISDNport->ntmode)
2400                         {
2401                                 mISDNport->l1link = 0;
2402                                 setup_queue(mISDNport, 0);
2403                                 goto l1_msg;
2404                         }
2405                         ss_deact:
2406                         mISDNport->l1link = 0;
2407                         setup_queue(mISDNport, 0);
2408                         break;
2409
2410                         case PH_CONTROL | CONFIRM:
2411                         case PH_CONTROL | INDICATION:
2412                         PDEBUG(DEBUG_ISDN, "Received PH_CONTROL for port %d (%s).\n", mISDNport->portnum, mISDNport->ifport->interface->name);
2413                         break;
2414
2415                         case DL_ESTABLISH | INDICATION:
2416                         case DL_ESTABLISH | CONFIRM:
2417                         l1l2l3_trace_header(mISDNport, NULL, frm->prim, DIRECTION_IN);
2418                         end_trace();
2419                         if (!mISDNport->ntmode) break; /* !!!!!!!!!!!!!!!! */
2420                         ss_estab:
2421                         if (mISDNport->l2establish)
2422                         {
2423                                 mISDNport->l2establish = 0;
2424                                 PDEBUG(DEBUG_ISDN, "the link became active before l2establish timer expiry.\n");
2425                         }
2426                         mISDNport->l2link = 1;
2427                         break;
2428
2429                         case DL_RELEASE | INDICATION:
2430                         case DL_RELEASE | CONFIRM:
2431                         l1l2l3_trace_header(mISDNport, NULL, frm->prim, DIRECTION_IN);
2432                         end_trace();
2433                         if (!mISDNport->ntmode) break; /* !!!!!!!!!!!!!!!! */
2434                         ss_rel:
2435                         mISDNport->l2link = 0;
2436                         if (mISDNport->ptp)
2437                         {
2438                                 time(&mISDNport->l2establish);
2439                                 PDEBUG(DEBUG_ISDN, "because we are ptp, we set a l2establish timer.\n");
2440                         }
2441                         break;
2442
2443                         default:
2444                         l1_msg:
2445                         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);
2446                         if (frm->dinfo==(signed long)0xffffffff && frm->prim==(PH_DATA|CONFIRM))
2447                         {
2448                                 PERROR("SERIOUS BUG, dinfo == 0xffffffff, prim == PH_DATA | CONFIRM !!!!\n");
2449                         }
2450                         /* d-message */
2451                         if (mISDNport->ntmode)
2452                         {
2453                                 /* l1-data enters the nt-mode library */
2454                                 nst = &mISDNport->nst;
2455                                 if (nst->l1_l2(nst, msg))
2456                                         free_msg(msg);
2457                                 return(1);
2458                         } else
2459                         {
2460                                 /* l3-data is sent to pbx */
2461                                 if (stack2manager_te(mISDNport, msg))
2462                                         free_msg(msg);
2463                                 return(1);
2464                         }
2465                 }
2466         } else
2467         /* child stack */
2468         {
2469                 /* b-message */
2470                 switch(frm->prim)
2471                 {
2472                         /* we don't care about confirms, we use rx data to sync tx */
2473                         case PH_DATA | CONFIRM:
2474                         case DL_DATA | CONFIRM:
2475                         break;
2476
2477                         /* we receive audio data, we respond to it AND we send tones */
2478                         case PH_DATA | INDICATION:
2479                         case DL_DATA | INDICATION:
2480                         case PH_CONTROL | INDICATION:
2481                         case PH_SIGNAL | INDICATION:
2482                         i = 0;
2483                         while(i < mISDNport->b_num)
2484                         {
2485                                 if ((unsigned int)(mISDNport->b_addr[i]&STACK_ID_MASK) == (frm->addr&STACK_ID_MASK))
2486                                         break;
2487                                 i++;
2488                         }
2489                         if (i == mISDNport->b_num)
2490                         {
2491                                 PERROR("unhandled b-message (prim 0x%x address 0x%x).\n", frm->prim, frm->addr);
2492                                 break;
2493                         }
2494                         if (mISDNport->b_port[i])
2495                         {
2496 //PERROR("port sech: %s data\n", mISDNport->b_port[i]->p_name);
2497                                 mISDNport->b_port[i]->bchannel_receive(frm);
2498                         } else
2499                                 PDEBUG(DEBUG_BCHANNEL, "b-channel is not associated to an ISDNPort (address 0x%x), ignoring.\n", frm->addr);
2500                         break;
2501
2502                         case PH_ACTIVATE | INDICATION:
2503                         case DL_ESTABLISH | INDICATION:
2504                         case PH_ACTIVATE | CONFIRM:
2505                         case DL_ESTABLISH | CONFIRM:
2506                         PDEBUG(DEBUG_BCHANNEL, "DL_ESTABLISH confirm: bchannel is now activated (address 0x%x).\n", frm->addr);
2507                         i = 0;
2508                         while(i < mISDNport->b_num)
2509                         {
2510                                 if ((unsigned int)(mISDNport->b_addr[i]&STACK_ID_MASK) == (frm->addr&STACK_ID_MASK))
2511                                         break;
2512                                 i++;
2513                         }
2514                         if (i == mISDNport->b_num)
2515                         {
2516                                 PERROR("unhandled b-establish (prim 0x%x address 0x%x).\n", frm->prim, frm->addr);
2517                                 break;
2518                         }
2519                         bchannel_event(mISDNport, i, B_EVENT_ACTIVATED);
2520                         break;
2521
2522                         case PH_DEACTIVATE | INDICATION:
2523                         case DL_RELEASE | INDICATION:
2524                         case PH_DEACTIVATE | CONFIRM:
2525                         case DL_RELEASE | CONFIRM:
2526                         PDEBUG(DEBUG_BCHANNEL, "DL_RELEASE confirm: bchannel is now de-activated (address 0x%x).\n", frm->addr);
2527                         i = 0;
2528                         while(i < mISDNport->b_num)
2529                         {
2530                                 if ((unsigned int)(mISDNport->b_addr[i]&STACK_ID_MASK) == (frm->addr&STACK_ID_MASK))
2531                                         break;
2532                                 i++;
2533                         }
2534                         if (i == mISDNport->b_num)
2535                         {
2536                                 PERROR("unhandled b-release (prim 0x%x address 0x%x).\n", frm->prim, frm->addr);
2537                                 break;
2538                         }
2539                         bchannel_event(mISDNport, i, B_EVENT_DEACTIVATED);
2540                         break;
2541
2542                         default:
2543                         PERROR("child message not handled: prim(0x%x) addr(0x%x) msg->len(%d)\n", frm->prim, frm->addr, msg->len);
2544                 }
2545         }
2546
2547         out:
2548         free_msg(msg);
2549         return(1);
2550 }
2551 #endif
2552
2553 #ifdef SOCKET_MISDN
2554 int do_layer3(struct mlayer3 *ml3, unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
2555 {
2556         struct mISDNport *mISDNport = ml3->private;
2557
2558         if (cmd == MT_ASSIGN)
2559         {
2560                 ueberdenken!!!
2561         }
2562         
2563         /* lock LCR */
2564         achtung MT_ASSIGN kommt hier an
2565         lock it baby
2566
2567         /* d-message */
2568         switch(cmd)
2569         {
2570                 case MGR_SHORTSTATUS_IND:
2571                 case MGR_SHORTSTATUS_CONF:
2572                 switch(frm->dinfo) {
2573                         case SSTATUS_L1_ACTIVATED:
2574                         l1l2l3_trace_header(mISDNport, NULL, PH_ACTIVATE_IND, DIRECTION_IN);
2575                         end_trace();
2576                         goto ss_act;
2577                         case SSTATUS_L1_DEACTIVATED:
2578                         l1l2l3_trace_header(mISDNport, NULL, PH_DEACTIVATE_IND, DIRECTION_IN);
2579                         end_trace();
2580                         goto ss_deact;
2581                         case SSTATUS_L2_ESTABLISHED:
2582                         l1l2l3_trace_header(mISDNport, NULL, DL_ESTABLISH_IND, DIRECTION_IN);
2583                         end_trace();
2584                         goto ss_estab;
2585                         case SSTATUS_L2_RELEASED:
2586                         l1l2l3_trace_header(mISDNport, NULL, DL_RELEASE_IND, DIRECTION_IN);
2587                         end_trace();
2588                         goto ss_rel;
2589                 }
2590                 break;
2591
2592                 case PH_ACTIVATE_CONF:
2593                 case PH_ACTIVATE_IND:
2594                 l1l2l3_trace_header(mISDNport, NULL, cmd, DIRECTION_IN);
2595                 end_trace();
2596                 ss_act:
2597                 mISDNport->l1link = 1;
2598 #if 0
2599                 if (mISDNport->ntmode)
2600                         setup_queue(mISDNport, 1);
2601 #endif
2602                 break;
2603
2604                 case PH_DEACTIVATE | CONFIRM:
2605                 case PH_DEACTIVATE | INDICATION:
2606                 l1l2l3_trace_header(mISDNport, NULL, cmd, DIRECTION_IN);
2607                 end_trace();
2608                 ss_deact:
2609                 mISDNport->l1link = 0;
2610 raus mit der setup-queue, da dies im stack geschieht
2611 #if 0
2612                 if (mISDNport->ntmode)
2613                         setup_queue(mISDNport, 0);
2614 #endif
2615                 break;
2616
2617                 case PH_CONTROL_CONFIRM:
2618                 case PH_CONTROL_INDICATION:
2619                 PDEBUG(DEBUG_ISDN, "Received PH_CONTROL for port %d (%s).\n", mISDNport->portnum, mISDNport->ifport->interface->name);
2620                 break;
2621
2622                 case DL_ESTABLISH_IND:
2623                 case DL_ESTABLISH_CONF:
2624                 l1l2l3_trace_header(mISDNport, NULL, cmd, DIRECTION_IN);
2625                 end_trace();
2626                 if (!mISDNport->ntmode) break; /* !!!!!!!!!!!!!!!! */
2627                 ss_estab:
2628                 if (mISDNport->l2establish)
2629                 {
2630                         mISDNport->l2establish = 0;
2631                         PDEBUG(DEBUG_ISDN, "the link became active before l2establish timer expiry.\n");
2632                 }
2633                 mISDNport->l2link = 1;
2634                 break;
2635
2636                 case DL_RELEASE_IND:
2637                 case DL_RELEASE_CONF:
2638                 l1l2l3_trace_header(mISDNport, NULL, cmd, DIRECTION_IN);
2639                 end_trace();
2640                 ss_rel:
2641                 mISDNport->l2link = 0;
2642                 if (mISDNport->ptp)
2643                 {
2644                         time(&mISDNport->l2establish);
2645                         PDEBUG(DEBUG_ISDN, "because we are ptp, we set a l2establish timer.\n");
2646                 }
2647                 break;
2648
2649                 default:
2650                 /* l3-data is sent to LCR */
2651                 message_from_mlayer3(mISDNport, cmd, pid, l3m);
2652         }
2653
2654         /* unlock LCR */
2655         unlock it baby
2656
2657         /* free message */
2658         if (l3m)
2659                 free_l3_msg(l3m);
2660         return(0);
2661
2662 }
2663 #endif
2664
2665
2666 /*
2667  * global function to add a new card (port)
2668  */
2669 struct mISDNport *mISDNport_open(int port, int ptp, int ptmp, int force_nt, struct interface *interface)
2670 {
2671         int ret;
2672         unsigned char buff[1025];
2673         iframe_t *frm = (iframe_t *)buff;
2674         struct mISDNport *mISDNport, **mISDNportp;
2675         int i, cnt;
2676         int pri, bri, ports;
2677         int nt, te;
2678 #ifdef SOCKET_MISDN
2679         struct mlayer3 *ml3;
2680         struct mISDN_devinfo devinfo;
2681
2682         ret = ioctl(mISDNsocket, IMGETCOUNT, &cnt);
2683         if (ret < 0)
2684         {
2685                 fprintf(stderr, "Cannot get number of mISDN devices. (ioctl IMGETCOUNT failed ret=%d)\n", ret);
2686                 return(NULL);
2687         }
2688 #else
2689 //      interface_info_t ii;
2690         net_stack_t *nst;
2691         manager_t *mgr;
2692         layer_info_t li;
2693         stack_info_t *stinf;
2694
2695         /* query port's requirements */
2696         cnt = mISDN_get_stack_count(mISDNdevice);
2697 #endif
2698
2699         if (cnt <= 0)
2700         {
2701                 PERROR_RUNTIME("Found no card. Please be sure to load card drivers.\n");
2702                 return(NULL);
2703         }
2704         if (port>cnt || port<1)
2705         {
2706                 PERROR_RUNTIME("Port (%d) given at 'ports' (options.conf) is out of existing port range (%d-%d)\n", port, 1, cnt);
2707                 return(NULL);
2708         }
2709
2710         pri = bri = ports = nt = te = 0;
2711 #ifdef SOCKET_MISDN
2712         devinfo.id = port - 1;
2713         ret = ioctl(socket, IMGETDEVINFO, &devinfo);
2714         if (ret <= 0)
2715         {
2716                 PERROR_RUNTIME("Cannot get device information for port %d. (ioctl IMGETDEVINFO failed ret=%d)\n", i, ret);
2717                 break;
2718         }
2719         /* output the port info */
2720         if (devinfo.Dprotocols & (1 << ISDN_P_TE_S0))
2721         {
2722                 bri = 1;
2723                 te = 1;
2724         }
2725         if (devinfo.Dprotocols & (1 << ISDN_P_NT_S0))
2726         {
2727                 bri = 1;
2728                 nt = 1;
2729         }
2730 #ifdef ISDN_P_TE_E1
2731         if (devinfo.Dprotocols & (1 << ISDN_P_TE_E1))
2732         {
2733                 pri = 1;
2734                 te = 1;
2735         }
2736 #endif
2737 #ifdef ISDN_P_NT_E1
2738         if (devinfo.Dprotocols & (1 << ISDN_P_NT_E1))
2739         {
2740                 pri = 1;
2741                 nt = 1;
2742         }
2743 #endif
2744 #ifdef ISDN_P_FXS
2745         if (devinfo.Dprotocols & (1 << ISDN_P_FXS))
2746         {
2747                 pots = 1;
2748                 te = 1;
2749         }
2750 #endif
2751 #ifdef ISDN_P_FXO
2752         if (devinfo.Dprotocols & (1 << ISDN_P_FXO))
2753         {
2754                 pots = 1;
2755                 nt = 1;
2756         }
2757 #endif
2758         if (force_nt && !nt)
2759         {
2760                 PERROR_RUNTIME("Port %d does not support NT-mode.\n", port);
2761                 return(NULL);
2762         }
2763         if (bri && pri)
2764         {
2765                 PERROR_RUNTIME("Port %d supports BRI and PRI?? What kind of controller is that?. (Can't use this!)\n", port);
2766                 return(NULL);
2767         }
2768         if (pots && !bri && !pri)
2769         {
2770                 PERROR_RUNTIME("Port %d supports POTS, LCR does not!\n", port);
2771                 return(NULL);
2772         }
2773         if (!bri && !pri)
2774         {
2775                 PERROR_RUNTIME("Port %d does not support BRI nor PRI!\n", port);
2776                 return(NULL);
2777         }
2778         if (!nt && !te)
2779         {
2780                 PERROR_RUNTIME("Port %d does not support NT-mode nor TE-mode!\n", port);
2781                 return(NULL);
2782         }
2783         /* force nt, by turning off TE */
2784         if (force_nt && nt)
2785                 te = 0;
2786         /* if TE an NT is supported (and not forced to NT), turn off NT */
2787         if (te && nt)
2788                 nt = 0;
2789 #else
2790         ret = mISDN_get_stack_info(mISDNdevice, port, buff, sizeof(buff));
2791         if (ret < 0)
2792         {
2793                 PERROR_RUNTIME("Cannot get stack info for port %d (ret=%d)\n", port, ret);
2794                 return(NULL);
2795         }
2796         stinf = (stack_info_t *)&frm->data.p;
2797         switch(stinf->pid.protocol[0] & ~ISDN_PID_FEATURE_MASK)
2798         {
2799                 case ISDN_PID_L0_TE_S0:
2800                 PDEBUG(DEBUG_ISDN, "TE-mode BRI S/T interface line\n");
2801                 break;
2802                 case ISDN_PID_L0_NT_S0:
2803                 PDEBUG(DEBUG_ISDN, "NT-mode BRI S/T interface port\n");
2804                 nt = 1;
2805                 break;
2806                 case ISDN_PID_L0_TE_E1:
2807                 PDEBUG(DEBUG_ISDN, "TE-mode PRI E1  interface line\n");
2808                 pri = 1;
2809                 break;
2810                 case ISDN_PID_L0_NT_E1:
2811                 PDEBUG(DEBUG_ISDN, "LT-mode PRI E1  interface port\n");
2812                 pri = 1;
2813                 nt = 1;
2814                 break;
2815                 default:
2816                 PERROR_RUNTIME("unknown port(%d) type 0x%08x\n", port, stinf->pid.protocol[0]);
2817                 return(NULL);
2818         }
2819         if (nt)
2820         {
2821                 /* NT */
2822                 if (stinf->pid.protocol[1] == 0)
2823                 {
2824                         PERROR_RUNTIME("Given port %d: Missing layer 1 NT-mode protocol.\n", port);
2825                         return(NULL);
2826                 }
2827                 if (stinf->pid.protocol[2])
2828                 {
2829                         PERROR_RUNTIME("Given port %d: Layer 2 protocol 0x%08x is detected, but not allowed for NT lib.\n", port, stinf->pid.protocol[2]);
2830                         return(NULL);
2831                 }
2832         }
2833         if (te)
2834         {
2835                 /* TE */
2836                 if (stinf->pid.protocol[1] == 0)
2837                 {
2838                         PERROR_RUNTIME("Given port %d: Missing layer 1 protocol.\n", port);
2839                         return(NULL);
2840                 }
2841                 if (stinf->pid.protocol[2] == 0)
2842                 {
2843                         PERROR_RUNTIME("Given port %d: Missing layer 2 protocol.\n", port);
2844                         return(NULL);
2845                 }
2846                 if (stinf->pid.protocol[3] == 0)
2847                 {
2848                         PERROR_RUNTIME("Given port %d: Missing layer 3 protocol.\n", port);
2849                         return(NULL);
2850                 } else
2851                 {
2852                         switch(stinf->pid.protocol[3] & ~ISDN_PID_FEATURE_MASK)
2853                         {
2854                                 case ISDN_PID_L3_DSS1USER:
2855                                 break;
2856
2857                                 default:
2858                                 PERROR_RUNTIME("Given port %d: own protocol 0x%08x", port,stinf->pid.protocol[3]);
2859                                 return(NULL);
2860                         }
2861                 }
2862                 if (stinf->pid.protocol[4])
2863                 {
2864                         PERROR_RUNTIME("Given port %d: Layer 4 protocol not allowed.\n", port);
2865                         return(NULL);
2866                 }
2867         }
2868 #endif
2869
2870         /* add mISDNport structure */
2871         mISDNportp = &mISDNport_first;
2872         while(*mISDNportp)
2873                 mISDNportp = &((*mISDNportp)->next);
2874         mISDNport = (struct mISDNport *)MALLOC(sizeof(struct mISDNport));
2875         pmemuse++;
2876         *mISDNportp = mISDNport;
2877
2878         /* allocate ressources of port */
2879 #ifdef SOCKET_MISDN
2880         /* open layer 3 */
2881         protocol = (nt)?L3_PROTOCOL_DSS1_USER:L3_PROTOCOL_DSS1_NETWORK;
2882         prop = 0;
2883         if (ptp)
2884                prop |= FLG_PTP;
2885         if (ptmp && pri)
2886                prop |= FLG_FORCE_PTMP;
2887         mISDNport->ml3 = open_layer3(port-1, protocol, prop , do_dchannel, mISDNport);
2888         if (!mISDNport->ml3)
2889         {
2890                 PERROR_RUNTIME("Cannot get layer(%d) id of port %d\n", nt?2:4, port);
2891                 return(NULL);
2892         }
2893
2894 #if 0
2895         /* if ntmode, establish L1 to send the tei removal during start */
2896         if (mISDNport->ntmode)
2897         {
2898                 iframe_t act;
2899                 /* L1 */
2900                 act.prim = PH_ACTIVATE | REQUEST; 
2901                 act.addr = mISDNport->upper_id | FLG_MSG_DOWN;
2902                 printf("UPPER ID 0x%x, addr 0x%x\n",mISDNport->upper_id, act.addr);
2903                 act.dinfo = 0;
2904                 act.len = 0;
2905                 mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
2906                 usleep(10000); /* to be sure, that l1 is up */
2907         }
2908 #endif
2909
2910         SCPY(mISDNport->name, devinfo.name);
2911         mISDNport->b_num = devinfo.nrbchan;
2912 #else
2913         msg_queue_init(&mISDNport->downqueue);
2914         mISDNport->d_stid = stinf->id;
2915         PDEBUG(DEBUG_ISDN, "d_stid = 0x%x.\n", mISDNport->d_stid);
2916         if ((stinf->pid.protocol[2]&ISDN_PID_L2_DF_PTP) || (nt&&ptp) || pri)
2917         {
2918                 PDEBUG(DEBUG_ISDN, "Port is point-to-point.\n");
2919                 ptp = 1;
2920                 if (ptmp && nt)
2921                 {
2922                         PDEBUG(DEBUG_ISDN, "Port is forced to point-to-multipoint.\n");
2923                         ptp = 0;
2924                 }
2925         }
2926
2927         /* create layer intance */
2928         memset(&li, 0, sizeof(li));
2929         UCPY(&li.name[0], (nt)?"net l2":"pbx l4");
2930         li.object_id = -1;
2931         li.extentions = 0;
2932         li.pid.protocol[nt?2:4] = (nt)?ISDN_PID_L2_LAPD_NET:ISDN_PID_L4_CAPI20;
2933         li.pid.layermask = ISDN_LAYER((nt?2:4));
2934         li.st = mISDNport->d_stid;
2935         ret = mISDN_new_layer(mISDNdevice, &li);
2936         if (ret)
2937         {
2938                 PERROR("Cannot add layer %d of port %d (ret %d)\n", nt?2:4, port, ret);
2939                 closeport:
2940                 mISDNport_close(mISDNport);
2941                 return(NULL);
2942         }
2943         mISDNport->upper_id = li.id;
2944         ret = mISDN_register_layer(mISDNdevice, mISDNport->d_stid, mISDNport->upper_id);
2945         if (ret)
2946         {
2947                 PERROR("Cannot register layer %d of port %d\n", nt?2:4, port);
2948                 goto closeport;
2949         }
2950         mISDNport->lower_id = mISDN_get_layerid(mISDNdevice, mISDNport->d_stid, nt?1:3); // id of lower layer (nt=1, te=3)
2951         if (mISDNport->lower_id < 0)
2952         {
2953                 PERROR("Cannot get layer(%d) id of port %d\n", nt?1:3, port);
2954                 goto closeport;
2955         }
2956         mISDNport->upper_id = mISDN_get_layerid(mISDNdevice, mISDNport->d_stid, nt?2:4); // id of uppermost layer (nt=2, te=4)
2957         if (mISDNport->upper_id < 0)
2958         {
2959                 PERROR("Cannot get layer(%d) id of port %d\n", nt?2:4, port);
2960                 goto closeport;
2961         }
2962         PDEBUG(DEBUG_ISDN, "Layer %d of port %d added.\n", nt?2:4, port);
2963
2964         /* if ntmode, establish L1 to send the tei removal during start */
2965         if (mISDNport->ntmode)
2966         {
2967                 iframe_t act;
2968                 /* L1 */
2969                 act.prim = PH_ACTIVATE | REQUEST; 
2970                 act.addr = mISDNport->upper_id | FLG_MSG_DOWN;
2971                 printf("UPPER ID 0x%x, addr 0x%x\n",mISDNport->upper_id, act.addr);
2972                 act.dinfo = 0;
2973                 act.len = 0;
2974                 mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
2975                 usleep(10000); /* to be sure, that l1 is up */
2976         }
2977
2978         /* create nst (nt-mode only) */
2979         if (nt)
2980         {
2981                 mgr = &mISDNport->mgr;
2982                 nst = &mISDNport->nst;
2983
2984                 mgr->nst = nst;
2985                 nst->manager = mgr;
2986
2987                 nst->l3_manager = stack2manager_nt; /* messages from nt-mode */
2988                 nst->device = mISDNdevice;
2989                 nst->cardnr = port;
2990                 nst->d_stid = mISDNport->d_stid;
2991
2992                 nst->feature = FEATURE_NET_HOLD;
2993                 if (ptp)
2994                         nst->feature |= FEATURE_NET_PTP;
2995                 if (pri)
2996                         nst->feature |= FEATURE_NET_CRLEN2 | FEATURE_NET_EXTCID;
2997 #if 0
2998                 i = 0;
2999                 while(i < mISDNport->b_num)
3000                 {
3001                         nst->b_stid[i] = mISDNport->b_stid[i];
3002                         i++;
3003                 }
3004 #endif
3005                 nst->l1_id = mISDNport->lower_id;
3006                 nst->l2_id = mISDNport->upper_id;
3007
3008                 /* phd */       
3009                 msg_queue_init(&nst->down_queue);
3010
3011                 Isdnl2Init(nst);
3012                 Isdnl3Init(nst);
3013         }
3014
3015         mISDNport->b_num = stinf->childcnt;
3016 #endif
3017         mISDNport->portnum = port;
3018         mISDNport->ntmode = nt;
3019         mISDNport->pri = pri;
3020         mISDNport->ptp = ptp;
3021         PDEBUG(DEBUG_ISDN, "Port has %d b-channels.\n", mISDNport->b_num);
3022         i = 0;
3023         while(i < mISDNport->b_num)
3024         {
3025                 mISDNport->b_state[i] = B_STATE_IDLE;
3026 #ifdef SOCKET_MISDN
3027                 mISDNport->b_socket = -1;
3028 #else
3029                 mISDNport->b_stid[i] = stinf->child[i];
3030                 PDEBUG(DEBUG_ISDN, "b_stid[%d] = 0x%x.\n", i, mISDNport->b_stid[i]);
3031 #endif
3032                 i++;
3033         }
3034
3035         /* if te-mode, query state link */
3036         if (!mISDNport->ntmode)
3037         {
3038                 iframe_t act;
3039                 /* L2 */
3040                 PDEBUG(DEBUG_ISDN, "sending short status request for port %d.\n", port);
3041                 act.prim = MGR_SHORTSTATUS | REQUEST; 
3042                 act.addr = mISDNport->upper_id | MSG_BROADCAST;
3043                 act.dinfo = SSTATUS_BROADCAST_BIT | SSTATUS_ALL;
3044                 act.len = 0;
3045                 mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
3046         }
3047         /* if ptp AND te-mode, pull up the link */
3048         if (mISDNport->ptp && !mISDNport->ntmode)
3049         {
3050                 iframe_t act;
3051                 /* L2 */
3052                 act.prim = DL_ESTABLISH | REQUEST; 
3053                 act.addr = (mISDNport->upper_id & ~LAYER_ID_MASK) | 4 | FLG_MSG_DOWN;
3054                 act.dinfo = 0;
3055                 act.len = 0;
3056                 mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
3057         }
3058         /* if ptp AND nt-mode, pull up the link */
3059         if (mISDNport->ptp && mISDNport->ntmode)
3060         {
3061                 msg_t *dmsg;
3062                 /* L2 */
3063                 dmsg = create_l2msg(DL_ESTABLISH | REQUEST, 0, 0);
3064                 if (mISDNport->nst.manager_l3(&mISDNport->nst, dmsg))
3065                         free_msg(dmsg);
3066         }
3067         /* initially, we assume that the link is down, exept for nt-ptmp */
3068         mISDNport->l2link = (mISDNport->ntmode && !mISDNport->ptp)?1:0;
3069
3070         PDEBUG(DEBUG_BCHANNEL, "using 'mISDN_dsp.o' module\n");
3071
3072         start_trace(mISDNport->portnum,
3073                     interface,
3074                     NULL,
3075                     NULL,
3076                     DIRECTION_NONE,
3077                     CATEGORY_CH,
3078                     0,
3079                     "PORT (open)");
3080         add_trace("channels", NULL, "%d", mISDNport->b_num);
3081         end_trace();
3082         return(mISDNport);
3083 }
3084
3085
3086 /*
3087  * function to free ALL cards (ports)
3088  */
3089 void mISDNport_close_all(void)
3090 {
3091         /* free all ports */
3092         while(mISDNport_first)
3093                 mISDNport_close(mISDNport_first);
3094 }
3095
3096 /*
3097  * free only one port
3098  */
3099 void mISDNport_close(struct mISDNport *mISDNport)
3100 {
3101         struct mISDNport **mISDNportp;
3102         class Port *port;
3103         class PmISDN *isdnport;
3104         net_stack_t *nst;
3105         unsigned char buf[32];
3106         int i;
3107
3108         /* remove all port instance that are linked to this mISDNport */
3109         port = port_first;
3110         while(port)
3111         {
3112                 if ((port->p_type&PORT_CLASS_MASK) == PORT_CLASS_mISDN)
3113                 {
3114                         isdnport = (class PmISDN *)port;
3115                         if (isdnport->p_m_mISDNport)
3116                         {
3117                                 PDEBUG(DEBUG_ISDN, "port %s uses mISDNport %d, destroying it.\n", isdnport->p_name, mISDNport->portnum);
3118                                 delete isdnport;
3119                         }
3120                 }
3121                 port = port->next;
3122         }
3123
3124         /* only if we are already part of interface */
3125         if (mISDNport->ifport)
3126         {
3127                 start_trace(mISDNport->portnum,
3128                             mISDNport->ifport->interface,
3129                             NULL,
3130                             NULL,
3131                             DIRECTION_NONE,
3132                             CATEGORY_CH,
3133                             0,
3134                             "PORT (close)");
3135                 end_trace();
3136         }
3137
3138         /* free bchannels */
3139         i = 0;
3140         while(i < mISDNport->b_num)
3141         {
3142                 if (mISDNport->b_addr[i])
3143                 {
3144                         _bchannel_destroy(mISDNport, i);
3145                         PDEBUG(DEBUG_BCHANNEL, "freeing %s port %d bchannel (index %d).\n", (mISDNport->ntmode)?"NT":"TE", mISDNport->portnum, i);
3146                 }
3147                 i++;
3148         }
3149
3150 #ifdef SOCKET_MISDN
3151         close_layer3(mISDNport->ml3);
3152 #else
3153         /* free ressources of port */
3154         msg_queue_purge(&mISDNport->downqueue);
3155
3156         /* free stacks */
3157         if (mISDNport->ntmode)
3158         {
3159                 nst = &mISDNport->nst;
3160                 if (nst->manager) /* to see if initialized */
3161                 {
3162                         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");
3163                         cleanup_Isdnl3(nst);
3164                         cleanup_Isdnl2(nst);
3165
3166                         /* phd */
3167                         msg_queue_purge(&nst->down_queue);
3168                         if (nst->phd_down_msg)
3169                                 FREE(nst->phd_down_msg, 0);
3170                 }
3171         }
3172
3173         PDEBUG(DEBUG_BCHANNEL, "freeing d-stack.\n");
3174         if (mISDNport->d_stid)
3175         {
3176                 if (mISDNport->upper_id)
3177                         mISDN_write_frame(mISDNdevice, buf, mISDNport->upper_id | FLG_MSG_DOWN, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
3178         }
3179 #endif
3180
3181         /* remove from list */
3182         mISDNportp = &mISDNport_first;
3183         while(*mISDNportp)
3184         {
3185                 if (*mISDNportp == mISDNport)
3186                 {
3187                         *mISDNportp = (*mISDNportp)->next;
3188                         mISDNportp = NULL;
3189                         break;
3190                 }
3191                 mISDNportp = &((*mISDNportp)->next);
3192         }
3193
3194         if (mISDNportp)
3195                 FATAL("mISDNport not in list\n");
3196         
3197         FREE(mISDNport, sizeof(struct mISDNport));
3198         pmemuse--;
3199
3200 }
3201
3202
3203 /*
3204  * global function to show all available isdn ports
3205  */
3206 void mISDN_port_info(void)
3207 {
3208         int ret;
3209         int i, ii, p;
3210         int useable, nt, te, pri, bri, pots;
3211         unsigned char buff[1025];
3212         iframe_t *frm = (iframe_t *)buff;
3213 #ifdef SOCKET_MISDN
3214         struct mISDN_devinfo devinfo;
3215         int socket;
3216
3217         /* open mISDN */
3218         socket = socket(PF_ISDN, SOCK_RAW, ISDN_P_BASE);
3219         if (socket < 0)
3220         {
3221                 fprintf(stderr, "Cannot open mISDN due to %s. (Does your Kernel support socket based mISDN?)\n", strerror(errno));
3222                 exit(EXIT_FAILURE);
3223         }
3224
3225         /* get number of stacks */
3226         i = 1;
3227         ret = ioctl(socket, IMGETCOUNT, &ii);
3228         if (ret < 0)
3229         {
3230                 fprintf(stderr, "Cannot get number of mISDN devices. (ioctl IMGETCOUNT failed ret=%d)\n", ret);
3231                 goto done;
3232         }
3233 #else
3234         stack_info_t *stinf;
3235         int device;
3236
3237         /* open mISDN */
3238         if ((device = mISDN_open()) < 0)
3239         {
3240                 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));
3241                 exit(EXIT_FAILURE);
3242         }
3243
3244         /* get number of stacks */
3245         i = 1;
3246         ii = mISDN_get_stack_count(device);
3247 #endif
3248         printf("\n");
3249         if (ii <= 0)
3250         {
3251                 printf("Found no card. Please be sure to load card drivers.\n");
3252                 goto done;
3253         }
3254
3255         /* loop the number of cards and get their info */
3256         while(i <= ii)
3257         {
3258                 nt = te = bri = pri = pots = 0;
3259                 useable = 0;
3260
3261 #ifdef SOCKET_MISDN
3262                 devinfo.id = i - 1;
3263                 ret = ioctl(socket, IMGETDEVINFO, &devinfo);
3264                 if (ret <= 0)
3265                 {
3266                         fprintf(stderr, "Cannot get device information for port %d. (ioctl IMGETDEVINFO failed ret=%d)\n", i, ret);
3267                         break;
3268                 }
3269
3270                 /* output the port info */
3271                 printf("Port %2d name='%s': ", i, devinfo.name);
3272                 if (devinfo.Dprotocols & (1 << ISDN_P_TE_S0))
3273                 {
3274                         bri = 1;
3275                         te = 1;
3276                 }
3277                 if (devinfo.Dprotocols & (1 << ISDN_P_NT_S0))
3278                 {
3279                         bri = 1;
3280                         nt = 1;
3281                 }
3282 #ifdef ISDN_P_TE_E1
3283                 if (devinfo.Dprotocols & (1 << ISDN_P_TE_E1))
3284                 {
3285                         pri = 1;
3286                         te = 1;
3287                 }
3288 #endif
3289 #ifdef ISDN_P_NT_E1
3290                 if (devinfo.Dprotocols & (1 << ISDN_P_NT_E1))
3291                 {
3292                         pri = 1;
3293                         nt = 1;
3294                 }
3295 #endif
3296 #ifdef ISDN_P_FXS
3297                 if (devinfo.Dprotocols & (1 << ISDN_P_FXS))
3298                 {
3299                         pots = 1;
3300                         te = 1;
3301                 }
3302 #endif
3303 #ifdef ISDN_P_FXO
3304                 if (devinfo.Dprotocols & (1 << ISDN_P_FXO))
3305                 {
3306                         pots = 1;
3307                         nt = 1;
3308                 }
3309 #endif
3310                 if ((te || nt) && (bri || pri || ports))
3311                         usable = 1;
3312
3313                 if (te && bri)
3314                         printf("TE-mode BRI S/T interface line (for phone lines)");
3315                 if (nt && bri)
3316                         printf("NT-mode BRI S/T interface port (for phones)");
3317                 if (te && pri)
3318                         printf("TE-mode PRI E1  interface line (for phone lines)");
3319                 if (nt && pri)
3320                         printf("NT-mode PRI E1  interface port (for E1 terminals)");
3321                 if (te && pots)
3322                         printf("FXS     POTS    interface port (for analog lines)");
3323                 if (nt && pots)
3324                         printf("FXO     POTS    interface port (for analog phones)");
3325                 if (ports)
3326                 {
3327                         usable = 0;
3328                         printf("\n -> Analog interfaces are not supported.");
3329                 } else
3330                 if (!usable)
3331                 {
3332                         printf("unsupported interface protocol bits 0x%016x", devinfo.Dprotocols);
3333                 }
3334                 printf("\n");
3335
3336                 printf("  - %d B-channels\n", devinfo.nfbchan);
3337 #else
3338                 ret = mISDN_get_stack_info(device, i, buff, sizeof(buff));
3339                 if (ret <= 0)
3340                 {
3341                         fprintf(stderr, "mISDN_get_stack_info() failed: port=%d error=%d\n", i, ret);
3342                         break;
3343                 }
3344                 stinf = (stack_info_t *)&frm->data.p;
3345
3346                 /* output the port info */
3347                 printf("Port %2d: ", i);
3348                 switch(stinf->pid.protocol[0] & ~ISDN_PID_FEATURE_MASK)
3349                 {
3350                         case ISDN_PID_L0_TE_S0:
3351                         useable = 1;
3352                         te = 1;
3353                         bri = 1;
3354                         printf("TE-mode BRI S/T interface line (for phone lines)");
3355                         break;
3356                         case ISDN_PID_L0_NT_S0:
3357                         useable = 1;
3358                         nt = 1;
3359                         bri = 1;
3360                         printf("NT-mode BRI S/T interface port (for phones)");
3361                         break;
3362                         case ISDN_PID_L0_TE_E1:
3363                         useable = 1;
3364                         te = 1;
3365                         pri = 1;
3366                         printf("TE-mode PRI E1  interface line (for phone lines)");
3367                         break;
3368                         case ISDN_PID_L0_NT_E1:
3369                         useable = 1;
3370                         nt = 1;
3371                         pri = 1;
3372                         printf("NT-mode PRI E1  interface port (for E1 terminals)");
3373                         break;
3374                         default:
3375                         useable = 0;
3376                         printf("unknown type 0x%08x",stinf->pid.protocol[0]);
3377                 }
3378                 printf("\n");
3379
3380                 if (nt)
3381                 {
3382                         if (stinf->pid.protocol[1] == 0)
3383                         {
3384                                 useable = 0;
3385                                 printf(" -> Missing layer 1 NT-mode protocol.\n");
3386                         }
3387                         p = 2;
3388                         while(p <= MAX_LAYER_NR) {
3389                                 if (stinf->pid.protocol[p])
3390                                 {
3391                                         useable = 0;
3392                                         printf(" -> Layer %d protocol 0x%08x is detected, port already in use by another application.\n", p, stinf->pid.protocol[p]);
3393                                 }
3394                                 p++;
3395                         }
3396                         if (useable)
3397                         {
3398                                 if (pri)
3399                                         printf(" -> Interface is Point-To-Point (PRI).\n");
3400                                 else
3401                                         printf(" -> Interface can be Poin-To-Point/Multipoint.\n");
3402                         }
3403                 }
3404                 if (te)
3405                 {
3406                         if (stinf->pid.protocol[1] == 0)
3407                         {
3408                                 useable = 0;
3409                                 printf(" -> Missing layer 1 protocol.\n");
3410                         }
3411                         if (stinf->pid.protocol[2] == 0)
3412                         {
3413                                 useable = 0;
3414                                 printf(" -> Missing layer 2 protocol.\n");
3415                         }
3416                         if (stinf->pid.protocol[2] & ISDN_PID_L2_DF_PTP)
3417                         {
3418                                 printf(" -> Interface is Poin-To-Point.\n");
3419                         }
3420                         if (stinf->pid.protocol[3] == 0)
3421                         {
3422                                 useable = 0;
3423                                 printf(" -> Missing layer 3 protocol.\n");
3424                         } else
3425                         {
3426                                 printf(" -> Protocol: ");
3427                                 switch(stinf->pid.protocol[3] & ~ISDN_PID_FEATURE_MASK)
3428                                 {
3429                                         case ISDN_PID_L3_DSS1USER:
3430                                         printf("DSS1 (Euro ISDN)");
3431                                         break;
3432
3433                                         default:
3434                                         useable = 0;
3435                                         printf("unknown protocol 0x%08x",stinf->pid.protocol[3]);
3436                                 }
3437                                 printf("\n");
3438                         }
3439                         p = 4;
3440                         while(p <= MAX_LAYER_NR) {
3441                                 if (stinf->pid.protocol[p])
3442                                 {
3443                                         useable = 0;
3444                                         printf(" -> Layer %d protocol 0x%08x is detected, port already in use by another application.\n", p, stinf->pid.protocol[p]);
3445                                 }
3446                                 p++;
3447                         }
3448                 }
3449                 printf("  - %d B-channels\n", stinf->childcnt);
3450 #endif
3451
3452                 if (!useable)
3453                         printf(" * Port NOT useable for LCR\n");
3454
3455                 printf("--------\n");
3456
3457                 i++;
3458         }
3459         printf("\n");
3460
3461 done:
3462 #ifdef SOCKET_MISDN
3463         close(sd);
3464 #else
3465         /* close mISDN */
3466         if ((ret = mISDN_close(device)))
3467                 FATAL("mISDN_close() failed: err=%d '%s'\n", ret, strerror(ret));
3468 #endif
3469 }
3470
3471
3472 /*
3473  * enque data from upper buffer
3474  */
3475 void PmISDN::txfromup(unsigned char *data, int length)
3476 {
3477 #ifdef SOCKET_MISDN
3478         unsigned char buf[MISDN_HEADER_LEN+((length>ISDN_LOAD)?length:ISDN_LOAD)];
3479         struct mISDNhead *frm = (struct mISDNhead *)buf;
3480
3481         if (p_m_b_index < 0)
3482                 return;
3483         if (!p_m_mISDNport->b_socket[p_m_b_index])
3484                 return;
3485 #else
3486         unsigned char buf[mISDN_HEADER_LEN+((length>ISDN_LOAD)?length:ISDN_LOAD)];
3487         iframe_t *frm = (iframe_t *)buf;
3488
3489         if (p_m_b_index < 0)
3490                 return;
3491         if (!p_m_mISDNport->b_addr[p_m_b_index])
3492                 return;
3493 #endif
3494
3495         /* check if high priority tones exist
3496          * ignore data in this case
3497          */
3498         if (p_tone_name[0] || p_m_crypt_msg_loops)
3499                 return;
3500
3501         /* preload procedure
3502          * if transmit buffer in DSP module is empty,
3503          * preload it to DSP_LOAD to prevent jitter gaps.
3504          */
3505         if (p_m_load==0 && ISDN_LOAD>0)
3506         {
3507
3508                 memcpy(buf+mISDN_HEADER_LEN, data, ISDN_LOAD);
3509                 frm->len = ISDN_LOAD;
3510                 mISDN_write(mISDNdevice, frm, mISDN_HEADER_LEN+frm->len, TIMEOUT_1SEC);
3511                 p_m_load += frm->len;
3512         }
3513
3514         /* drop if load would exceed ISDN_MAXLOAD
3515          * this keeps the delay not too high
3516          */
3517         if (p_m_load+length > ISDN_MAXLOAD)
3518                 return;
3519
3520         /* make and send frame */
3521 #ifdef SOCKET_MISDN
3522         frm->prim = DL_DATA_REQ;
3523         frm->id = 0;
3524         memcpy(buf+MISDN_HEADER_LEN, data, length);
3525         ret = sendto(p_m_mISDNport->b_socket[p_m_b_index], buf, MISDN_HEADER_LEN+length, 0, NULL, 0);
3526         if (!ret)
3527                 PERROR("Failed to send to socket %d\n", handle);
3528 #else
3529         frm->prim = DL_DATA | REQUEST; 
3530         frm->addr = p_m_mISDNport->b_addr[p_m_b_index] | FLG_MSG_DOWN;
3531         frm->dinfo = 0;
3532         frm->len = length;
3533         memcpy(buf+mISDN_HEADER_LEN, data, length);
3534         mISDN_write(mISDNdevice, frm, mISDN_HEADER_LEN+frm->len, TIMEOUT_1SEC);
3535 #endif
3536         p_m_load += length;
3537 }
3538