4b4e3fcf3085f2d21ca94870376976a1a3261dcb
[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         if (p_m_b_index < 0)
1177                 return;
1178
1179         /* unreserve channel */
1180         if (p_m_b_reserve)
1181                 p_m_mISDNport->b_reserved--;
1182         p_m_b_reserve = 0;
1183
1184         /* if not in use */
1185         if (!p_m_b_channel)
1186                 return;
1187
1188         PDEBUG(DEBUG_BCHANNEL, "PmISDN(%s) dropping bchannel\n", p_name);
1189
1190         if (p_m_mISDNport->b_state[p_m_b_index] != B_STATE_IDLE)
1191                 bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_DROP);
1192         p_m_mISDNport->b_port[p_m_b_index] = NULL;
1193         p_m_b_index = -1;
1194         p_m_b_channel = 0;
1195         p_m_b_exclusive = 0;
1196 }
1197
1198 /* process bchannel export/import message from join */
1199 void message_bchannel_from_join(class JoinRemote *joinremote, int type, unsigned long handle)
1200 {
1201         class Endpoint *epoint;
1202         class Port *port;
1203         class PmISDN *isdnport;
1204         struct mISDNport *mISDNport;
1205         int i, ii;
1206
1207         switch(type)
1208         {
1209                 case BCHANNEL_REQUEST:
1210                 /* find the port object for the join object ref */
1211                 if (!(epoint = find_epoint_id(joinremote->j_epoint_id)))
1212                 {
1213                         PDEBUG(DEBUG_BCHANNEL, "join %d has no endpoint (anymore)\n", joinremote->j_serial);
1214                         return;
1215                 }
1216                 if (!epoint->ep_portlist)
1217                 {
1218                         PDEBUG(DEBUG_BCHANNEL, "join %d has no port (anymore in portlist)\n", joinremote->j_serial);
1219                         return;
1220                 }
1221                 if (epoint->ep_portlist->next)
1222                 {
1223                         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);
1224                 }
1225                 if (!(port = find_port_id(epoint->ep_portlist->port_id)))
1226                 {
1227                         PDEBUG(DEBUG_BCHANNEL, "join %d has no port (anymore as object)\n", joinremote->j_serial);
1228                         return;
1229                 }
1230                 if (!((port->p_type&PORT_CLASS_MASK) != PORT_CLASS_mISDN))
1231                 {
1232                         PERROR("join %d has port %d not of mISDN type. This shall not happen.\n", joinremote->j_serial, port->p_serial);
1233                 }
1234                 isdnport = (class PmISDN *)port;
1235
1236                 /* assign */
1237                 if (isdnport->p_m_remote_id)
1238                 {
1239                         PERROR("join %d recevied bchannel request from remote, but channel is already assinged.\n", joinremote->j_serial);
1240                         break;
1241                 }
1242                 mISDNport = isdnport->p_m_mISDNport;
1243                 i = isdnport->p_m_b_index;
1244                 chan_trace_header(mISDNport, isdnport, "MESSAGE_BCHANNEL (from remote application)", DIRECTION_NONE);
1245                 add_trace("type", NULL, "export request");
1246                 isdnport->p_m_remote_ref = joinremote->j_serial;
1247                 isdnport->p_m_remote_id = joinremote->j_remote_id;
1248                 if (mISDNport && i>=0)
1249                 {
1250                         bchannel_event(mISDNport, i, B_EVENT_EXPORTREQUEST);
1251                 }
1252                 end_trace();
1253                 break;
1254
1255                 case BCHANNEL_ASSIGN_ACK:
1256                 case BCHANNEL_REMOVE_ACK:
1257                 /* find mISDNport for stack ID */
1258                 mISDNport = mISDNport_first;
1259                 while(mISDNport)
1260                 {
1261                         i = 0;
1262                         ii = mISDNport->b_num;
1263                         while(i < ii)
1264                         {
1265 #ifdef SOCKET_MISDN
1266                                 if (mISDNport->b_socket[i] == handle)
1267 #else
1268                                 if ((unsigned long)(mISDNport->portnum<<8)+i+1+(i>=15) == handle)
1269 #endif
1270                                         break;
1271                                 i++;
1272                         }
1273                         if (i != ii)
1274                                 break;
1275                         mISDNport = mISDNport->next;
1276                 }
1277                 if (!mISDNport)
1278                 {
1279                         PERROR("received assign/remove ack for handle=%x, but handle does not exist in any mISDNport structure.\n", handle);
1280                         break;
1281                 }
1282                 /* mISDNport may now be set or NULL */
1283                 
1284                 /* set */
1285                 chan_trace_header(mISDNport, mISDNport->b_port[i], "MESSAGE_BCHANNEL (from remote application)", DIRECTION_NONE);
1286                 add_trace("type", NULL, (type==BCHANNEL_ASSIGN_ACK)?"assign_ack":"remove_ack");
1287                 if (mISDNport && i>=0)
1288                         bchannel_event(mISDNport, i, (type==BCHANNEL_ASSIGN_ACK)?B_EVENT_EXPORTED:B_EVENT_IMPORTED);
1289                 end_trace();
1290                 break;
1291                 default:
1292                 PERROR("received wrong bchannel message type %d from remote\n", type);
1293         }
1294 }
1295
1296
1297 /*
1298  * handler
1299
1300 audio transmission procedure:
1301 -----------------------------
1302
1303 * priority
1304 three sources of audio transmission:
1305 - crypto-data high priority
1306 - tones high priority (also high)
1307 - remote-data low priority
1308
1309 * elapsed
1310 a variable that temporarily shows the number of samples elapsed since last transmission process.
1311 p_m_last_tv_* is used to store that last timestamp. this is used to calculate the time elapsed.
1312
1313 * load
1314 a variable that is increased whenever data is transmitted.
1315 it is decreased while time elapses. it stores the number of samples that
1316 are currently loaded to dsp module.
1317 since clock in dsp module is the same clock for user space process, these 
1318 times have no skew.
1319
1320 * levels
1321 there are two levels:
1322 ISDN_LOAD will give the load that have to be kept in dsp.
1323 ISDN_MAXLOAD will give the maximum load before dropping.
1324
1325 * procedure for low priority data
1326 see txfromup() for procedure
1327 in short: remote data is ignored during high priority tones
1328
1329 * procedure for high priority data
1330 whenever load is below ISDN_LOAD, load is filled up to ISDN_LOAD
1331 if no more data is available, load becomes empty again.
1332
1333 'load' variable:
1334 0                    ISDN_LOAD           ISDN_MAXLOAD
1335 +--------------------+----------------------+
1336 |                    |                      |
1337 +--------------------+----------------------+
1338
1339 on empty load or on load below ISDN_LOAD, the load is inceased to ISDN_LOAD:
1340 0                    ISDN_LOAD           ISDN_MAXLOAD
1341 +--------------------+----------------------+
1342 |TTTTTTTTTTTTTTTTTTTT|                      |
1343 +--------------------+----------------------+
1344
1345 on empty load, remote-audio causes the load with the remote audio to be increased to ISDN_LOAD.
1346 0                    ISDN_LOAD           ISDN_MAXLOAD
1347 +--------------------+----------------------+
1348 |TTTTTTTTTTTTTTTTTTTTRRRRR                  |
1349 +--------------------+----------------------+
1350
1351  */
1352 int PmISDN::handler(void)
1353 {
1354         struct message *message;
1355         int elapsed = 0;
1356         int ret;
1357
1358         if ((ret = Port::handler()))
1359                 return(ret);
1360
1361         /* get elapsed */
1362         if (p_m_last_tv_sec)
1363         {
1364                 elapsed = 8000 * (now_tv.tv_sec - p_m_last_tv_sec)
1365                         + 8 * (now_tv.tv_usec/1000 - p_m_last_tv_msec);
1366         } else
1367         {
1368                 /* set clock of first process ever in this instance */
1369                 p_m_last_tv_sec = now_tv.tv_sec;
1370                 p_m_last_tv_msec = now_tv.tv_usec/1000;
1371         }
1372         /* process only if we have a minimum of samples, to make packets not too small */
1373         if (elapsed >= ISDN_TRANSMIT)
1374         {
1375                 /* set clock of last process! */
1376                 p_m_last_tv_sec = now_tv.tv_sec;
1377                 p_m_last_tv_msec = now_tv.tv_usec/1000;
1378
1379                 /* update load */
1380                 if (elapsed < p_m_load)
1381                         p_m_load -= elapsed;
1382                 else
1383                         p_m_load = 0;
1384
1385                 /* to send data, tone must be active OR crypt messages must be on */
1386                 if ((p_tone_name[0] || p_m_crypt_msg_loops) && p_m_load < ISDN_LOAD)
1387                 {
1388                         int tosend = ISDN_LOAD - p_m_load, length; 
1389 #ifdef SOCKET_MISDN
1390                         unsigned char buf[MISDN_HEADER_LEN+tosend];
1391                         struct mISDNhead *frm = (struct mISDNhead *)buf;
1392                         unsigned long *d = buf+MISDN_HEADER_LEN;
1393 #else
1394                         unsigned char buf[mISDN_HEADER_LEN+tosend];
1395                         iframe_t *frm = (iframe_t *)buf;
1396                         unsigned char *p = buf+mISDN_HEADER_LEN;
1397 #endif
1398
1399                         /* copy crypto loops */
1400                         while (p_m_crypt_msg_loops && tosend)
1401                         {
1402                                 /* how much do we have to send */
1403                                 length = p_m_crypt_msg_len - p_m_crypt_msg_current;
1404
1405                                 /* clip tosend */
1406                                 if (length > tosend)
1407                                         length = tosend;
1408
1409                                 /* copy message (part) to buffer */
1410                                 memcpy(p, p_m_crypt_msg+p_m_crypt_msg_current, length);
1411
1412                                 /* new position */
1413                                 p_m_crypt_msg_current += length;
1414                                 if (p_m_crypt_msg_current == p_m_crypt_msg_len)
1415                                 {
1416                                         /* next loop */
1417                                         p_m_crypt_msg_current = 0;
1418                                         p_m_crypt_msg_loops--;
1419                                 }
1420
1421                                 /* new length */
1422                                 tosend -= length;
1423                         }
1424
1425                         /* copy tones */
1426                         if (p_tone_name[0] && tosend)
1427                         {
1428                                 tosend -= read_audio(p, tosend);
1429                         }
1430
1431                         /* send data */
1432 #ifdef SOCKET_MISDN
1433                         frm->prim = DL_DATA_REQ;
1434                         frm->id = 0;
1435                         ret = sendto(handle, buffer, MISDN_HEADER_LEN+ISDN_LOAD-p_m_load-tosend, 0, NULL, 0);
1436                         if (!ret)
1437                                 PERROR("Failed to send to socket %d\n", handle);
1438 #else
1439                         frm->prim = DL_DATA | REQUEST; 
1440                         frm->addr = p_m_mISDNport->b_addr[p_m_b_index] | FLG_MSG_DOWN;
1441                         frm->dinfo = 0;
1442                         frm->len = ISDN_LOAD - p_m_load - tosend;
1443 #endif
1444                         if (frm->len)
1445                                 mISDN_write(mISDNdevice, frm, mISDN_HEADER_LEN+frm->len, TIMEOUT_1SEC);
1446                         p_m_load += frm->len;
1447                 }
1448         }
1449
1450         // NOTE: deletion is done by the child class
1451
1452         /* handle timeouts */
1453         if (p_m_timeout)
1454         {
1455                 if (p_m_timer+p_m_timeout < now_d)
1456                 {
1457                         PDEBUG(DEBUG_ISDN, "(%s) timeout after %d seconds detected (state=%d).\n", p_name, p_m_timeout, p_state);
1458                         p_m_timeout = 0;
1459                         /* send timeout to endpoint */
1460                         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_TIMEOUT);
1461                         message->param.state = p_state;
1462                         message_put(message);
1463                         return(1);
1464                 }
1465         }
1466         
1467         return(0); /* nothing done */
1468 }
1469
1470
1471 /*
1472  * whenever we get audio data from bchannel, we process it here
1473  */
1474 #ifdef SOCKET_MISDN
1475 void PmISDN::bchannel_receive(mISDNhead *hh, unsigned char *data, int len)
1476 {
1477         unsigned long cont = *((unsigned long *)data);
1478 #else
1479 void PmISDN::bchannel_receive(iframe_t *frm)
1480 {
1481         int len = frm->len;
1482         unsigned long cont = *((unsigned long *)&frm->data.p);
1483         unsigned char *data =(unsigned char *)&frm->data.p;
1484 #endif
1485         unsigned char *data_temp;
1486         unsigned long length_temp;
1487         struct message *message;
1488         unsigned char *p;
1489         int l;
1490
1491 #ifdef SOCKET_MISDN
1492         if (hh->prim == PH_CONTROL_IND)
1493 #else
1494         if (frm->prim == (PH_CONTROL | INDICATION))
1495 #endif
1496         {
1497                 if (len < 4)
1498                 {
1499                         PERROR("SHORT READ OF PH_CONTROL INDICATION\n");
1500                         return;
1501                 }
1502                 if ((cont&(~DTMF_TONE_MASK)) == DTMF_TONE_VAL)
1503                 {
1504                         chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
1505                         add_trace("DTMF", NULL, "%c", cont & DTMF_TONE_MASK);
1506                         end_trace();
1507                         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_DTMF);
1508                         message->param.dtmf = cont & DTMF_TONE_MASK;
1509                         PDEBUG(DEBUG_PORT, "PmISDN(%s) PH_CONTROL INDICATION  DTMF digit '%c'\n", p_name, message->param.dtmf);
1510                         message_put(message);
1511                         return;
1512                 }
1513                 switch(cont)
1514                 {
1515                         case BF_REJECT:
1516                         chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
1517                         add_trace("DSP-CRYPT", NULL, "error");
1518                         end_trace();
1519                         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CRYPT);
1520                         message->param.crypt.type = CC_ERROR_IND;
1521                         PDEBUG(DEBUG_PORT, "PmISDN(%s) PH_CONTROL INDICATION  reject of blowfish.\n", p_name);
1522                         message_put(message);
1523                         break;
1524
1525                         case BF_ACCEPT:
1526                         chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
1527                         add_trace("DSP-CRYPT", NULL, "ok");
1528                         end_trace();
1529                         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CRYPT);
1530                         message->param.crypt.type = CC_ACTBF_CONF;
1531                         PDEBUG(DEBUG_PORT, "PmISDN(%s) PH_CONTROL INDICATION  accept of blowfish.\n", p_name);
1532                         message_put(message);
1533                         break;
1534
1535                         case CMX_TX_DATA:
1536                         if (!p_m_txdata)
1537                         {
1538                                 /* if tx is off, it may happen that fifos send us pending informations, we just ignore them */
1539                                 PDEBUG(DEBUG_BCHANNEL, "PmISDN(%s) ignoring tx data, because 'txdata' is turned off\n", p_name);
1540                                 return;
1541                         }
1542                         if (p_record)
1543                                 record((unsigned char *)(cont+1), len - 4, 1); // from up
1544                         break;
1545
1546                         default:
1547                         chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
1548                         add_trace("unknown", NULL, "0x%x", cont);
1549                         end_trace();
1550                 }
1551                 return;
1552         }
1553 #ifdef SOCKET_MISDN
1554         if (hh->prim != PH_DATA_IND && hh->prim != DL_DATA_IND)
1555         {
1556                 PERROR("Bchannel received unknown primitve: 0x%x\n", hh->prim);
1557 #else
1558         if (frm->prim != (PH_DATA | INDICATION) && frm->prim != (DL_DATA | INDICATION))
1559         {
1560                 PERROR("Bchannel received unknown primitve: 0x%x\n", frm->prim);
1561 #endif
1562                 return;
1563         }
1564
1565         /* calls will not process any audio data unless
1566          * the call is connected OR interface features audio during call setup.
1567          */
1568 //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);     
1569 #ifndef DEBUG_COREBRIDGE
1570         if (p_state!=PORT_STATE_CONNECT
1571          && !p_m_mISDNport->earlyb)
1572                 return;
1573 #endif
1574
1575         /* if rx is off, it may happen that fifos send us pending informations, we just ignore them */
1576         if (p_m_rxoff)
1577         {
1578                 PDEBUG(DEBUG_BCHANNEL, "PmISDN(%s) ignoring data, because rx is turned off\n", p_name);
1579                 return;
1580         }
1581
1582         /* record data */
1583         if (p_record)
1584                 record(data, len, 0); // from down
1585
1586         /* randomize and listen to crypt message if enabled */
1587         if (p_m_crypt_listen)
1588         {
1589                 /* the noisy randomizer */
1590                 p = data;
1591                 l = len;
1592                 while(l--)
1593                         mISDN_rand[mISDN_rand_count & 0xff] += *p++;
1594
1595                 cryptman_listen_bch(data, len);
1596         }
1597
1598         p = data;
1599
1600         /* send data to epoint */
1601         if (p_m_joindata && ACTIVE_EPOINT(p_epointlist)) /* only if we have an epoint object */
1602         {
1603                 length_temp = len;
1604                 data_temp = p;
1605                 while(length_temp)
1606                 {
1607                         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_DATA);
1608                         message->param.data.len = (length_temp>sizeof(message->param.data.data))?sizeof(message->param.data.data):length_temp;
1609                         memcpy(message->param.data.data, data_temp, message->param.data.len);
1610                         message_put(message);
1611                         if (length_temp <= sizeof(message->param.data.data))
1612                                 break;
1613                         data_temp += sizeof(message->param.data.data);
1614                         length_temp -= sizeof(message->param.data.data);
1615                 }
1616         }
1617 }
1618
1619
1620 /*
1621  * set echotest
1622  */
1623 void PmISDN::set_echotest(int echo)
1624 {
1625         if (p_m_echo != echo)
1626         {
1627                 p_m_echo = echo;
1628                 PDEBUG(DEBUG_ISDN, "we set echo to echo=%d.\n", p_m_echo);
1629                 if (p_m_b_channel)
1630                         if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1631 #ifdef SOCKET_MISDN
1632                                 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);
1633 #else
1634                                 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);
1635 #endif
1636         }
1637 }
1638
1639 /*
1640  * set tone
1641  */
1642 void PmISDN::set_tone(char *dir, char *tone)
1643 {
1644         int id;
1645
1646         if (!tone)
1647                 tone = "";
1648         PDEBUG(DEBUG_ISDN, "isdn port now plays tone:'%s'.\n", tone);
1649         if (!tone[0])
1650         {
1651                 id = TONE_OFF;
1652                 goto setdsp;
1653         }
1654
1655         /* check if we NOT really have to use a dsp-tone */
1656         if (!options.dsptones)
1657         {
1658                 nodsp:
1659                 if (p_m_tone)
1660                 if (p_m_b_index >= 0)
1661                 if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1662                 {
1663                         PDEBUG(DEBUG_ISDN, "we reset tone from id=%d to OFF.\n", p_m_tone);
1664 #ifdef SOCKET_MISDN
1665                         ph_control(p_m_mISDNport, this, p_m_mISDNport->b_socket[p_m_b_index], TONE_PATT_OFF, 0, "DSP-TONE", 0);
1666 #else
1667                         ph_control(p_m_mISDNport, this, p_m_mISDNport->b_addr[p_m_b_index], TONE_PATT_OFF, 0, "DSP-TONE", 0);
1668 #endif
1669                 }
1670                 p_m_tone = 0;
1671                 Port::set_tone(dir, tone);
1672                 return;
1673         }
1674         if (p_tone_dir[0])
1675                 goto nodsp;
1676
1677         /* now we USE dsp-tone, convert name */
1678         else if (!strcmp(tone, "dialtone"))
1679         {
1680                 switch(options.dsptones) {
1681                 case DSP_AMERICAN: id = TONE_AMERICAN_DIALTONE; break;
1682                 case DSP_GERMAN: id = TONE_GERMAN_DIALTONE; break;
1683                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDDIALTONE; break;
1684                 }
1685         } else if (!strcmp(tone, "dialpbx"))
1686         {
1687                 switch(options.dsptones) {
1688                 case DSP_AMERICAN: id = TONE_AMERICAN_DIALPBX; break;
1689                 case DSP_GERMAN: id = TONE_GERMAN_DIALPBX; break;
1690                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDDIALPBX; break;
1691                 }
1692         } else if (!strcmp(tone, "ringing"))
1693         {
1694                 switch(options.dsptones) {
1695                 case DSP_AMERICAN: id = TONE_AMERICAN_RINGING; break;
1696                 case DSP_GERMAN: id = TONE_GERMAN_RINGING; break;
1697                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDRINGING; break;
1698                 }
1699         } else if (!strcmp(tone, "ringpbx"))
1700         {
1701                 switch(options.dsptones) {
1702                 case DSP_AMERICAN: id = TONE_AMERICAN_RINGPBX; break;
1703                 case DSP_GERMAN: id = TONE_GERMAN_RINGPBX; break;
1704                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDRINGPBX; break;
1705                 }
1706         } else if (!strcmp(tone, "busy"))
1707         {
1708                 busy:
1709                 switch(options.dsptones) {
1710                 case DSP_AMERICAN: id = TONE_AMERICAN_BUSY; break;
1711                 case DSP_GERMAN: id = TONE_GERMAN_BUSY; break;
1712                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDBUSY; break;
1713                 }
1714         } else if (!strcmp(tone, "release"))
1715         {
1716                 hangup:
1717                 switch(options.dsptones) {
1718                 case DSP_AMERICAN: id = TONE_AMERICAN_HANGUP; break;
1719                 case DSP_GERMAN: id = TONE_GERMAN_HANGUP; break;
1720                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDHANGUP; break;
1721                 }
1722         } else if (!strcmp(tone, "cause_10"))
1723                 goto hangup;
1724         else if (!strcmp(tone, "cause_11"))
1725                 goto busy;
1726         else if (!strcmp(tone, "cause_22"))
1727         {
1728                 switch(options.dsptones) {
1729                 case DSP_AMERICAN: id = TONE_SPECIAL_INFO; break;
1730                 case DSP_GERMAN: id = TONE_GERMAN_GASSENBESETZT; break;
1731                 case DSP_OLDGERMAN: id = TONE_GERMAN_OLDBUSY; break;
1732                 }
1733         } else if (!strncmp(tone, "cause_", 6))
1734                 id = TONE_SPECIAL_INFO;
1735         else
1736                 id = TONE_OFF;
1737
1738         /* if we have a tone that is not supported by dsp */
1739         if (id==TONE_OFF && tone[0])
1740                 goto nodsp;
1741
1742         setdsp:
1743         if (p_m_tone != id)
1744         {
1745                 /* set new tone */
1746                 p_m_tone = id;
1747                 PDEBUG(DEBUG_ISDN, "we set tone to id=%d.\n", p_m_tone);
1748                 if (p_m_b_index >= 0)
1749                 if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1750 #ifdef SOCKET_MISDN
1751                         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);
1752 #else
1753                         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);
1754 #endif
1755         }
1756         /* turn user-space tones off in cases of no tone OR dsp tone */
1757         Port::set_tone("",NULL);
1758 }
1759
1760
1761 /* MESSAGE_mISDNSIGNAL */
1762 //extern struct message *dddebug;
1763 void PmISDN::message_mISDNsignal(unsigned long epoint_id, int message_id, union parameter *param)
1764 {
1765         switch(param->mISDNsignal.message)
1766         {
1767                 case mISDNSIGNAL_VOLUME:
1768                 if (p_m_txvol != param->mISDNsignal.txvol)
1769                 {
1770                         p_m_txvol = param->mISDNsignal.txvol;
1771                         PDEBUG(DEBUG_BCHANNEL, "we change tx-volume to shift=%d.\n", p_m_txvol);
1772                         if (p_m_b_index >= 0)
1773                         if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1774 #ifdef SOCKET_MISDN
1775                                 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);
1776 #else
1777                                 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);
1778 #endif
1779                 } else
1780                         PDEBUG(DEBUG_BCHANNEL, "we already have tx-volume shift=%d.\n", p_m_rxvol);
1781                 if (p_m_rxvol != param->mISDNsignal.rxvol)
1782                 {
1783                         p_m_rxvol = param->mISDNsignal.rxvol;
1784                         PDEBUG(DEBUG_BCHANNEL, "we change rx-volume to shift=%d.\n", p_m_rxvol);
1785                         if (p_m_b_index >= 0)
1786                         if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1787 #ifdef SOCKET_MISDN
1788                                 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);
1789 #else
1790                                 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);
1791 #endif
1792                 } else
1793                         PDEBUG(DEBUG_BCHANNEL, "we already have rx-volume shift=%d.\n", p_m_rxvol);
1794                 break;
1795
1796                 case mISDNSIGNAL_CONF:
1797 //if (dddebug) PDEBUG(DEBUG_ISDN, "dddebug = %d\n", dddebug->type);
1798 //tone          if (!p_m_tone && p_m_conf!=param->mISDNsignal.conf)
1799                 if (p_m_conf != param->mISDNsignal.conf)
1800                 {
1801                         p_m_conf = param->mISDNsignal.conf;
1802                         PDEBUG(DEBUG_BCHANNEL, "we change conference to conf=%d.\n", p_m_conf);
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], (p_m_conf)?CMX_CONF_JOIN:CMX_CONF_SPLIT, p_m_conf, "DSP-CONF", p_m_conf);
1807 #else
1808                                 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);
1809 #endif
1810                 } else
1811                         PDEBUG(DEBUG_BCHANNEL, "we already have conf=%d.\n", p_m_conf);
1812                 /* we must set, even if currently tone forbids conf */
1813                 p_m_conf = param->mISDNsignal.conf;
1814 //if (dddebug) PDEBUG(DEBUG_ISDN, "dddebug = %d\n", dddebug->type);
1815                 break;
1816
1817                 case mISDNSIGNAL_JOINDATA:
1818                 if (p_m_joindata != param->mISDNsignal.joindata)
1819                 {
1820                         p_m_joindata = param->mISDNsignal.joindata;
1821                         PDEBUG(DEBUG_BCHANNEL, "we change to joindata=%d.\n", p_m_joindata);
1822                 } else
1823                         PDEBUG(DEBUG_BCHANNEL, "we already have joindata=%d.\n", p_m_joindata);
1824                 break;
1825                 
1826                 case mISDNSIGNAL_DELAY:
1827                 if (p_m_delay != param->mISDNsignal.delay)
1828                 {
1829                         p_m_delay = param->mISDNsignal.delay;
1830                         PDEBUG(DEBUG_BCHANNEL, "we change delay mode to delay=%d.\n", p_m_delay);
1831                         if (p_m_b_index >= 0)
1832                         if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1833 #ifdef SOCKET_MISDN
1834                                 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);
1835 #else
1836                                 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);
1837 #endif
1838                 } else
1839                         PDEBUG(DEBUG_BCHANNEL, "we already have delay=%d.\n", p_m_delay);
1840                 break;
1841
1842                 default:
1843                 PERROR("PmISDN(%s) unsupported signal message %d.\n", p_name, param->mISDNsignal.message);
1844         }
1845 }
1846
1847 /* MESSAGE_CRYPT */
1848 void PmISDN::message_crypt(unsigned long epoint_id, int message_id, union parameter *param)
1849 {
1850         struct message *message;
1851
1852         switch(param->crypt.type)
1853         {
1854                 case CC_ACTBF_REQ:           /* activate blowfish */
1855                 p_m_crypt = 1;
1856                 p_m_crypt_key_len = param->crypt.len;
1857                 if (p_m_crypt_key_len > (int)sizeof(p_m_crypt_key))
1858                 {
1859                         PERROR("PmISDN(%s) key too long %d > %d\n", p_name, p_m_crypt_key_len, sizeof(p_m_crypt_key));
1860                         message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CRYPT);
1861                         message->param.crypt.type = CC_ERROR_IND;
1862                         message_put(message);
1863                         break;
1864                 }
1865                 memcpy(p_m_crypt_key, param->crypt.data, p_m_crypt_key_len);
1866                 crypt_off:
1867                 PDEBUG(DEBUG_BCHANNEL, "we set encryption to crypt=%d. (0 means OFF)\n", p_m_crypt);
1868                 if (p_m_b_index >= 0)
1869                 if (p_m_mISDNport->b_state[p_m_b_index] == B_STATE_ACTIVE)
1870 #ifdef SOCKET_MISDN
1871                         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);
1872 #else
1873                         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);
1874 #endif
1875                 break;
1876
1877                 case CC_DACT_REQ:            /* deactivate session encryption */
1878                 p_m_crypt = 0;
1879                 goto crypt_off;
1880                 break;
1881
1882                 case CR_LISTEN_REQ:          /* start listening to messages */
1883                 p_m_crypt_listen = 1;
1884                 p_m_crypt_listen_state = 0;
1885                 break;
1886
1887                 case CR_UNLISTEN_REQ:        /* stop listening to messages */
1888                 p_m_crypt_listen = 0;
1889                 break;
1890
1891                 case CR_MESSAGE_REQ:         /* send message */
1892                 p_m_crypt_msg_len = cryptman_encode_bch(param->crypt.data, param->crypt.len, p_m_crypt_msg, sizeof(p_m_crypt_msg));
1893                 if (!p_m_crypt_msg_len)
1894                 {
1895                         PERROR("PmISDN(%s) message too long %d > %d\n", p_name, param->crypt.len-1, sizeof(p_m_crypt_msg));
1896                         break;
1897                 }
1898                 p_m_crypt_msg_current = 0; /* reset */
1899                 p_m_crypt_msg_loops = 3; /* enable */
1900 #if 0
1901                 /* disable txmix, or we get corrupt data due to audio process */
1902                 if (p_m_txmix && p_m_b_index>=0)
1903                 {
1904                         PDEBUG(DEBUG_BCHANNEL, "for sending CR_MESSAGE_REQ, we reset txmix from txmix=%d.\n", p_m_txmix);
1905 #ifdef SOCKET_MISDN
1906                         ph_control(p_m_mISDNport, this, p_mISDNport->b_socket[p_m_b_index], CMX_MIX_OFF, 0, "DSP-TXMIX", 0);
1907 #else
1908                         ph_control(p_m_mISDNport, this, p_mISDNport->b_addr[p_m_b_index], CMX_MIX_OFF, 0, "DSP-TXMIX", 0);
1909 #endif
1910                 }
1911 #endif
1912                 break;
1913
1914                 default:
1915                 PERROR("PmISDN(%s) unknown crypt message %d\n", p_name, param->crypt.type);
1916         }
1917
1918 }
1919
1920 /*
1921  * endpoint sends messages to the port
1922  */
1923 int PmISDN::message_epoint(unsigned long epoint_id, int message_id, union parameter *param)
1924 {
1925         if (Port::message_epoint(epoint_id, message_id, param))
1926                 return(1);
1927
1928         switch(message_id)
1929         {
1930                 case MESSAGE_DATA: /* tx-data from upper layer */
1931                 txfromup(param->data.data, param->data.len);
1932                 return(1);
1933
1934                 case MESSAGE_mISDNSIGNAL: /* user command */
1935                 PDEBUG(DEBUG_ISDN, "PmISDN(%s) received special ISDN SIGNAL %d.\n", p_name, param->mISDNsignal.message);
1936                 message_mISDNsignal(epoint_id, message_id, param);
1937                 return(1);
1938
1939                 case MESSAGE_CRYPT: /* crypt control command */
1940                 PDEBUG(DEBUG_ISDN, "PmISDN(%s) received encryption command '%d'.\n", p_name, param->crypt.type);
1941                 message_crypt(epoint_id, message_id, param);
1942                 return(1);
1943         }
1944
1945         return(0);
1946 }
1947
1948
1949 /*
1950  * main loop for processing messages from mISDN
1951  */
1952 #ifdef SOCKET_MISDN
1953 int mISDN_handler(void)
1954 {
1955         int ret;
1956         struct mISDNport *mISDNport;
1957         class PmISDN *isdnport;
1958         int i;
1959         char buffer[2048+MISDN_HEADER_LEN];
1960         struct mISDNhead *hh = (struct mISDNhead *)buffer;
1961
1962         /* process all ports */
1963         mISDNport = mISDNport_first;
1964         while(mISDNport)
1965         {
1966                 /* process all bchannels */
1967                 i = 0;
1968                 while(i < mISDNport->b_num)
1969                 {
1970                         /* handle port of bchannel */
1971                         isdnport=mISDNport->b_port[i];
1972                         if (isdnport)
1973                         {
1974                                 /* call bridges in user space OR crypto OR recording */
1975                                 if (isdnport->p_m_joindata || isdnport->p_m_crypt_msg_loops || isdnport->p_m_crypt_listen || isdnport->p_record)
1976                                 {
1977                                         /* rx IS required */
1978                                         if (isdnport->p_m_rxoff)
1979                                         {
1980                                                 /* turn on RX */
1981                                                 isdnport->p_m_rxoff = 0;
1982                                                 PDEBUG(DEBUG_BCHANNEL, "%s: receive data is required, so we turn them on\n");
1983                                                 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
1984                                                         ph_control(mISDNport, isdnport, mISDNport->b_socket[isdnport->p_m_b_index], CMX_RECEIVE_ON, 0, "DSP-RXOFF", 0);
1985                                                 return(1);
1986                                         }
1987                                 } else
1988                                 {
1989                                         /* rx NOT required */
1990                                         if (!isdnport->p_m_rxoff)
1991                                         {
1992                                                 /* turn off RX */
1993                                                 isdnport->p_m_rxoff = 1;
1994                                                 PDEBUG(DEBUG_BCHANNEL, "%s: receive data is not required, so we turn them off\n");
1995                                                 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
1996                                                         ph_control(mISDNport, isdnport, mISDNport->b_socket[isdnport->p_m_b_index], CMX_RECEIVE_OFF, 0, "DSP-RXOFF", 1);
1997                                                 return(1);
1998                                         }
1999                                 }
2000                                 /* recording */
2001                                 if (isdnport->p_record)
2002                                 {
2003                                         /* txdata IS required */
2004                                         if (!isdnport->p_m_txdata)
2005                                         {
2006                                                 /* turn on RX */
2007                                                 isdnport->p_m_txdata = 1;
2008                                                 PDEBUG(DEBUG_BCHANNEL, "%s: transmit data is required, so we turn them on\n");
2009                                                 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
2010                                                         ph_control(mISDNport, isdnport, mISDNport->b_socket[isdnport->p_m_b_index], CMX_TXDATA_ON, 0, "DSP-TXDATA", 1);
2011                                                 return(1);
2012                                         }
2013                                 } else
2014                                 {
2015                                         /* txdata NOT required */
2016                                         if (isdnport->p_m_txdata)
2017                                         {
2018                                                 /* turn off RX */
2019                                                 isdnport->p_m_txdata = 0;
2020                                                 PDEBUG(DEBUG_BCHANNEL, "%s: transmit data is not required, so we turn them off\n");
2021                                                 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
2022                                                         ph_control(mISDNport, isdnport, mISDNport->b_socket[isdnport->p_m_b_index], CMX_TXDATA_OFF, 0, "DSP-TXDATA", 0);
2023                                                 return(1);
2024                                         }
2025                                 }
2026                         }
2027
2028                         /* handle message from bchannel */
2029                         if (mISDNport->b_stack[i] > -1)
2030                         {
2031                                 ret = recv(mISDNport->b_stack[i], buffer, sizeof(buffer), 0);
2032                                 if (ret >= MISDN_HEADER_LEN)
2033                                 {
2034                                         switch(hh->prim)
2035                                         {
2036                                                 /* we don't care about confirms, we use rx data to sync tx */
2037                                                 case PH_DATA_CONF:
2038                                                 case DL_DATA_CONF:
2039                                                 break;
2040
2041                                                 /* we receive audio data, we respond to it AND we send tones */
2042                                                 case PH_DATA_IND:
2043                                                 case DL_DATA_IND:
2044                                                 case PH_CONTROL_IND:
2045                                                 if (mISDNport->b_port[i])
2046                                                         mISDNport->b_port[i]->bchannel_receive(hh, buffer+MISDN_HEADER_LEN, ret-MISDN_HEADER_LEN);
2047                                                 else
2048                                                         PDEBUG(DEBUG_BCHANNEL, "b-channel is not associated to an ISDNPort (socket %d), ignoring.\n", mISDNport->b_stack[i]);
2049                                                 break;
2050
2051                                                 case PH_ACTIVATE_IND:
2052                                                 case DL_ESTABLISH_IND:
2053                                                 case PH_ACTIVATE_CONF:
2054                                                 case DL_ESTABLISH_CONF:
2055                                                 PDEBUG(DEBUG_BCHANNEL, "DL_ESTABLISH confirm: bchannel is now activated (socket %d).\n", mISDNport->b_socket[i]);
2056                                                 bchannel_event(mISDNport, i, B_EVENT_ACTIVATED);
2057                                                 break;
2058
2059                                                 case PH_DEACTIVATE_IND:
2060                                                 case DL_RELEASE_IND:
2061                                                 case PH_DEACTIVATE_CONF:
2062                                                 case DL_RELEASE_CONF:
2063                                                 PDEBUG(DEBUG_BCHANNEL, "DL_RELEASE confirm: bchannel is now de-activated (socket %d).\n", mISDNport->b_socket[i]);
2064                                                 bchannel_event(mISDNport, i, B_EVENT_DEACTIVATED);
2065                                                 break;
2066
2067                                                 default:
2068                                                 PERROR("child message not handled: prim(0x%x) socket(%d) msg->len(%d)\n", hh->prim, mISDNport->b_socket[i], msg->len);
2069                                         }
2070                                 } else
2071                                 {
2072                                         if (ret < 0 && errno != EWOULDBLOCK)
2073                                                 PERROR("Read from port %d, index %d failed with return code %d\n", mISDNport->portnum, i, ret);
2074                                 }
2075                         }
2076                         
2077                         i++;
2078                 }
2079 #if 0
2080                 if (mISDNport->l1timeout && now>mISDNport->l1timeout)
2081                 { ---}
2082                         PDEBUG(DEBUG_ISDN, "the L1 establish timer expired, we release all pending messages.\n", mISDNport->portnum);
2083                         mISDNport->l1timeout = 0;
2084 #endif
2085
2086                 /* layer 2 establish timer */
2087                 if (mISDNport->l2establish)
2088                 {
2089                         if (now-mISDNport->l2establish > 5)
2090                         {
2091
2092                                 PDEBUG(DEBUG_ISDN, "the L2 establish timer expired, we try to establish the link portnum=%d.\n", mISDNport->portnum);
2093                                 mISDNport->ml3->to_layer2(mISDNport->ml3, DL_ESTABLISH_REQ);
2094                                 l1l2l3_trace_header(mISDNport, NULL, DL_ESTABLISH_REQ, DIRECTION_OUT);
2095                                 end_trace();
2096                                 return(1);
2097                         }
2098                 }
2099
2100
2101                 mISDNport = mISDNport->next;
2102         }
2103
2104 }
2105 #else
2106 int mISDN_handler(void)
2107 {
2108         int ret;
2109         struct mISDNport *mISDNport;
2110         class PmISDN *isdnport;
2111         int i;
2112         msg_t *msg;
2113         iframe_t *frm;
2114         msg_t *dmsg;
2115         mISDNuser_head_t *hh;
2116         net_stack_t *nst;
2117
2118         /* the que avoids loopbacks when replying to stack after receiving
2119          * from stack. */
2120         mISDNport = mISDNport_first;
2121         while(mISDNport)
2122         {
2123                 /* process turning on/off rx */
2124                 i = 0;
2125                 while(i < mISDNport->b_num)
2126                 {
2127                         isdnport=mISDNport->b_port[i];
2128                         if (isdnport)
2129                         {
2130                                 /* call bridges in user space OR crypto OR recording */
2131                                 if (isdnport->p_m_joindata || isdnport->p_m_crypt_msg_loops || isdnport->p_m_crypt_listen || isdnport->p_record)
2132                                 {
2133                                         /* rx IS required */
2134                                         if (isdnport->p_m_rxoff)
2135                                         {
2136                                                 /* turn on RX */
2137                                                 isdnport->p_m_rxoff = 0;
2138                                                 PDEBUG(DEBUG_BCHANNEL, "%s: receive data is required, so we turn them on\n");
2139                                                 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
2140                                                         ph_control(mISDNport, isdnport, mISDNport->b_addr[isdnport->p_m_b_index], CMX_RECEIVE_ON, 0, "DSP-RXOFF", 0);
2141                                                 return(1);
2142                                         }
2143                                 } else
2144                                 {
2145                                         /* rx NOT required */
2146                                         if (!isdnport->p_m_rxoff)
2147                                         {
2148                                                 /* turn off RX */
2149                                                 isdnport->p_m_rxoff = 1;
2150                                                 PDEBUG(DEBUG_BCHANNEL, "%s: receive data is not required, so we turn them off\n");
2151                                                 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
2152                                                         ph_control(mISDNport, isdnport, mISDNport->b_addr[isdnport->p_m_b_index], CMX_RECEIVE_OFF, 0, "DSP-RXOFF", 1);
2153                                                 return(1);
2154                                         }
2155                                 }
2156                                 /* recording */
2157                                 if (isdnport->p_record)
2158                                 {
2159                                         /* txdata IS required */
2160                                         if (!isdnport->p_m_txdata)
2161                                         {
2162                                                 /* turn on RX */
2163                                                 isdnport->p_m_txdata = 1;
2164                                                 PDEBUG(DEBUG_BCHANNEL, "%s: transmit data is required, so we turn them on\n");
2165                                                 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
2166                                                         ph_control(mISDNport, isdnport, mISDNport->b_addr[isdnport->p_m_b_index], CMX_TXDATA_ON, 0, "DSP-TXDATA", 1);
2167                                                 return(1);
2168                                         }
2169                                 } else
2170                                 {
2171                                         /* txdata NOT required */
2172                                         if (isdnport->p_m_txdata)
2173                                         {
2174                                                 /* turn off RX */
2175                                                 isdnport->p_m_txdata = 0;
2176                                                 PDEBUG(DEBUG_BCHANNEL, "%s: transmit data is not required, so we turn them off\n");
2177                                                 if (mISDNport->b_port[i] && mISDNport->b_state[i] == B_STATE_ACTIVE)
2178                                                         ph_control(mISDNport, isdnport, mISDNport->b_addr[isdnport->p_m_b_index], CMX_TXDATA_OFF, 0, "DSP-TXDATA", 0);
2179                                                 return(1);
2180                                         }
2181                                 }
2182                         }
2183                         i++;
2184                 }
2185 #if 0
2186                 if (mISDNport->l1timeout && now>mISDNport->l1timeout)
2187                 { ---}
2188                         PDEBUG(DEBUG_ISDN, "the L1 establish timer expired, we release all pending messages.\n", mISDNport->portnum);
2189                         mISDNport->l1timeout = 0;
2190 #endif
2191
2192                 if (mISDNport->l2establish)
2193                 {
2194                         if (now-mISDNport->l2establish > 5)
2195                         {
2196                                 if (mISDNport->ntmode)
2197                                 {
2198                                         PDEBUG(DEBUG_ISDN, "the L2 establish timer expired, we try to establish the link NT portnum=%d.\n", mISDNport->portnum);
2199                                         time(&mISDNport->l2establish);
2200                                         /* establish */
2201                                         dmsg = create_l2msg(DL_ESTABLISH | REQUEST, 0, 0);
2202                                         if (mISDNport->nst.manager_l3(&mISDNport->nst, dmsg))
2203                                                 free_msg(dmsg);
2204                                 } else {
2205                                         iframe_t act;
2206
2207                                         PDEBUG(DEBUG_ISDN, "the L2 establish timer expired, we try to establish the link TE portnum=%d.\n", mISDNport->portnum);
2208                                         time(&mISDNport->l2establish);
2209                                         /* establish */
2210                                         act.prim = DL_ESTABLISH | REQUEST; 
2211                                         act.addr = (mISDNport->upper_id & ~LAYER_ID_MASK) | 3 | FLG_MSG_DOWN;
2212                                         act.dinfo = 0;
2213                                         act.len = 0;
2214                                         mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
2215                                 }
2216                                 l1l2l3_trace_header(mISDNport, NULL, DL_ESTABLISH | REQUEST, DIRECTION_OUT);
2217                                 end_trace();
2218                                 return(1);
2219                         }
2220                 }
2221                 if ((dmsg = msg_dequeue(&mISDNport->downqueue)))
2222                 {
2223                         if (mISDNport->ntmode)
2224                         {
2225                                 hh = (mISDNuser_head_t *)dmsg->data;
2226                                 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);
2227                                 if (mISDNport->nst.manager_l3(&mISDNport->nst, dmsg))
2228                                         free_msg(dmsg);
2229                         } else
2230                         {
2231                                 frm = (iframe_t *)dmsg->data;
2232                                 frm->addr = mISDNport->upper_id | FLG_MSG_DOWN;
2233                                 frm->len = (dmsg->len) - mISDN_HEADER_LEN;
2234                                 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);
2235                                 mISDN_write(mISDNdevice, dmsg->data, dmsg->len, TIMEOUT_1SEC);
2236                                 free_msg(dmsg);
2237                         }
2238                         return(1);
2239                 }
2240                 mISDNport = mISDNport->next;
2241         } 
2242
2243         /* no device, no read */
2244         if (mISDNdevice < 0)
2245                 return(0);
2246
2247         /* get message from kernel */
2248         if (!(msg = alloc_msg(MAX_MSG_SIZE)))
2249                 return(1);
2250         ret = mISDN_read(mISDNdevice, msg->data, MAX_MSG_SIZE, 0);
2251         if (ret < 0)
2252         {
2253                 free_msg(msg);
2254                 if (errno == EAGAIN)
2255                         return(0);
2256                 FATAL("Failed to do mISDN_read()\n");
2257         }
2258         if (!ret)
2259         {
2260                 free_msg(msg);
2261 //              printf("%s: ERROR: mISDN_read() returns nothing\n");
2262                 return(0);
2263         }
2264         msg->len = ret;
2265         frm = (iframe_t *)msg->data;
2266
2267         /* global prim */
2268         switch(frm->prim)
2269         {
2270                 case MGR_DELLAYER | CONFIRM:
2271                 case MGR_INITTIMER | CONFIRM:
2272                 case MGR_ADDTIMER | CONFIRM:
2273                 case MGR_DELTIMER | CONFIRM:
2274                 case MGR_REMOVETIMER | CONFIRM:
2275                 free_msg(msg);
2276                 return(1);
2277         }
2278
2279         /* handle timer events from mISDN for NT-stack
2280          * note: they do not associate with a stack */
2281         if (frm->prim == (MGR_TIMER | INDICATION))
2282         {
2283                 itimer_t *it;
2284
2285                 /* find mISDNport */
2286                 mISDNport = mISDNport_first;
2287                 while(mISDNport)
2288                 {
2289                         /* nt mode only */
2290                         if (mISDNport->ntmode)
2291                         {
2292                                 it = mISDNport->nst.tlist;
2293                                 /* find timer */
2294                                 while(it)
2295                                 {
2296                                         if (it->id == (int)frm->addr)
2297                                                 break;
2298                                         it = it->next;
2299                                 }
2300                                 if (it)
2301                                         break;
2302                         }
2303                         mISDNport = mISDNport->next;
2304                 }
2305                 if (mISDNport)
2306                 {
2307                         mISDN_write_frame(mISDNdevice, msg->data, mISDNport->upper_id | FLG_MSG_DOWN,
2308                                 MGR_TIMER | RESPONSE, 0, 0, NULL, TIMEOUT_1SEC);
2309
2310                         PDEBUG(DEBUG_ISDN, "timer-indication port %d it=%p\n", mISDNport->portnum, it);
2311                         test_and_clear_bit(FLG_TIMER_RUNING, (long unsigned int *)&it->Flags);
2312                         ret = it->function(it->data);
2313                 } else
2314                 {
2315                         PDEBUG(DEBUG_ISDN, "timer-indication not handled\n");
2316                 }
2317                 goto out;
2318         }
2319
2320         /* find the mISDNport that belongs to the stack */
2321         mISDNport = mISDNport_first;
2322         while(mISDNport)
2323         {
2324                 if ((frm->addr&MASTER_ID_MASK) == (unsigned int)(mISDNport->upper_id&MASTER_ID_MASK))
2325                         break;
2326                 mISDNport = mISDNport->next;
2327         } 
2328         if (!mISDNport)
2329         {
2330                 PERROR("message belongs to no mISDNport: prim(0x%x) addr(0x%x) msg->len(%d)\n", frm->prim, frm->addr, msg->len);
2331                 goto out;
2332         }
2333
2334         /* master stack */
2335         if (!(frm->addr&FLG_CHILD_STACK))
2336         {
2337                 /* d-message */
2338                 switch(frm->prim)
2339                 {
2340                         case MGR_SHORTSTATUS | INDICATION:
2341                         case MGR_SHORTSTATUS | CONFIRM:
2342                         switch(frm->dinfo) {
2343                                 case SSTATUS_L1_ACTIVATED:
2344                                 l1l2l3_trace_header(mISDNport, NULL, PH_ACTIVATE | (frm->prim & 0x3), DIRECTION_IN);
2345                                 end_trace();
2346                                 goto ss_act;
2347                                 case SSTATUS_L1_DEACTIVATED:
2348                                 l1l2l3_trace_header(mISDNport, NULL, PH_DEACTIVATE | (frm->prim & 0x3), DIRECTION_IN);
2349                                 end_trace();
2350                                 goto ss_deact;
2351                                 case SSTATUS_L2_ESTABLISHED:
2352                                 l1l2l3_trace_header(mISDNport, NULL, DL_ESTABLISH | (frm->prim & 0x3), DIRECTION_IN);
2353                                 end_trace();
2354                                 goto ss_estab;
2355                                 case SSTATUS_L2_RELEASED:
2356                                 l1l2l3_trace_header(mISDNport, NULL, DL_RELEASE | (frm->prim & 0x3), DIRECTION_IN);
2357                                 end_trace();
2358                                 goto ss_rel;
2359                         }
2360                         break;
2361
2362                         case PH_ACTIVATE | CONFIRM:
2363                         case PH_ACTIVATE | INDICATION:
2364                         l1l2l3_trace_header(mISDNport, NULL, frm->prim, DIRECTION_IN);
2365                         end_trace();
2366                         if (mISDNport->ntmode)
2367                         {
2368                                 mISDNport->l1link = 1;
2369                                 setup_queue(mISDNport, 1);
2370                                 goto l1_msg;
2371                         }
2372                         ss_act:
2373                         mISDNport->l1link = 1;
2374                         setup_queue(mISDNport, 1);
2375                         break;
2376
2377                         case PH_DEACTIVATE | CONFIRM:
2378                         case PH_DEACTIVATE | INDICATION:
2379                         l1l2l3_trace_header(mISDNport, NULL, frm->prim, DIRECTION_IN);
2380                         end_trace();
2381                         if (mISDNport->ntmode)
2382                         {
2383                                 mISDNport->l1link = 0;
2384                                 setup_queue(mISDNport, 0);
2385                                 goto l1_msg;
2386                         }
2387                         ss_deact:
2388                         mISDNport->l1link = 0;
2389                         setup_queue(mISDNport, 0);
2390                         break;
2391
2392                         case PH_CONTROL | CONFIRM:
2393                         case PH_CONTROL | INDICATION:
2394                         PDEBUG(DEBUG_ISDN, "Received PH_CONTROL for port %d (%s).\n", mISDNport->portnum, mISDNport->ifport->interface->name);
2395                         break;
2396
2397                         case DL_ESTABLISH | INDICATION:
2398                         case DL_ESTABLISH | CONFIRM:
2399                         l1l2l3_trace_header(mISDNport, NULL, frm->prim, DIRECTION_IN);
2400                         end_trace();
2401                         if (!mISDNport->ntmode) break; /* !!!!!!!!!!!!!!!! */
2402                         ss_estab:
2403                         if (mISDNport->l2establish)
2404                         {
2405                                 mISDNport->l2establish = 0;
2406                                 PDEBUG(DEBUG_ISDN, "the link became active before l2establish timer expiry.\n");
2407                         }
2408                         mISDNport->l2link = 1;
2409                         break;
2410
2411                         case DL_RELEASE | INDICATION:
2412                         case DL_RELEASE | CONFIRM:
2413                         l1l2l3_trace_header(mISDNport, NULL, frm->prim, DIRECTION_IN);
2414                         end_trace();
2415                         if (!mISDNport->ntmode) break; /* !!!!!!!!!!!!!!!! */
2416                         ss_rel:
2417                         mISDNport->l2link = 0;
2418                         if (mISDNport->ptp)
2419                         {
2420                                 time(&mISDNport->l2establish);
2421                                 PDEBUG(DEBUG_ISDN, "because we are ptp, we set a l2establish timer.\n");
2422                         }
2423                         break;
2424
2425                         default:
2426                         l1_msg:
2427                         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);
2428                         if (frm->dinfo==(signed long)0xffffffff && frm->prim==(PH_DATA|CONFIRM))
2429                         {
2430                                 PERROR("SERIOUS BUG, dinfo == 0xffffffff, prim == PH_DATA | CONFIRM !!!!\n");
2431                         }
2432                         /* d-message */
2433                         if (mISDNport->ntmode)
2434                         {
2435                                 /* l1-data enters the nt-mode library */
2436                                 nst = &mISDNport->nst;
2437                                 if (nst->l1_l2(nst, msg))
2438                                         free_msg(msg);
2439                                 return(1);
2440                         } else
2441                         {
2442                                 /* l3-data is sent to pbx */
2443                                 if (stack2manager_te(mISDNport, msg))
2444                                         free_msg(msg);
2445                                 return(1);
2446                         }
2447                 }
2448         } else
2449         /* child stack */
2450         {
2451                 /* b-message */
2452                 switch(frm->prim)
2453                 {
2454                         /* we don't care about confirms, we use rx data to sync tx */
2455                         case PH_DATA | CONFIRM:
2456                         case DL_DATA | CONFIRM:
2457                         break;
2458
2459                         /* we receive audio data, we respond to it AND we send tones */
2460                         case PH_DATA | INDICATION:
2461                         case DL_DATA | INDICATION:
2462                         case PH_CONTROL | INDICATION:
2463                         i = 0;
2464                         while(i < mISDNport->b_num)
2465                         {
2466                                 if ((unsigned int)(mISDNport->b_addr[i]&STACK_ID_MASK) == (frm->addr&STACK_ID_MASK))
2467                                         break;
2468                                 i++;
2469                         }
2470                         if (i == mISDNport->b_num)
2471                         {
2472                                 PERROR("unhandled b-message (prim 0x%x address 0x%x).\n", frm->prim, frm->addr);
2473                                 break;
2474                         }
2475                         if (mISDNport->b_port[i])
2476                         {
2477 //PERROR("port sech: %s data\n", mISDNport->b_port[i]->p_name);
2478                                 mISDNport->b_port[i]->bchannel_receive(frm);
2479                         } else
2480                                 PDEBUG(DEBUG_BCHANNEL, "b-channel is not associated to an ISDNPort (address 0x%x), ignoring.\n", frm->addr);
2481                         break;
2482
2483                         case PH_ACTIVATE | INDICATION:
2484                         case DL_ESTABLISH | INDICATION:
2485                         case PH_ACTIVATE | CONFIRM:
2486                         case DL_ESTABLISH | CONFIRM:
2487                         PDEBUG(DEBUG_BCHANNEL, "DL_ESTABLISH confirm: bchannel is now activated (address 0x%x).\n", frm->addr);
2488                         i = 0;
2489                         while(i < mISDNport->b_num)
2490                         {
2491                                 if ((unsigned int)(mISDNport->b_addr[i]&STACK_ID_MASK) == (frm->addr&STACK_ID_MASK))
2492                                         break;
2493                                 i++;
2494                         }
2495                         if (i == mISDNport->b_num)
2496                         {
2497                                 PERROR("unhandled b-establish (prim 0x%x address 0x%x).\n", frm->prim, frm->addr);
2498                                 break;
2499                         }
2500                         bchannel_event(mISDNport, i, B_EVENT_ACTIVATED);
2501                         break;
2502
2503                         case PH_DEACTIVATE | INDICATION:
2504                         case DL_RELEASE | INDICATION:
2505                         case PH_DEACTIVATE | CONFIRM:
2506                         case DL_RELEASE | CONFIRM:
2507                         PDEBUG(DEBUG_BCHANNEL, "DL_RELEASE confirm: bchannel is now de-activated (address 0x%x).\n", frm->addr);
2508                         i = 0;
2509                         while(i < mISDNport->b_num)
2510                         {
2511                                 if ((unsigned int)(mISDNport->b_addr[i]&STACK_ID_MASK) == (frm->addr&STACK_ID_MASK))
2512                                         break;
2513                                 i++;
2514                         }
2515                         if (i == mISDNport->b_num)
2516                         {
2517                                 PERROR("unhandled b-release (prim 0x%x address 0x%x).\n", frm->prim, frm->addr);
2518                                 break;
2519                         }
2520                         bchannel_event(mISDNport, i, B_EVENT_DEACTIVATED);
2521                         break;
2522
2523                         default:
2524                         PERROR("child message not handled: prim(0x%x) addr(0x%x) msg->len(%d)\n", frm->prim, frm->addr, msg->len);
2525                 }
2526         }
2527
2528         out:
2529         free_msg(msg);
2530         return(1);
2531 }
2532 #endif
2533
2534 #ifdef SOCKET_MISDN
2535 int do_layer3(struct mlayer3 *ml3, unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
2536 {
2537         struct mISDNport *mISDNport = ml3->private;
2538
2539         if (cmd == MT_ASSIGN)
2540         {
2541                 ueberdenken!!!
2542         }
2543         
2544         /* lock LCR */
2545         achtung MT_ASSIGN kommt hier an
2546         lock it baby
2547
2548         /* d-message */
2549         switch(cmd)
2550         {
2551                 case MGR_SHORTSTATUS_IND:
2552                 case MGR_SHORTSTATUS_CONF:
2553                 switch(frm->dinfo) {
2554                         case SSTATUS_L1_ACTIVATED:
2555                         l1l2l3_trace_header(mISDNport, NULL, PH_ACTIVATE_IND, DIRECTION_IN);
2556                         end_trace();
2557                         goto ss_act;
2558                         case SSTATUS_L1_DEACTIVATED:
2559                         l1l2l3_trace_header(mISDNport, NULL, PH_DEACTIVATE_IND, DIRECTION_IN);
2560                         end_trace();
2561                         goto ss_deact;
2562                         case SSTATUS_L2_ESTABLISHED:
2563                         l1l2l3_trace_header(mISDNport, NULL, DL_ESTABLISH_IND, DIRECTION_IN);
2564                         end_trace();
2565                         goto ss_estab;
2566                         case SSTATUS_L2_RELEASED:
2567                         l1l2l3_trace_header(mISDNport, NULL, DL_RELEASE_IND, DIRECTION_IN);
2568                         end_trace();
2569                         goto ss_rel;
2570                 }
2571                 break;
2572
2573                 case PH_ACTIVATE_CONF:
2574                 case PH_ACTIVATE_IND:
2575                 l1l2l3_trace_header(mISDNport, NULL, cmd, DIRECTION_IN);
2576                 end_trace();
2577                 ss_act:
2578                 mISDNport->l1link = 1;
2579 #if 0
2580                 if (mISDNport->ntmode)
2581                         setup_queue(mISDNport, 1);
2582 #endif
2583                 break;
2584
2585                 case PH_DEACTIVATE | CONFIRM:
2586                 case PH_DEACTIVATE | INDICATION:
2587                 l1l2l3_trace_header(mISDNport, NULL, cmd, DIRECTION_IN);
2588                 end_trace();
2589                 ss_deact:
2590                 mISDNport->l1link = 0;
2591 raus mit der setup-queue, da dies im stack geschieht
2592 #if 0
2593                 if (mISDNport->ntmode)
2594                         setup_queue(mISDNport, 0);
2595 #endif
2596                 break;
2597
2598                 case PH_CONTROL_CONFIRM:
2599                 case PH_CONTROL_INDICATION:
2600                 PDEBUG(DEBUG_ISDN, "Received PH_CONTROL for port %d (%s).\n", mISDNport->portnum, mISDNport->ifport->interface->name);
2601                 break;
2602
2603                 case DL_ESTABLISH_IND:
2604                 case DL_ESTABLISH_CONF:
2605                 l1l2l3_trace_header(mISDNport, NULL, cmd, DIRECTION_IN);
2606                 end_trace();
2607                 if (!mISDNport->ntmode) break; /* !!!!!!!!!!!!!!!! */
2608                 ss_estab:
2609                 if (mISDNport->l2establish)
2610                 {
2611                         mISDNport->l2establish = 0;
2612                         PDEBUG(DEBUG_ISDN, "the link became active before l2establish timer expiry.\n");
2613                 }
2614                 mISDNport->l2link = 1;
2615                 break;
2616
2617                 case DL_RELEASE_IND:
2618                 case DL_RELEASE_CONF:
2619                 l1l2l3_trace_header(mISDNport, NULL, cmd, DIRECTION_IN);
2620                 end_trace();
2621                 ss_rel:
2622                 mISDNport->l2link = 0;
2623                 if (mISDNport->ptp)
2624                 {
2625                         time(&mISDNport->l2establish);
2626                         PDEBUG(DEBUG_ISDN, "because we are ptp, we set a l2establish timer.\n");
2627                 }
2628                 break;
2629
2630                 default:
2631                 /* l3-data is sent to LCR */
2632                 message_from_mlayer3(mISDNport, cmd, pid, l3m);
2633         }
2634
2635         /* unlock LCR */
2636         unlock it baby
2637
2638         /* free message */
2639         if (l3m)
2640                 free_l3_msg(l3m);
2641         return(0);
2642
2643 }
2644 #endif
2645
2646
2647 /*
2648  * global function to add a new card (port)
2649  */
2650 struct mISDNport *mISDNport_open(int port, int ptp, int ptmp, int force_nt, struct interface *interface)
2651 {
2652         int ret;
2653         unsigned char buff[1025];
2654         iframe_t *frm = (iframe_t *)buff;
2655         struct mISDNport *mISDNport, **mISDNportp;
2656         int i, cnt;
2657         int pri, bri, ports;
2658         int nt, te;
2659 #ifdef SOCKET_MISDN
2660         struct mlayer3 *ml3;
2661         struct mISDN_devinfo devinfo;
2662
2663         ret = ioctl(mISDNsocket, IMGETCOUNT, &cnt);
2664         if (ret < 0)
2665         {
2666                 fprintf(stderr, "Cannot get number of mISDN devices. (ioctl IMGETCOUNT failed ret=%d)\n", ret);
2667                 return(NULL);
2668         }
2669 #else
2670 //      interface_info_t ii;
2671         net_stack_t *nst;
2672         manager_t *mgr;
2673         layer_info_t li;
2674         stack_info_t *stinf;
2675
2676         /* query port's requirements */
2677         cnt = mISDN_get_stack_count(mISDNdevice);
2678 #endif
2679
2680         if (cnt <= 0)
2681         {
2682                 PERROR_RUNTIME("Found no card. Please be sure to load card drivers.\n");
2683                 return(NULL);
2684         }
2685         if (port>cnt || port<1)
2686         {
2687                 PERROR_RUNTIME("Port (%d) given at 'ports' (options.conf) is out of existing port range (%d-%d)\n", port, 1, cnt);
2688                 return(NULL);
2689         }
2690
2691         pri = bri = ports = nt = te = 0;
2692 #ifdef SOCKET_MISDN
2693         devinfo.id = port - 1;
2694         ret = ioctl(socket, IMGETDEVINFO, &devinfo);
2695         if (ret <= 0)
2696         {
2697                 PERROR_RUNTIME("Cannot get device information for port %d. (ioctl IMGETDEVINFO failed ret=%d)\n", i, ret);
2698                 break;
2699         }
2700         /* output the port info */
2701         if (devinfo.Dprotocols & (1 << ISDN_P_TE_S0))
2702         {
2703                 bri = 1;
2704                 te = 1;
2705         }
2706         if (devinfo.Dprotocols & (1 << ISDN_P_NT_S0))
2707         {
2708                 bri = 1;
2709                 nt = 1;
2710         }
2711 #ifdef ISDN_P_TE_E1
2712         if (devinfo.Dprotocols & (1 << ISDN_P_TE_E1))
2713         {
2714                 pri = 1;
2715                 te = 1;
2716         }
2717 #endif
2718 #ifdef ISDN_P_NT_E1
2719         if (devinfo.Dprotocols & (1 << ISDN_P_NT_E1))
2720         {
2721                 pri = 1;
2722                 nt = 1;
2723         }
2724 #endif
2725 #ifdef ISDN_P_FXS
2726         if (devinfo.Dprotocols & (1 << ISDN_P_FXS))
2727         {
2728                 pots = 1;
2729                 te = 1;
2730         }
2731 #endif
2732 #ifdef ISDN_P_FXO
2733         if (devinfo.Dprotocols & (1 << ISDN_P_FXO))
2734         {
2735                 pots = 1;
2736                 nt = 1;
2737         }
2738 #endif
2739         if (force_nt && !nt)
2740         {
2741                 PERROR_RUNTIME("Port %d does not support NT-mode.\n", port);
2742                 return(NULL);
2743         }
2744         if (bri && pri)
2745         {
2746                 PERROR_RUNTIME("Port %d supports BRI and PRI?? What kind of controller is that?. (Can't use this!)\n", port);
2747                 return(NULL);
2748         }
2749         if (pots && !bri && !pri)
2750         {
2751                 PERROR_RUNTIME("Port %d supports POTS, LCR does not!\n", port);
2752                 return(NULL);
2753         }
2754         if (!bri && !pri)
2755         {
2756                 PERROR_RUNTIME("Port %d does not support BRI nor PRI!\n", port);
2757                 return(NULL);
2758         }
2759         if (!nt && !te)
2760         {
2761                 PERROR_RUNTIME("Port %d does not support NT-mode nor TE-mode!\n", port);
2762                 return(NULL);
2763         }
2764         /* force nt, by turning off TE */
2765         if (force_nt && nt)
2766                 te = 0;
2767         /* if TE an NT is supported (and not forced to NT), turn off NT */
2768         if (te && nt)
2769                 nt = 0;
2770 #else
2771         ret = mISDN_get_stack_info(mISDNdevice, port, buff, sizeof(buff));
2772         if (ret < 0)
2773         {
2774                 PERROR_RUNTIME("Cannot get stack info for port %d (ret=%d)\n", port, ret);
2775                 return(NULL);
2776         }
2777         stinf = (stack_info_t *)&frm->data.p;
2778         switch(stinf->pid.protocol[0] & ~ISDN_PID_FEATURE_MASK)
2779         {
2780                 case ISDN_PID_L0_TE_S0:
2781                 PDEBUG(DEBUG_ISDN, "TE-mode BRI S/T interface line\n");
2782                 break;
2783                 case ISDN_PID_L0_NT_S0:
2784                 PDEBUG(DEBUG_ISDN, "NT-mode BRI S/T interface port\n");
2785                 nt = 1;
2786                 break;
2787                 case ISDN_PID_L0_TE_E1:
2788                 PDEBUG(DEBUG_ISDN, "TE-mode PRI E1  interface line\n");
2789                 pri = 1;
2790                 break;
2791                 case ISDN_PID_L0_NT_E1:
2792                 PDEBUG(DEBUG_ISDN, "LT-mode PRI E1  interface port\n");
2793                 pri = 1;
2794                 nt = 1;
2795                 break;
2796                 default:
2797                 PERROR_RUNTIME("unknown port(%d) type 0x%08x\n", port, stinf->pid.protocol[0]);
2798                 return(NULL);
2799         }
2800         if (nt)
2801         {
2802                 /* NT */
2803                 if (stinf->pid.protocol[1] == 0)
2804                 {
2805                         PERROR_RUNTIME("Given port %d: Missing layer 1 NT-mode protocol.\n", port);
2806                         return(NULL);
2807                 }
2808                 if (stinf->pid.protocol[2])
2809                 {
2810                         PERROR_RUNTIME("Given port %d: Layer 2 protocol 0x%08x is detected, but not allowed for NT lib.\n", port, stinf->pid.protocol[2]);
2811                         return(NULL);
2812                 }
2813         }
2814         if (te)
2815         {
2816                 /* TE */
2817                 if (stinf->pid.protocol[1] == 0)
2818                 {
2819                         PERROR_RUNTIME("Given port %d: Missing layer 1 protocol.\n", port);
2820                         return(NULL);
2821                 }
2822                 if (stinf->pid.protocol[2] == 0)
2823                 {
2824                         PERROR_RUNTIME("Given port %d: Missing layer 2 protocol.\n", port);
2825                         return(NULL);
2826                 }
2827                 if (stinf->pid.protocol[3] == 0)
2828                 {
2829                         PERROR_RUNTIME("Given port %d: Missing layer 3 protocol.\n", port);
2830                         return(NULL);
2831                 } else
2832                 {
2833                         switch(stinf->pid.protocol[3] & ~ISDN_PID_FEATURE_MASK)
2834                         {
2835                                 case ISDN_PID_L3_DSS1USER:
2836                                 break;
2837
2838                                 default:
2839                                 PERROR_RUNTIME("Given port %d: own protocol 0x%08x", port,stinf->pid.protocol[3]);
2840                                 return(NULL);
2841                         }
2842                 }
2843                 if (stinf->pid.protocol[4])
2844                 {
2845                         PERROR_RUNTIME("Given port %d: Layer 4 protocol not allowed.\n", port);
2846                         return(NULL);
2847                 }
2848         }
2849 #endif
2850
2851         /* add mISDNport structure */
2852         mISDNportp = &mISDNport_first;
2853         while(*mISDNportp)
2854                 mISDNportp = &((*mISDNportp)->next);
2855         mISDNport = (struct mISDNport *)MALLOC(sizeof(struct mISDNport));
2856         pmemuse++;
2857         *mISDNportp = mISDNport;
2858
2859         /* allocate ressources of port */
2860 #ifdef SOCKET_MISDN
2861         /* open layer 3 */
2862         protocol = (nt)?L3_PROTOCOL_DSS1_USER:L3_PROTOCOL_DSS1_NETWORK;
2863         prop = 0;
2864         if (ptp)
2865                prop |= FLG_PTP;
2866         if (ptmp && pri)
2867                prop |= FLG_FORCE_PTMP;
2868         mISDNport->ml3 = open_layer3(port-1, protocol, prop , do_dchannel, mISDNport);
2869         if (!mISDNport->ml3)
2870         {
2871                 PERROR_RUNTIME("Cannot get layer(%d) id of port %d\n", nt?2:4, port);
2872                 return(NULL);
2873         }
2874
2875 #if 0
2876         /* if ntmode, establish L1 to send the tei removal during start */
2877         if (mISDNport->ntmode)
2878         {
2879                 iframe_t act;
2880                 /* L1 */
2881                 act.prim = PH_ACTIVATE | REQUEST; 
2882                 act.addr = mISDNport->upper_id | FLG_MSG_DOWN;
2883                 printf("UPPER ID 0x%x, addr 0x%x\n",mISDNport->upper_id, act.addr);
2884                 act.dinfo = 0;
2885                 act.len = 0;
2886                 mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
2887                 usleep(10000); /* to be sure, that l1 is up */
2888         }
2889 #endif
2890
2891         SCPY(mISDNport->name, devinfo.name);
2892         mISDNport->b_num = devinfo.nrbchan;
2893 #else
2894         msg_queue_init(&mISDNport->downqueue);
2895         mISDNport->d_stid = stinf->id;
2896         PDEBUG(DEBUG_ISDN, "d_stid = 0x%x.\n", mISDNport->d_stid);
2897         if ((stinf->pid.protocol[2]&ISDN_PID_L2_DF_PTP) || (nt&&ptp) || pri)
2898         {
2899                 PDEBUG(DEBUG_ISDN, "Port is point-to-point.\n");
2900                 ptp = 1;
2901                 if (ptmp && nt)
2902                 {
2903                         PDEBUG(DEBUG_ISDN, "Port is forced to point-to-multipoint.\n");
2904                         ptp = 0;
2905                 }
2906         }
2907
2908         /* create layer intance */
2909         memset(&li, 0, sizeof(li));
2910         UCPY(&li.name[0], (nt)?"net l2":"pbx l4");
2911         li.object_id = -1;
2912         li.extentions = 0;
2913         li.pid.protocol[nt?2:4] = (nt)?ISDN_PID_L2_LAPD_NET:ISDN_PID_L4_CAPI20;
2914         li.pid.layermask = ISDN_LAYER((nt?2:4));
2915         li.st = mISDNport->d_stid;
2916         ret = mISDN_new_layer(mISDNdevice, &li);
2917         if (ret)
2918         {
2919                 PERROR("Cannot add layer %d of port %d (ret %d)\n", nt?2:4, port, ret);
2920                 closeport:
2921                 mISDNport_close(mISDNport);
2922                 return(NULL);
2923         }
2924         mISDNport->upper_id = li.id;
2925         ret = mISDN_register_layer(mISDNdevice, mISDNport->d_stid, mISDNport->upper_id);
2926         if (ret)
2927         {
2928                 PERROR("Cannot register layer %d of port %d\n", nt?2:4, port);
2929                 goto closeport;
2930         }
2931         mISDNport->lower_id = mISDN_get_layerid(mISDNdevice, mISDNport->d_stid, nt?1:3); // id of lower layer (nt=1, te=3)
2932         if (mISDNport->lower_id < 0)
2933         {
2934                 PERROR("Cannot get layer(%d) id of port %d\n", nt?1:3, port);
2935                 goto closeport;
2936         }
2937         mISDNport->upper_id = mISDN_get_layerid(mISDNdevice, mISDNport->d_stid, nt?2:4); // id of uppermost layer (nt=2, te=4)
2938         if (mISDNport->upper_id < 0)
2939         {
2940                 PERROR("Cannot get layer(%d) id of port %d\n", nt?2:4, port);
2941                 goto closeport;
2942         }
2943         PDEBUG(DEBUG_ISDN, "Layer %d of port %d added.\n", nt?2:4, port);
2944
2945         /* if ntmode, establish L1 to send the tei removal during start */
2946         if (mISDNport->ntmode)
2947         {
2948                 iframe_t act;
2949                 /* L1 */
2950                 act.prim = PH_ACTIVATE | REQUEST; 
2951                 act.addr = mISDNport->upper_id | FLG_MSG_DOWN;
2952                 printf("UPPER ID 0x%x, addr 0x%x\n",mISDNport->upper_id, act.addr);
2953                 act.dinfo = 0;
2954                 act.len = 0;
2955                 mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
2956                 usleep(10000); /* to be sure, that l1 is up */
2957         }
2958
2959         /* create nst (nt-mode only) */
2960         if (nt)
2961         {
2962                 mgr = &mISDNport->mgr;
2963                 nst = &mISDNport->nst;
2964
2965                 mgr->nst = nst;
2966                 nst->manager = mgr;
2967
2968                 nst->l3_manager = stack2manager_nt; /* messages from nt-mode */
2969                 nst->device = mISDNdevice;
2970                 nst->cardnr = port;
2971                 nst->d_stid = mISDNport->d_stid;
2972
2973                 nst->feature = FEATURE_NET_HOLD;
2974                 if (ptp)
2975                         nst->feature |= FEATURE_NET_PTP;
2976                 if (pri)
2977                         nst->feature |= FEATURE_NET_CRLEN2 | FEATURE_NET_EXTCID;
2978 #if 0
2979                 i = 0;
2980                 while(i < mISDNport->b_num)
2981                 {
2982                         nst->b_stid[i] = mISDNport->b_stid[i];
2983                         i++;
2984                 }
2985 #endif
2986                 nst->l1_id = mISDNport->lower_id;
2987                 nst->l2_id = mISDNport->upper_id;
2988
2989                 /* phd */       
2990                 msg_queue_init(&nst->down_queue);
2991
2992                 Isdnl2Init(nst);
2993                 Isdnl3Init(nst);
2994         }
2995
2996         mISDNport->b_num = stinf->childcnt;
2997 #endif
2998         mISDNport->portnum = port;
2999         mISDNport->ntmode = nt;
3000         mISDNport->pri = pri;
3001         mISDNport->ptp = ptp;
3002         PDEBUG(DEBUG_ISDN, "Port has %d b-channels.\n", mISDNport->b_num);
3003         i = 0;
3004         while(i < mISDNport->b_num)
3005         {
3006                 mISDNport->b_state[i] = B_STATE_IDLE;
3007 #ifdef SOCKET_MISDN
3008                 mISDNport->b_socket = -1;
3009 #else
3010                 mISDNport->b_stid[i] = stinf->child[i];
3011                 PDEBUG(DEBUG_ISDN, "b_stid[%d] = 0x%x.\n", i, mISDNport->b_stid[i]);
3012 #endif
3013                 i++;
3014         }
3015
3016         /* if te-mode, query state link */
3017         if (!mISDNport->ntmode)
3018         {
3019                 iframe_t act;
3020                 /* L2 */
3021                 PDEBUG(DEBUG_ISDN, "sending short status request for port %d.\n", port);
3022                 act.prim = MGR_SHORTSTATUS | REQUEST; 
3023                 act.addr = mISDNport->upper_id | MSG_BROADCAST;
3024                 act.dinfo = SSTATUS_BROADCAST_BIT | SSTATUS_ALL;
3025                 act.len = 0;
3026                 mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
3027         }
3028         /* if ptp AND te-mode, pull up the link */
3029         if (mISDNport->ptp && !mISDNport->ntmode)
3030         {
3031                 iframe_t act;
3032                 /* L2 */
3033                 act.prim = DL_ESTABLISH | REQUEST; 
3034                 act.addr = (mISDNport->upper_id & ~LAYER_ID_MASK) | 4 | FLG_MSG_DOWN;
3035                 act.dinfo = 0;
3036                 act.len = 0;
3037                 mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
3038         }
3039         /* if ptp AND nt-mode, pull up the link */
3040         if (mISDNport->ptp && mISDNport->ntmode)
3041         {
3042                 msg_t *dmsg;
3043                 /* L2 */
3044                 dmsg = create_l2msg(DL_ESTABLISH | REQUEST, 0, 0);
3045                 if (mISDNport->nst.manager_l3(&mISDNport->nst, dmsg))
3046                         free_msg(dmsg);
3047         }
3048         /* initially, we assume that the link is down, exept for nt-ptmp */
3049         mISDNport->l2link = (mISDNport->ntmode && !mISDNport->ptp)?1:0;
3050
3051         PDEBUG(DEBUG_BCHANNEL, "using 'mISDN_dsp.o' module\n");
3052
3053         start_trace(mISDNport->portnum,
3054                     interface,
3055                     NULL,
3056                     NULL,
3057                     DIRECTION_NONE,
3058                     CATEGORY_CH,
3059                     0,
3060                     "PORT (open)");
3061         add_trace("channels", NULL, "%d", mISDNport->b_num);
3062         end_trace();
3063         return(mISDNport);
3064 }
3065
3066
3067 /*
3068  * function to free ALL cards (ports)
3069  */
3070 void mISDNport_close_all(void)
3071 {
3072         /* free all ports */
3073         while(mISDNport_first)
3074                 mISDNport_close(mISDNport_first);
3075 }
3076
3077 /*
3078  * free only one port
3079  */
3080 void mISDNport_close(struct mISDNport *mISDNport)
3081 {
3082         struct mISDNport **mISDNportp;
3083         class Port *port;
3084         class PmISDN *isdnport;
3085         net_stack_t *nst;
3086         unsigned char buf[32];
3087         int i;
3088
3089         /* remove all port instance that are linked to this mISDNport */
3090         port = port_first;
3091         while(port)
3092         {
3093                 if ((port->p_type&PORT_CLASS_MASK) == PORT_CLASS_mISDN)
3094                 {
3095                         isdnport = (class PmISDN *)port;
3096                         if (isdnport->p_m_mISDNport)
3097                         {
3098                                 PDEBUG(DEBUG_ISDN, "port %s uses mISDNport %d, destroying it.\n", isdnport->p_name, mISDNport->portnum);
3099                                 delete isdnport;
3100                         }
3101                 }
3102                 port = port->next;
3103         }
3104
3105         /* only if we are already part of interface */
3106         if (mISDNport->ifport)
3107         {
3108                 start_trace(mISDNport->portnum,
3109                             mISDNport->ifport->interface,
3110                             NULL,
3111                             NULL,
3112                             DIRECTION_NONE,
3113                             CATEGORY_CH,
3114                             0,
3115                             "PORT (close)");
3116                 end_trace();
3117         }
3118
3119         /* free bchannels */
3120         i = 0;
3121         while(i < mISDNport->b_num)
3122         {
3123                 if (mISDNport->b_addr[i])
3124                 {
3125                         _bchannel_destroy(mISDNport, i);
3126                         PDEBUG(DEBUG_BCHANNEL, "freeing %s port %d bchannel (index %d).\n", (mISDNport->ntmode)?"NT":"TE", mISDNport->portnum, i);
3127                 }
3128                 i++;
3129         }
3130
3131 #ifdef SOCKET_MISDN
3132         close_layer3(mISDNport->ml3);
3133 #else
3134         /* free ressources of port */
3135         msg_queue_purge(&mISDNport->downqueue);
3136
3137         /* free stacks */
3138         if (mISDNport->ntmode)
3139         {
3140                 nst = &mISDNport->nst;
3141                 if (nst->manager) /* to see if initialized */
3142                 {
3143                         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");
3144                         cleanup_Isdnl3(nst);
3145                         cleanup_Isdnl2(nst);
3146
3147                         /* phd */
3148                         msg_queue_purge(&nst->down_queue);
3149                         if (nst->phd_down_msg)
3150                                 FREE(nst->phd_down_msg, 0);
3151                 }
3152         }
3153
3154         PDEBUG(DEBUG_BCHANNEL, "freeing d-stack.\n");
3155         if (mISDNport->d_stid)
3156         {
3157                 if (mISDNport->upper_id)
3158                         mISDN_write_frame(mISDNdevice, buf, mISDNport->upper_id | FLG_MSG_DOWN, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
3159         }
3160 #endif
3161
3162         /* remove from list */
3163         mISDNportp = &mISDNport_first;
3164         while(*mISDNportp)
3165         {
3166                 if (*mISDNportp == mISDNport)
3167                 {
3168                         *mISDNportp = (*mISDNportp)->next;
3169                         mISDNportp = NULL;
3170                         break;
3171                 }
3172                 mISDNportp = &((*mISDNportp)->next);
3173         }
3174
3175         if (mISDNportp)
3176                 FATAL("mISDNport not in list\n");
3177         
3178         FREE(mISDNport, sizeof(struct mISDNport));
3179         pmemuse--;
3180
3181 }
3182
3183
3184 /*
3185  * global function to show all available isdn ports
3186  */
3187 void mISDN_port_info(void)
3188 {
3189         int ret;
3190         int i, ii, p;
3191         int useable, nt, te, pri, bri, pots;
3192         unsigned char buff[1025];
3193         iframe_t *frm = (iframe_t *)buff;
3194 #ifdef SOCKET_MISDN
3195         struct mISDN_devinfo devinfo;
3196         int socket;
3197
3198         /* open mISDN */
3199         socket = socket(PF_ISDN, SOCK_RAW, ISDN_P_BASE);
3200         if (socket < 0)
3201         {
3202                 fprintf(stderr, "Cannot open mISDN due to %s. (Does your Kernel support socket based mISDN?)\n", strerror(errno));
3203                 exit(EXIT_FAILURE);
3204         }
3205
3206         /* get number of stacks */
3207         i = 1;
3208         ret = ioctl(socket, IMGETCOUNT, &ii);
3209         if (ret < 0)
3210         {
3211                 fprintf(stderr, "Cannot get number of mISDN devices. (ioctl IMGETCOUNT failed ret=%d)\n", ret);
3212                 goto done;
3213         }
3214 #else
3215         stack_info_t *stinf;
3216         int device;
3217
3218         /* open mISDN */
3219         if ((device = mISDN_open()) < 0)
3220         {
3221                 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));
3222                 exit(EXIT_FAILURE);
3223         }
3224
3225         /* get number of stacks */
3226         i = 1;
3227         ii = mISDN_get_stack_count(device);
3228 #endif
3229         printf("\n");
3230         if (ii <= 0)
3231         {
3232                 printf("Found no card. Please be sure to load card drivers.\n");
3233                 goto done;
3234         }
3235
3236         /* loop the number of cards and get their info */
3237         while(i <= ii)
3238         {
3239                 nt = te = bri = pri = pots = 0;
3240                 useable = 0;
3241
3242 #ifdef SOCKET_MISDN
3243                 devinfo.id = i - 1;
3244                 ret = ioctl(socket, IMGETDEVINFO, &devinfo);
3245                 if (ret <= 0)
3246                 {
3247                         fprintf(stderr, "Cannot get device information for port %d. (ioctl IMGETDEVINFO failed ret=%d)\n", i, ret);
3248                         break;
3249                 }
3250
3251                 /* output the port info */
3252                 printf("Port %2d name='%s': ", i, devinfo.name);
3253                 if (devinfo.Dprotocols & (1 << ISDN_P_TE_S0))
3254                 {
3255                         bri = 1;
3256                         te = 1;
3257                 }
3258                 if (devinfo.Dprotocols & (1 << ISDN_P_NT_S0))
3259                 {
3260                         bri = 1;
3261                         nt = 1;
3262                 }
3263 #ifdef ISDN_P_TE_E1
3264                 if (devinfo.Dprotocols & (1 << ISDN_P_TE_E1))
3265                 {
3266                         pri = 1;
3267                         te = 1;
3268                 }
3269 #endif
3270 #ifdef ISDN_P_NT_E1
3271                 if (devinfo.Dprotocols & (1 << ISDN_P_NT_E1))
3272                 {
3273                         pri = 1;
3274                         nt = 1;
3275                 }
3276 #endif
3277 #ifdef ISDN_P_FXS
3278                 if (devinfo.Dprotocols & (1 << ISDN_P_FXS))
3279                 {
3280                         pots = 1;
3281                         te = 1;
3282                 }
3283 #endif
3284 #ifdef ISDN_P_FXO
3285                 if (devinfo.Dprotocols & (1 << ISDN_P_FXO))
3286                 {
3287                         pots = 1;
3288                         nt = 1;
3289                 }
3290 #endif
3291                 if ((te || nt) && (bri || pri || ports))
3292                         usable = 1;
3293
3294                 if (te && bri)
3295                         printf("TE-mode BRI S/T interface line (for phone lines)");
3296                 if (nt && bri)
3297                         printf("NT-mode BRI S/T interface port (for phones)");
3298                 if (te && pri)
3299                         printf("TE-mode PRI E1  interface line (for phone lines)");
3300                 if (nt && pri)
3301                         printf("NT-mode PRI E1  interface port (for E1 terminals)");
3302                 if (te && pots)
3303                         printf("FXS     POTS    interface port (for analog lines)");
3304                 if (nt && pots)
3305                         printf("FXO     POTS    interface port (for analog phones)");
3306                 if (ports)
3307                 {
3308                         usable = 0;
3309                         printf("\n -> Analog interfaces are not supported.");
3310                 } else
3311                 if (!usable)
3312                 {
3313                         printf("unsupported interface protocol bits 0x%016x", devinfo.Dprotocols);
3314                 }
3315                 printf("\n");
3316
3317                 printf("  - %d B-channels\n", devinfo.nfbchan);
3318 #else
3319                 ret = mISDN_get_stack_info(device, i, buff, sizeof(buff));
3320                 if (ret <= 0)
3321                 {
3322                         fprintf(stderr, "mISDN_get_stack_info() failed: port=%d error=%d\n", i, ret);
3323                         break;
3324                 }
3325                 stinf = (stack_info_t *)&frm->data.p;
3326
3327                 /* output the port info */
3328                 printf("Port %2d: ", i);
3329                 switch(stinf->pid.protocol[0] & ~ISDN_PID_FEATURE_MASK)
3330                 {
3331                         case ISDN_PID_L0_TE_S0:
3332                         useable = 1;
3333                         te = 1;
3334                         bri = 1;
3335                         printf("TE-mode BRI S/T interface line (for phone lines)");
3336                         break;
3337                         case ISDN_PID_L0_NT_S0:
3338                         useable = 1;
3339                         nt = 1;
3340                         bri = 1;
3341                         printf("NT-mode BRI S/T interface port (for phones)");
3342                         break;
3343                         case ISDN_PID_L0_TE_E1:
3344                         useable = 1;
3345                         te = 1;
3346                         pri = 1;
3347                         printf("TE-mode PRI E1  interface line (for phone lines)");
3348                         break;
3349                         case ISDN_PID_L0_NT_E1:
3350                         useable = 1;
3351                         nt = 1;
3352                         pri = 1;
3353                         printf("NT-mode PRI E1  interface port (for E1 terminals)");
3354                         break;
3355                         default:
3356                         useable = 0;
3357                         printf("unknown type 0x%08x",stinf->pid.protocol[0]);
3358                 }
3359                 printf("\n");
3360
3361                 if (nt)
3362                 {
3363                         if (stinf->pid.protocol[1] == 0)
3364                         {
3365                                 useable = 0;
3366                                 printf(" -> Missing layer 1 NT-mode protocol.\n");
3367                         }
3368                         p = 2;
3369                         while(p <= MAX_LAYER_NR) {
3370                                 if (stinf->pid.protocol[p])
3371                                 {
3372                                         useable = 0;
3373                                         printf(" -> Layer %d protocol 0x%08x is detected, port already in use by another application.\n", p, stinf->pid.protocol[p]);
3374                                 }
3375                                 p++;
3376                         }
3377                         if (useable)
3378                         {
3379                                 if (pri)
3380                                         printf(" -> Interface is Point-To-Point (PRI).\n");
3381                                 else
3382                                         printf(" -> Interface can be Poin-To-Point/Multipoint.\n");
3383                         }
3384                 }
3385                 if (te)
3386                 {
3387                         if (stinf->pid.protocol[1] == 0)
3388                         {
3389                                 useable = 0;
3390                                 printf(" -> Missing layer 1 protocol.\n");
3391                         }
3392                         if (stinf->pid.protocol[2] == 0)
3393                         {
3394                                 useable = 0;
3395                                 printf(" -> Missing layer 2 protocol.\n");
3396                         }
3397                         if (stinf->pid.protocol[2] & ISDN_PID_L2_DF_PTP)
3398                         {
3399                                 printf(" -> Interface is Poin-To-Point.\n");
3400                         }
3401                         if (stinf->pid.protocol[3] == 0)
3402                         {
3403                                 useable = 0;
3404                                 printf(" -> Missing layer 3 protocol.\n");
3405                         } else
3406                         {
3407                                 printf(" -> Protocol: ");
3408                                 switch(stinf->pid.protocol[3] & ~ISDN_PID_FEATURE_MASK)
3409                                 {
3410                                         case ISDN_PID_L3_DSS1USER:
3411                                         printf("DSS1 (Euro ISDN)");
3412                                         break;
3413
3414                                         default:
3415                                         useable = 0;
3416                                         printf("unknown protocol 0x%08x",stinf->pid.protocol[3]);
3417                                 }
3418                                 printf("\n");
3419                         }
3420                         p = 4;
3421                         while(p <= MAX_LAYER_NR) {
3422                                 if (stinf->pid.protocol[p])
3423                                 {
3424                                         useable = 0;
3425                                         printf(" -> Layer %d protocol 0x%08x is detected, port already in use by another application.\n", p, stinf->pid.protocol[p]);
3426                                 }
3427                                 p++;
3428                         }
3429                 }
3430                 printf("  - %d B-channels\n", stinf->childcnt);
3431 #endif
3432
3433                 if (!useable)
3434                         printf(" * Port NOT useable for LCR\n");
3435
3436                 printf("--------\n");
3437
3438                 i++;
3439         }
3440         printf("\n");
3441
3442 done:
3443 #ifdef SOCKET_MISDN
3444         close(sd);
3445 #else
3446         /* close mISDN */
3447         if ((ret = mISDN_close(device)))
3448                 FATAL("mISDN_close() failed: err=%d '%s'\n", ret, strerror(ret));
3449 #endif
3450 }
3451
3452
3453 /*
3454  * enque data from upper buffer
3455  */
3456 void PmISDN::txfromup(unsigned char *data, int length)
3457 {
3458 #ifdef SOCKET_MISDN
3459         unsigned char buf[MISDN_HEADER_LEN+((length>ISDN_LOAD)?length:ISDN_LOAD)];
3460         struct mISDNhead *frm = (struct mISDNhead *)buf;
3461
3462         if (p_m_b_index < 0)
3463                 return;
3464         if (!p_m_mISDNport->b_socket[p_m_b_index])
3465                 return;
3466 #else
3467         unsigned char buf[mISDN_HEADER_LEN+((length>ISDN_LOAD)?length:ISDN_LOAD)];
3468         iframe_t *frm = (iframe_t *)buf;
3469
3470         if (p_m_b_index < 0)
3471                 return;
3472         if (!p_m_mISDNport->b_addr[p_m_b_index])
3473                 return;
3474 #endif
3475
3476         /* check if high priority tones exist
3477          * ignore data in this case
3478          */
3479         if (p_tone_name[0] || p_m_crypt_msg_loops)
3480                 return;
3481
3482         /* preload procedure
3483          * if transmit buffer in DSP module is empty,
3484          * preload it to DSP_LOAD to prevent jitter gaps.
3485          */
3486         if (p_m_load==0 && ISDN_LOAD>0)
3487         {
3488
3489                 memcpy(buf+mISDN_HEADER_LEN, data, ISDN_LOAD);
3490                 frm->len = ISDN_LOAD;
3491                 mISDN_write(mISDNdevice, frm, mISDN_HEADER_LEN+frm->len, TIMEOUT_1SEC);
3492                 p_m_load += frm->len;
3493         }
3494
3495         /* drop if load would exceed ISDN_MAXLOAD
3496          * this keeps the delay not too high
3497          */
3498         if (p_m_load+length > ISDN_MAXLOAD)
3499                 return;
3500
3501         /* make and send frame */
3502 #ifdef SOCKET_MISDN
3503         frm->prim = DL_DATA_REQ;
3504         frm->id = 0;
3505         memcpy(buf+MISDN_HEADER_LEN, data, length);
3506         ret = sendto(p_m_mISDNport->b_socket[p_m_b_index], buf, MISDN_HEADER_LEN+length, 0, NULL, 0);
3507         if (!ret)
3508                 PERROR("Failed to send to socket %d\n", handle);
3509 #else
3510         frm->prim = DL_DATA | REQUEST; 
3511         frm->addr = p_m_mISDNport->b_addr[p_m_b_index] | FLG_MSG_DOWN;
3512         frm->dinfo = 0;
3513         frm->len = length;
3514         memcpy(buf+mISDN_HEADER_LEN, data, length);
3515         mISDN_write(mISDNdevice, frm, mISDN_HEADER_LEN+frm->len, TIMEOUT_1SEC);
3516 #endif
3517         p_m_load += length;
3518 }
3519