b866b69ed6bf0be05cfbd2dd8240183fbdb53d05
[lcr.git] / bchannel.c
1 /*****************************************************************************\
2 **                                                                           **
3 ** Linux Call Router                                                         **
4 **                                                                           **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg                                              **
7 **                                                                           **
8 ** mISDN channel handlin for remote application                              **
9 **                                                                           **
10 \*****************************************************************************/ 
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <unistd.h>
15 #include <string.h>
16 #include <poll.h>
17 #include <errno.h>
18 #include <sys/ioctl.h>
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include <fcntl.h>
22 #ifdef SOCKET_MISDN
23 #include <netinet/udp.h>
24 #include <netinet/in.h>
25 #include <netdb.h>
26 #include <sys/socket.h>
27 #include <mISDNif.h>
28 #else
29 #include <mISDNuser/isdn_net.h>
30 #include <mISDNuser/net_l3.h>
31 #endif
32
33 #include <asterisk/frame.h>
34
35
36 #include "extension.h"
37 #include "message.h"
38 #include "lcrsocket.h"
39 #include "cause.h"
40 #include "bchannel.h"
41 #include "chan_lcr.h"
42 #include "callerid.h"
43
44
45 #ifndef ISDN_PID_L4_B_USER
46 #define ISDN_PID_L4_B_USER 0x440000ff
47 #endif
48
49 pid_t   bchannel_pid;
50
51 enum {
52         BSTATE_IDLE,
53         BSTATE_ACTIVATING,
54         BSTATE_ACTIVE,
55 };
56
57 #ifdef SOCKET_MISDN
58
59 int bchannel_initialize(void)
60 {
61         return(0);
62 }
63
64 void bchannel_deinitialize(void)
65 {
66 }
67 #else
68 int bchannel_entity = 0; /* used for udevice */
69 int bchannel_device = -1; /* the device handler and port list */
70
71 int bchannel_initialize(void)
72 {
73         unsigned char buff[1025];
74         iframe_t *frm = (iframe_t *)buff;
75         int ret;
76
77         /* open mISDNdevice if not already open */
78         if (bchannel_device < 0)
79         {
80                 ret = mISDN_open();
81                 if (ret < 0)
82                 {
83                         CERROR(NULL, NULL, "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));
84                         return(-1);
85                 }
86                 bchannel_device = ret;
87                 CDEBUG(NULL, NULL, "mISDN device opened.\n");
88
89                 /* create entity for layer 3 TE-mode */
90                 mISDN_write_frame(bchannel_device, buff, 0, MGR_NEWENTITY | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
91                 ret = mISDN_read_frame(bchannel_device, frm, sizeof(iframe_t), 0, MGR_NEWENTITY | CONFIRM, TIMEOUT_1SEC);
92                 if (ret < (int)mISDN_HEADER_LEN)
93                 {
94                         noentity:
95                         CERROR(NULL, NULL, "Cannot request MGR_NEWENTITY from mISDN. Exitting due to software bug.");
96                         return(-1);
97                 }
98                 bchannel_entity = frm->dinfo & 0xffff;
99                 if (!bchannel_entity)
100                         goto noentity;
101         }
102         return(0);
103 }
104
105 void bchannel_deinitialize(void)
106 {
107         unsigned char buff[1025];
108
109         if (bchannel_device >= 0)
110         {
111                 /* free entity */
112                 mISDN_write_frame(bchannel_device, buff, 0, MGR_DELENTITY | REQUEST, bchannel_entity, 0, NULL, TIMEOUT_1SEC);
113                 /* close device */
114                 mISDN_close(bchannel_device);
115                 bchannel_device = -1;
116         }
117 }
118 #endif
119
120 /*
121  * send control information to the channel (dsp-module)
122  */
123 static void ph_control(unsigned long handle, unsigned long c1, unsigned long c2, char *trace_name, int trace_value)
124 {
125 #ifdef SOCKET_MISDN
126         unsigned char buffer[MISDN_HEADER_LEN+sizeof(int)+sizeof(int)];
127         struct mISDNhead *ctrl = (struct mISDNhead *)buffer;
128         unsigned long *d = (unsigned long *)(buffer+MISDN_HEADER_LEN);
129         int ret;
130
131         ctrl->prim = PH_CONTROL_REQ;
132         ctrl->id = 0;
133         *d++ = c1;
134         *d++ = c2;
135         ret = sendto(handle, buffer, MISDN_HEADER_LEN+sizeof(int)*2, 0, NULL, 0);
136         if (!ret)
137                 CERROR(NULL, NULL, "Failed to send to socket %d\n", handle);
138 #else
139         unsigned char buffer[mISDN_HEADER_LEN+sizeof(int)+sizeof(int)];
140         iframe_t *ctrl = (iframe_t *)buffer; 
141         unsigned long *d = (unsigned long *)&ctrl->data.p;
142
143         ctrl->prim = PH_CONTROL | REQUEST;
144         ctrl->addr = handle | FLG_MSG_DOWN;
145         ctrl->dinfo = 0;
146         ctrl->len = sizeof(int)*2;
147         *d++ = c1;
148         *d++ = c2;
149         mISDN_write(bchannel_device, ctrl, mISDN_HEADER_LEN+ctrl->len, TIMEOUT_1SEC);
150 #endif
151 #if 0
152         chan_trace_header(mISDNport, isdnport, "BCHANNEL control", DIRECTION_OUT);
153         if (c1 == CMX_CONF_JOIN)
154                 add_trace(trace_name, NULL, "0x%08x", trace_value);
155         else
156                 add_trace(trace_name, NULL, "%d", trace_value);
157         end_trace();
158 #endif
159 }
160
161 static void ph_control_block(unsigned long handle, unsigned long c1, void *c2, int c2_len, char *trace_name, int trace_value)
162 {
163 #ifdef SOCKET_MISDN
164         unsigned char buffer[MISDN_HEADER_LEN+sizeof(int)+c2_len];
165         struct mISDNhead *ctrl = (struct mISDNhead *)buffer;
166         unsigned long *d = (unsigned long *)(buffer+MISDN_HEADER_LEN);
167         int ret;
168
169         ctrl->prim = PH_CONTROL_REQ;
170         ctrl->id = 0;
171         *d++ = c1;
172         memcpy(d, c2, c2_len);
173         ret = sendto(handle, buffer, MISDN_HEADER_LEN+sizeof(int)+c2_len, 0, NULL, 0);
174         if (!ret)
175                 CERROR(NULL, NULL, "Failed to send to socket %d\n", handle);
176 #else
177         unsigned char buffer[mISDN_HEADER_LEN+sizeof(int)+c2_len];
178         iframe_t *ctrl = (iframe_t *)buffer;
179         unsigned long *d = (unsigned long *)&ctrl->data.p;
180
181         ctrl->prim = PH_CONTROL | REQUEST;
182         ctrl->addr = handle | FLG_MSG_DOWN;
183         ctrl->dinfo = 0;
184         ctrl->len = sizeof(int)+c2_len;
185         *d++ = c1;
186         memcpy(d, c2, c2_len);
187         mISDN_write(bchannel_device, ctrl, mISDN_HEADER_LEN+ctrl->len, TIMEOUT_1SEC);
188 #endif
189 #if 0
190         chan_trace_header(mISDNport, isdnport, "BCHANNEL control", DIRECTION_OUT);
191         add_trace(trace_name, NULL, "%d", trace_value);
192         end_trace();
193 #endif
194 }
195
196
197 /*
198  * create stack
199  */
200 int bchannel_create(struct bchannel *bchannel)
201 {
202         int ret;
203 #ifdef SOCKET_MISDN
204         unsigned long on = 1;
205         struct sockaddr_mISDN addr;
206
207         if (bchannel->b_sock)
208         {
209                 CERROR(NULL, NULL, "Socket already created for handle 0x%x\n", bchannel->handle);
210                 return(0);
211         }
212
213         /* open socket */
214         bchannel->b_sock = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_B_L2DSP);
215         if (bchannel->b_sock < 0)
216         {
217                 CERROR(NULL, NULL, "Failed to open bchannel-socket for handle 0x%x with mISDN-DSP layer. Did you load mISDNdsp.ko?\n", bchannel->handle);
218                 return(0);
219         }
220         
221         /* set nonblocking io */
222         ret = ioctl(bchannel->b_sock, FIONBIO, &on);
223         if (ret < 0)
224         {
225                 CERROR(NULL, NULL, "Failed to set bchannel-socket handle 0x%x into nonblocking IO\n", bchannel->handle);
226                 close(bchannel->b_sock);
227                 bchannel->b_sock = -1;
228                 return(0);
229         }
230
231         /* bind socket to bchannel */
232         addr.family = AF_ISDN;
233         addr.dev = (bchannel->handle>>8)-1;
234         addr.channel = bchannel->handle && 0xff;
235         ret = bind(bchannel->b_sock, (struct sockaddr *)&addr, sizeof(addr));
236         if (ret < 0)
237         {
238                 CERROR(NULL, NULL, "Failed to bind bchannel-socket for handle 0x%x with mISDN-DSP layer. Did you load mISDNdsp.ko?\n", bchannel->handle);
239                 close(bchannel->b_sock);
240                 bchannel->b_sock = -1;
241                 return(0);
242         }
243
244 #if 0
245         chan_trace_header(mISDNport, mISDNport->b_port[i], "BCHANNEL create socket", DIRECTION_OUT);
246         add_trace("channel", NULL, "%d", i+1+(i>=15));
247         add_trace("socket", NULL, "%d", mISDNport->b_socket[i]);
248         end_trace();
249 #endif
250         return(1);
251 }
252 #else
253         unsigned char buff[1024];
254         layer_info_t li;
255         mISDN_pid_t pid;
256
257         if (bchannel->b_stid)
258         {
259                 CERROR(NULL, NULL, "Stack already created for address 0x%lx\n", bchannel->b_stid);
260                 return(0);
261         }
262
263         if (bchannel->b_addr)
264         {
265                 CERROR(NULL, NULL, "Stack already created for address 0x%lx\n", bchannel->b_addr);
266                 return(0);
267         }
268
269         /* create new layer */
270         CDEBUG(NULL, NULL, "creating new layer for stid 0x%lx.\n" , bchannel->handle);
271         memset(&li, 0, sizeof(li));
272         memset(&pid, 0, sizeof(pid));
273         li.object_id = -1;
274         li.extentions = 0;
275         li.st = bchannel->handle;
276         strcpy(li.name, "B L4");
277         li.pid.layermask = ISDN_LAYER((4));
278         li.pid.protocol[4] = ISDN_PID_L4_B_USER;
279         ret = mISDN_new_layer(bchannel_device, &li);
280         if (ret)
281         {
282                 failed_new_layer:
283                 CERROR(NULL, NULL, "mISDN_new_layer() failed to add bchannel for stid 0x%lx.\n", bchannel->handle);
284                 goto failed;
285         }
286         if (!li.id)
287         {
288                 goto failed_new_layer;
289         }
290         bchannel->b_stid = bchannel->handle;
291         bchannel->b_addr = li.id;
292         CDEBUG(NULL, NULL, "new layer (b_addr=0x%x)\n", bchannel->b_addr);
293
294         /* create new stack */
295         pid.protocol[1] = ISDN_PID_L1_B_64TRANS;
296         pid.protocol[2] = ISDN_PID_L2_B_TRANS;
297         pid.protocol[3] = ISDN_PID_L3_B_DSP;
298         pid.protocol[4] = ISDN_PID_L4_B_USER;
299         pid.layermask = ISDN_LAYER((1)) | ISDN_LAYER((2)) | ISDN_LAYER((3)) | ISDN_LAYER((4));
300         ret = mISDN_set_stack(bchannel_device, bchannel->b_stid, &pid);
301         if (ret)
302         {
303                 stack_error:
304                 CERROR(NULL, NULL, "mISDN_set_stack() failed (ret=%d) to add bchannel stid=0x%lx\n", ret, bchannel->b_stid);
305                 mISDN_write_frame(bchannel_device, buff, bchannel->b_addr, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
306                 goto failed;
307         }
308         ret = mISDN_get_setstack_ind(bchannel_device, bchannel->b_addr);
309         if (ret)
310                 goto stack_error;
311
312         /* get layer id */
313         bchannel->b_addr = mISDN_get_layerid(bchannel_device, bchannel->b_stid, 4);
314         if (!bchannel->b_addr)
315                 goto stack_error;
316 #if 0
317         chan_trace_header(mISDNport, mISDNport->b_port[i], "BCHANNEL create stack", DIRECTION_OUT);
318         add_trace("channel", NULL, "%d", i+1+(i>=15));
319         add_trace("stack", "id", "0x%08x", mISDNport->b_stid[i]);
320         add_trace("stack", "address", "0x%08x", mISDNport->b_addr[i]);
321         end_trace();
322 #endif
323
324         return(1);
325
326 failed:
327         bchannel->b_stid = 0;
328         bchannel->b_addr = 0;
329         return(0);
330 }
331 #endif
332
333
334 /*
335  * activate / deactivate request
336  */
337 void bchannel_activate(struct bchannel *bchannel, int activate)
338 {
339 #ifdef SOCKET_MISDN
340         struct mISDNhead act;
341         int ret;
342
343         act.prim = (activate)?DL_ESTABLISH_REQ:DL_RELEASE_REQ; 
344         act.id = 0;
345         ret = sendto(bchannel->b_sock, &act, MISDN_HEADER_LEN, 0, NULL, 0);
346         if (!ret)
347                 CERROR(NULL, NULL, "Failed to send to socket %d\n", bchannel->b_sock);
348 #else
349         iframe_t act;
350
351         /* activate bchannel */
352         act.prim = (activate?DL_ESTABLISH:DL_RELEASE) | REQUEST; 
353         act.addr = bchannel->b_addr | FLG_MSG_DOWN;
354         act.dinfo = 0;
355         act.len = 0;
356         mISDN_write(bchannel_device, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
357 #endif
358
359         bchannel->b_state = BSTATE_ACTIVATING;
360 #if 0
361         /* trace */
362         chan_trace_header(mISDNport, mISDNport->b_port[i], activate?(char*)"BCHANNEL activate":(char*)"BCHANNEL deactivate", DIRECTION_OUT);
363         add_trace("channel", NULL, "%d", i+1+(i>=15));
364         end_trace();
365 #endif
366 }
367
368
369 /*
370  * set features
371  */
372 static void bchannel_activated(struct bchannel *bchannel)
373 {
374 #ifdef SOCKET_MISDN
375         int handle;
376
377         handle = bchannel->b_sock;
378 #else
379         unsigned long handle;
380
381         handle = bchannel->b_addr;
382 #endif
383
384         /* set dsp features */
385         if (bchannel->b_txdata)
386                 ph_control(handle, (bchannel->b_txdata)?DSP_TXDATA_ON:DSP_TXDATA_OFF, 0, "DSP-TXDATA", bchannel->b_txdata);
387         if (bchannel->b_delay)
388                 ph_control(handle, DSP_DELAY, bchannel->b_delay, "DSP-DELAY", bchannel->b_delay);
389         if (bchannel->b_tx_dejitter)
390                 ph_control(handle, (bchannel->b_tx_dejitter)?DSP_TX_DEJITTER:DSP_TX_DEJ_OFF, 0, "DSP-TX_DEJITTER", bchannel->b_tx_dejitter);
391         if (bchannel->b_tx_gain)
392                 ph_control(handle, DSP_VOL_CHANGE_TX, bchannel->b_tx_gain, "DSP-TX_GAIN", bchannel->b_tx_gain);
393         if (bchannel->b_rx_gain)
394                 ph_control(handle, DSP_VOL_CHANGE_RX, bchannel->b_rx_gain, "DSP-RX_GAIN", bchannel->b_rx_gain);
395         if (bchannel->b_pipeline[0])
396 #ifdef SOCKET_MISDN
397                 ph_control_block(handle, DSP_PIPELINE_CFG, bchannel->b_pipeline, strlen(bchannel->b_pipeline)+1, "DSP-PIPELINE", 0);
398 #else
399                 ph_control_block(handle, PIPELINE_CFG, bchannel->b_pipeline, strlen(bchannel->b_pipeline)+1, "DSP-PIPELINE", 0);
400 #endif
401         if (bchannel->b_conf)
402                 ph_control(handle, DSP_CONF_JOIN, bchannel->b_conf, "DSP-CONF", bchannel->b_conf);
403         if (bchannel->b_echo)
404                 ph_control(handle, DSP_ECHO_ON, 0, "DSP-ECHO", 1);
405         if (bchannel->b_tone)
406                 ph_control(handle, DSP_TONE_PATT_ON, bchannel->b_tone, "DSP-TONE", bchannel->b_tone);
407         if (bchannel->b_rxoff)
408                 ph_control(handle, DSP_RECEIVE_OFF, 0, "DSP-RXOFF", 1);
409 //      if (bchannel->b_txmix)
410 //              ph_control(handle, DSP_MIX_ON, 0, "DSP-MIX", 1);
411         if (bchannel->b_dtmf)
412                 ph_control(handle, DTMF_TONE_START, 0, "DSP-DTMF", 1);
413         if (bchannel->b_crypt_len)
414                 ph_control_block(handle, DSP_BF_ENABLE_KEY, bchannel->b_crypt_key, bchannel->b_crypt_len, "DSP-CRYPT", bchannel->b_crypt_len);
415         if (bchannel->b_conf)
416                 ph_control(handle, DSP_CONF_JOIN, bchannel->b_conf, "DSP-CONF", bchannel->b_conf);
417
418         bchannel->b_state = BSTATE_ACTIVE;
419 }
420
421 /*
422  * destroy stack
423  */
424 static void bchannel_destroy(struct bchannel *bchannel)
425 {
426 #ifdef SOCKET_MISDN
427 #if 0
428         chan_trace_header(mISDNport, mISDNport->b_port[i], "BCHANNEL remove socket", DIRECTION_OUT);
429         add_trace("channel", NULL, "%d", i+1+(i>=15));
430         add_trace("socket", NULL, "%d", mISDNport->b_socket[i]);
431         end_trace();
432 #endif
433         if (bchannel->b_sock > -1)
434         {
435                 close(bchannel->b_sock);
436                 bchannel->b_sock = -1;
437         }
438 #else
439         unsigned char buff[1024];
440
441 #if 0
442         chan_trace_header(mISDNport, mISDNport->b_port[i], "BCHANNEL remove stack", DIRECTION_OUT);
443         add_trace("channel", NULL, "%d", i+1+(i>=15));
444         add_trace("stack", "id", "0x%08x", mISDNport->b_stid[i]);
445         add_trace("stack", "address", "0x%08x", mISDNport->b_addr[i]);
446         end_trace();
447 #endif
448         /* remove our stack only if set */
449         if (bchannel->b_addr)
450         {
451                 CDEBUG(NULL, NULL, "free stack (b_addr=0x%x)\n", bchannel->b_addr);
452                 mISDN_clear_stack(bchannel_device, bchannel->b_stid);
453                 mISDN_write_frame(bchannel_device, buff, bchannel->b_addr | FLG_MSG_DOWN, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
454                 bchannel->b_stid = 0;
455                 bchannel->b_addr = 0;
456         }
457 #endif
458         bchannel->b_state = BSTATE_IDLE;
459 }
460
461
462 /*
463  * whenever we get audio data from bchannel, we process it here
464  */
465 static void bchannel_receive(struct bchannel *bchannel, unsigned long prim, unsigned long dinfo, unsigned char *data, int len)
466 {
467         unsigned long cont = *((unsigned long *)data);
468 //      unsigned char *data_temp;
469 //      unsigned long length_temp;
470 //      unsigned char *p;
471 //      int l;
472
473 #ifdef SOCKET_MISDN
474         if (prim == PH_CONTROL_IND)
475 #else
476         if (prim == (PH_CONTROL | INDICATION))
477 #endif
478         {
479                 if (len < 4)
480                 {
481                         CERROR(NULL, NULL, "SHORT READ OF PH_CONTROL INDICATION\n");
482                         return;
483                 }
484                 if ((cont&(~DTMF_TONE_MASK)) == DTMF_TONE_VAL)
485                 {
486 #if 0
487                         chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
488                         add_trace("DTMF", NULL, "%c", cont & DTMF_TONE_MASK);
489                         end_trace();
490 #endif
491                         if (bchannel->rx_dtmf)
492                                 bchannel->rx_dtmf(bchannel, cont & DTMF_TONE_MASK);
493                         return;
494                 }
495                 switch(cont)
496                 {
497 #ifdef SOCKET_MISDN
498                         case DSP_BF_REJECT:
499 #else
500                         case BF_REJECT:
501 #endif
502 #if 0
503                         chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
504                         add_trace("DSP-CRYPT", NULL, "error");
505                         end_trace();
506 #endif
507                         break;
508
509 #ifdef SOCKET_MISDN
510                         case DSP_BF_ACCEPT:
511 #else
512                         case BF_ACCEPT:
513 #endif
514 #if 0
515                         chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
516                         add_trace("DSP-CRYPT", NULL, "ok");
517                         end_trace();
518 #endif
519                         break;
520
521                         default:
522 #if 0
523                         chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
524                         add_trace("unknown", NULL, "0x%x", cont);
525                         end_trace();
526 #else
527                         ;
528 #endif
529                 }
530                 return;
531         }
532 #ifdef SOCKET_MISDN
533         if (prim == PH_DATA_REQ)
534         {
535                 if (!bchannel->b_txdata)
536                 {
537                         /* if tx is off, it may happen that fifos send us pending informations, we just ignore them */
538                         CDEBUG(NULL, NULL, "ignoring tx data, because 'txdata' is turned off\n");
539                         return;
540                 }
541                 return;
542         }
543 #else
544         if (prim == (PH_SIGNAL | INDICATION))
545         {
546                 switch(dinfo)
547                 {
548                         case CMX_TX_DATA:
549                         if (!bchannel->b_txdata)
550                         {
551                                 /* if tx is off, it may happen that fifos send us pending informations, we just ignore them */
552                                 CDEBUG(NULL, NULL, "ignoring tx data, because 'txdata' is turned off\n");
553                                 return;
554                         }
555                         break;
556
557                         default:
558 #if 0
559                         chan_trace_header(p_m_mISDNport, this, "BCHANNEL signal", DIRECTION_IN);
560                         add_trace("unknown", NULL, "0x%x", frm->dinfo);
561                         end_trace();
562 #else
563                         ;
564 #endif
565                 }
566                 return;
567         }
568 #endif
569         if (prim != PH_DATA_IND && prim != DL_DATA_IND)
570         {
571                 CERROR(NULL, NULL, "Bchannel received unknown primitve: 0x%lx\n", prim);
572                 return;
573         }
574         /* calls will not process any audio data unless
575          * the call is connected OR interface features audio during call setup.
576          */
577
578         /* if rx is off, it may happen that fifos send us pending informations, we just ignore them */
579         if (bchannel->b_rxoff)
580         {
581                 CDEBUG(NULL, NULL, "ignoring data, because rx is turned off\n");
582                 return;
583         }
584
585         if (!bchannel->call)
586         {
587                 CDEBUG(NULL, NULL, "ignoring data, because no call associated with bchannel\n");
588                 return;
589         }
590         if (!bchannel->call->audiopath)
591         {
592                 /* return, because we have no audio from port */
593                 return;
594         }
595         len = write(bchannel->call->pipe[1], data, len);
596         if (len < 0)
597         {
598                 CDEBUG(NULL, NULL, "broken pipe on bchannel pipe\n");
599                 return;
600         }
601 }
602
603
604 /*
605  * transmit data to bchannel
606  */
607 void bchannel_transmit(struct bchannel *bchannel, unsigned char *data, int len)
608 {
609         unsigned char buff[1025];
610 #ifdef SOCKET_MISDN
611         struct mISDNhead *frm = (struct mISDNhead *)buff;
612 #else
613         iframe_t *frm = (iframe_t *)buff;
614 #endif
615         int ret;
616
617         if (bchannel->b_state != BSTATE_ACTIVE)
618                 return;
619 #ifdef SOCKET_MISDN
620         frm->prim = DL_DATA_REQ;
621         frm->id = 0;
622         ret = sendto(bchannel->b_sock, data, len, 0, NULL, 0);
623         if (!ret)
624                 CERROR(NULL, NULL, "Failed to send to socket %d\n", bchannel->b_sock);
625 #else
626         frm->prim = DL_DATA | REQUEST; 
627         frm->addr = bchannel->b_addr | FLG_MSG_DOWN;
628         frm->dinfo = 0;
629         frm->len = len;
630         if (frm->len)
631                 mISDN_write(bchannel_device, frm, mISDN_HEADER_LEN+frm->len, TIMEOUT_1SEC);
632 #endif
633 }
634
635
636 /*
637  * join bchannel
638  */
639 void bchannel_join(struct bchannel *bchannel, unsigned short id)
640 {
641 #ifdef SOCKET_MISDN
642         int handle;
643
644         handle = bchannel->b_sock;
645 #else
646         unsigned long handle;
647
648         handle = bchannel->b_addr;
649 #endif
650         if (id) {
651                 bchannel->b_conf = (id<<16) + bchannel_pid;
652                 bchannel->b_rxoff = 1;
653         } else {
654                 bchannel->b_conf = 0;
655                 bchannel->b_rxoff = 0;
656         }
657         if (bchannel->b_state == BSTATE_ACTIVE)
658         {
659                 ph_control(handle, DSP_RECEIVE_OFF, bchannel->b_rxoff, "DSP-RX_OFF", bchannel->b_conf);
660                 ph_control(handle, DSP_CONF_JOIN, bchannel->b_conf, "DSP-CONF", bchannel->b_conf);
661         }
662 }
663
664
665 /*
666  * main loop for processing messages from mISDN
667  */
668 #ifdef SOCKET_MISDN
669 int bchannel_handle(void)
670 {
671         int ret, work = 0;
672         struct bchannel *bchannel;
673         char buffer[2048+MISDN_HEADER_LEN];
674         struct mISDNhead *hh = (struct mISDNhead *)buffer;
675
676         /* process all bchannels */
677         bchannel = bchannel_first;
678         while(bchannel)
679         {
680                 /* handle message from bchannel */
681                 if (bchannel->b_sock > -1)
682                 {
683                         ret = recv(bchannel->b_sock, buffer, sizeof(buffer), 0);
684                         if (ret >= MISDN_HEADER_LEN)
685                         {
686                                 work = 1;
687                                 switch(hh->prim)
688                                 {
689                                         /* we don't care about confirms, we use rx data to sync tx */
690                                         case PH_DATA_CNF:
691                                         break;
692
693                                         /* we receive audio data, we respond to it AND we send tones */
694                                         case PH_DATA_IND:
695                                         case PH_DATA_REQ:
696                                         case DL_DATA_IND:
697                                         case PH_CONTROL_IND:
698                                         bchannel_receive(bchannel, hh->prim, hh->id, buffer+MISDN_HEADER_LEN, ret-MISDN_HEADER_LEN);
699                                         break;
700
701                                         case PH_ACTIVATE_IND:
702                                         case DL_ESTABLISH_IND:
703                                         case PH_ACTIVATE_CNF:
704                                         case DL_ESTABLISH_CNF:
705                                         CDEBUG(NULL, NULL, "DL_ESTABLISH confirm: bchannel is now activated (socket %d).\n", bchannel->b_sock);
706                                         bchannel_activated(bchannel);
707                                         break;
708
709                                         case PH_DEACTIVATE_IND:
710                                         case DL_RELEASE_IND:
711                                         case PH_DEACTIVATE_CNF:
712                                         case DL_RELEASE_CNF:
713                                         CDEBUG(NULL, NULL, "DL_RELEASE confirm: bchannel is now de-activated (socket %d).\n", bchannel->b_sock);
714 //                                      bchannel_deactivated(bchannel);
715                                         break;
716
717                                         default:
718                                         CERROR(NULL, NULL, "child message not handled: prim(0x%x) socket(%d) data len(%d)\n", hh->prim, bchannel->b_sock, ret - MISDN_HEADER_LEN);
719                                 }
720                         } else
721                         {
722                                 if (ret < 0 && errno != EWOULDBLOCK)
723                                         CERROR(NULL, NULL, "Read from socket %d failed with return code %d\n", bchannel->b_sock, ret);
724                         }
725                 }
726                 bchannel = bchannel->next;
727         }
728
729         /* if we received at least one b-frame, we will return 1 */
730         return(work);
731 }
732 #else
733 int bchannel_handle(void)
734 {
735         struct bchannel *bchannel;
736         iframe_t *frm;
737         unsigned char buffer[2048];
738         int len;
739
740         /* no device, no read */
741         if (bchannel_device < 0)
742                 return(0);
743
744         /* get message from kernel */
745         len = mISDN_read(bchannel_device, buffer, sizeof(buffer), 0);
746         if (len < 0)
747         {
748                 if (errno == EAGAIN)
749                         return(0);
750                 CERROR(NULL, NULL, "Failed to do mISDN_read()\n");
751                 return(0);
752         }
753         if (!len)
754         {
755 //              printf("%s: ERROR: mISDN_read() returns nothing\n");
756                 return(0);
757         }
758         frm = (iframe_t *)buffer;
759
760         /* global prim */
761         switch(frm->prim)
762         {
763                 case MGR_DELLAYER | CONFIRM:
764                 case MGR_INITTIMER | CONFIRM:
765                 case MGR_ADDTIMER | CONFIRM:
766                 case MGR_DELTIMER | CONFIRM:
767                 case MGR_REMOVETIMER | CONFIRM:
768                 return(1);
769         }
770
771         /* find the mISDNport that belongs to the stack */
772         bchannel = bchannel_first;
773         while(bchannel)
774         {
775                 if (frm->addr == bchannel->b_addr)
776                         break;
777                 bchannel = bchannel->next;
778         } 
779         if (!bchannel)
780         {
781                 CERROR(NULL, NULL, "message belongs to no bchannel: prim(0x%x) addr(0x%x) msg->len(%d)\n", frm->prim, frm->addr, len);
782                 goto out;
783         }
784
785         /* b-message */
786         switch(frm->prim)
787         {
788                 /* we don't care about confirms, we use rx data to sync tx */
789                 case PH_DATA | CONFIRM:
790                 case DL_DATA | CONFIRM:
791                 break;
792
793                 /* we receive audio data, we respond to it AND we send tones */
794                 case PH_DATA | INDICATION:
795                 case DL_DATA | INDICATION:
796                 case PH_CONTROL | INDICATION:
797                 case PH_SIGNAL | INDICATION:
798                 bchannel_receive(bchannel, frm->prim, frm->dinfo, (unsigned char *)frm->data.p, frm->len);
799                 break;
800
801                 case PH_ACTIVATE | INDICATION:
802                 case DL_ESTABLISH | INDICATION:
803                 case PH_ACTIVATE | CONFIRM:
804                 case DL_ESTABLISH | CONFIRM:
805                 CDEBUG(NULL, NULL, "DL_ESTABLISH confirm: bchannel is now activated (address 0x%x).\n", frm->addr);
806                 bchannel_activated(bchannel);
807                 break;
808
809                 case PH_DEACTIVATE | INDICATION:
810                 case DL_RELEASE | INDICATION:
811                 case PH_DEACTIVATE | CONFIRM:
812                 case DL_RELEASE | CONFIRM:
813                 CDEBUG(NULL, NULL, "DL_RELEASE confirm: bchannel is now de-activated (address 0x%x).\n", frm->addr);
814 //              bchannel_deactivated(bchannel);
815                 break;
816
817                 default:
818                 CERROR(NULL, NULL, "message not handled: prim(0x%x) addr(0x%x) msg->len(%d)\n", frm->prim, frm->addr, len);
819         }
820
821         out:
822         return(1);
823 }
824 #endif
825
826
827 /*
828  * bchannel channel handling
829  */
830 struct bchannel *bchannel_first = NULL;
831 struct bchannel *find_bchannel_handle(unsigned long handle)
832 {
833         struct bchannel *bchannel = bchannel_first;
834
835         while(bchannel)
836         {
837                 if (bchannel->handle == handle)
838                         break;
839                 bchannel = bchannel->next;
840         }
841         return(bchannel);
842 }
843
844 #if 0
845 struct bchannel *find_bchannel_ref(unsigned long ref)
846 {
847         struct bchannel *bchannel = bchannel_first;
848
849         while(bchannel)
850         {
851                 if (bchannel->ref == ref)
852                         break;
853                 bchannel = bchannel->next;
854         }
855         return(bchannel);
856 }
857 #endif
858
859 struct bchannel *alloc_bchannel(unsigned long handle)
860 {
861         struct bchannel **bchannelp = &bchannel_first;
862
863         while(*bchannelp)
864                 bchannelp = &((*bchannelp)->next);
865
866         *bchannelp = (struct bchannel *)malloc(sizeof(struct bchannel));
867         if (!*bchannelp)
868                 return(NULL);
869         (*bchannelp)->handle = handle;
870         (*bchannelp)->b_state = BSTATE_IDLE;
871                 
872         return(*bchannelp);
873 }
874
875 void free_bchannel(struct bchannel *bchannel)
876 {
877         struct bchannel **temp = &bchannel_first;
878
879         while(*temp)
880         {
881                 if (*temp == bchannel)
882                 {
883                         *temp = (*temp)->next;
884 #ifdef SOCKET_MISDN
885                         if (bchannel->b_sock > -1)
886 #else
887                         if (bchannel->b_stid)
888 #endif
889                                 bchannel_destroy(bchannel);
890                         if (bchannel->call)
891                         {
892                                 if (bchannel->call->bchannel)
893                                         bchannel->call->bchannel = NULL;
894                         }
895                         free(bchannel);
896                         return;
897                 }
898                 temp = &((*temp)->next);
899         }
900 }
901
902