2adec861c6915537b5ef2909de3992ac15400c40
[lcr.git] / channel.c
1 /*****************************************************************************\
2 **                                                                           **
3 ** Linux Call Router                                                         **
4 **                                                                           **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg                                              **
7 **                                                                           **
8 ** mISDN bchannel access (for Asterisk)                                      **
9 **                                                                           **
10 \*****************************************************************************/ 
11
12
13 #include <stdio.h>
14 #include <string.h>
15 #include <stdlib.h>
16 #include "main.h"
17 #include <unistd.h>
18 #include <poll.h>
19 #include <errno.h>
20 #include <sys/ioctl.h>
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <fcntl.h>
24 extern "C" {
25 #include <net_l2.h>
26 }
27
28 #if 0
29 #ifndef ISDN_PID_L2_B_USER
30 #define ISDN_PID_L2_B_USER 0x420000ff
31 #endif
32 #ifndef ISDN_PID_L3_B_USER
33 #define ISDN_PID_L3_B_USER 0x430000ff
34 #endif
35 #endif
36 #ifndef ISDN_PID_L4_B_USER
37 #define ISDN_PID_L4_B_USER 0x440000ff
38 #endif
39
40 /* used for udevice */
41 int entity = 0;
42
43 /* the device handler and port list */
44 int mISDNdevice = -1;
45
46
47 /* open mISDN device */
48 void mISDNdevice_open(void)
49 {
50         /* open mISDNdevice if not already open */
51         if (mISDNdevice < 0)
52         {
53                 ret = mISDN_open();
54                 if (ret < 0)
55                 {
56                         PERROR("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));
57                         return(NULL);
58                 }
59                 mISDNdevice = ret;
60                 PDEBUG(DEBUG_ISDN, "mISDN device opened.\n");
61         }
62 }
63
64 /* close mISDN device */
65 void mISDNdevice_close(void)
66 {
67         if (mISDNdevice > -1)
68         {
69                 mISDN_close();
70                 PDEBUG(DEBUG_ISDN, "mISDN device closed.\n");
71         }
72 }
73
74 /* create bchannel layer */
75 unsigned long mISDN_createlayer(unsigned long stid)
76 {
77         unsigned long addr;
78
79         /* create new layer */
80         PDEBUG(DEBUG_BCHANNEL, "creating new layer for bchannel stid=0%x.\n" , stid);
81         memset(&li, 0, sizeof(li));
82         memset(&pid, 0, sizeof(pid));
83         li.object_id = -1;
84         li.extentions = 0;
85         li.st = stid;
86         UCPY(li.name, "B L4");
87         li.pid.layermask = ISDN_LAYER((4));
88         li.pid.protocol[4] = ISDN_PID_L4_B_USER;
89         ret = mISDN_new_layer(mISDNdevice, &li);
90         if (ret)
91         {
92                 failed_new_layer:
93                 PERROR("mISDN_new_layer() failed to add bchannel stid=0%x.\n", stid);
94                 goto failed;
95         }
96         addr = li.id;
97         if (!li.id)
98         {
99                 goto failed_new_layer;
100         }
101         PDEBUG(DEBUG_BCHANNEL, "new layer (addr=0x%x)\n", addr);
102
103         /* create new stack */
104         pid.protocol[1] = ISDN_PID_L1_B_64TRANS;
105         pid.protocol[2] = ISDN_PID_L2_B_TRANS;
106         pid.protocol[3] = ISDN_PID_L3_B_DSP;
107         pid.protocol[4] = ISDN_PID_L4_B_USER;
108         pid.layermask = ISDN_LAYER((1)) | ISDN_LAYER((2)) | ISDN_LAYER((3)) | ISDN_LAYER((4));
109         ret = mISDN_set_stack(mISDNdevice, stid, &pid);
110         if (ret)
111         {
112                 stack_error:
113                 PERROR("mISDN_set_stack() failed (ret=%d) to add bchannel stid=0x%x\n", ret, stid);
114                 mISDN_write_frame(mISDNdevice, buff, addr, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
115                 goto failed;
116         }
117         ret = mISDN_get_setstack_ind(mISDNdevice, addr);
118         if (ret)
119                 goto stack_error;
120
121         /* get layer id */
122         addr = mISDN_get_layerid(mISDNdevice, stid, 4);
123         if (!addr)
124                 goto stack_error;
125 }
126
127 /* destroy bchannel layer */
128 void mISDN_destroylayer(unsigned long stid, unsigned long addr)
129 {
130         /* remove our stack only if set */
131         if (addr)
132         {
133                 PDEBUG(DEBUG_BCHANNEL, "free stack (addr=0x%x)\n", addr);
134                 mISDN_clear_stack(mISDNdevice, stid);
135                 mISDN_write_frame(mISDNdevice, buff, addr | FLG_MSG_DOWN, MGR_DELLAYER | REQUEST, 0, 0, NULL, TIMEOUT_1SEC);
136         }
137 }
138
139 /* do activation and deactivation of bchannel */
140 static void mISDN_bchannelactivate(unsigned long addr, int activate)
141 {
142         iframe_t act;
143
144         /* activate bchannel */
145         act.prim = (activate?DL_ESTABLISH:DL_RELEASE) | REQUEST; 
146         act.addr = addr | FLG_MSG_DOWN;
147         act.dinfo = 0;
148         act.len = 0;
149         mISDN_write(mISDNdevice, &act, mISDN_HEADER_LEN+act.len, TIMEOUT_1SEC);
150 }
151
152 /* handle all mISDN messages */
153 int mISDN_handler(void)
154 {
155         int ret;
156         msg_t *msg;
157         iframe_t *frm;
158         struct mISDNport *mISDNport;
159         class PmISDN *isdnport;
160         net_stack_t *nst;
161         msg_t *dmsg;
162         mISDNuser_head_t *hh;
163         int i;
164         struct chan_bchannel *bchannel;
165
166         /* no device, no read */
167         if (mISDNdevice < 0)
168                 return(0);
169
170         /* get message from kernel */
171         if (!(msg = alloc_msg(MAX_MSG_SIZE)))
172                 return(1);
173         ret = mISDN_read(mISDNdevice, msg->data, MAX_MSG_SIZE, 0);
174         if (ret < 0)
175         {
176                 free_msg(msg);
177                 if (errno == EAGAIN)
178                         return(0);
179                 FATAL("Failed to do mISDN_read()\n");
180         }
181         if (!ret)
182         {
183                 free_msg(msg);
184 //              printf("%s: ERROR: mISDN_read() returns nothing\n");
185                 return(0);
186         }
187         msg->len = ret;
188         frm = (iframe_t *)msg->data;
189
190         /* global prim */
191         switch(frm->prim)
192         {
193                 case MGR_DELLAYER | CONFIRM:
194                 case MGR_INITTIMER | CONFIRM:
195                 case MGR_ADDTIMER | CONFIRM:
196                 case MGR_DELTIMER | CONFIRM:
197                 case MGR_REMOVETIMER | CONFIRM:
198                 free_msg(msg);
199                 return(1);
200         }
201
202         /* look for channel instance, that has the address of this message */
203         bchannel = bchannel_first;
204         while(bchannel)
205         {
206                 if (frm->addr == bchannel->b_addr)
207                         break;
208                 bchannel = chan->next;
209         } 
210         if (!bchannel)
211         {
212                 PERROR("message belongs to no bchannel: prim(0x%x) addr(0x%x) msg->len(%d)\n", frm->prim, frm->addr, msg->len);
213                 goto out;
214         }
215
216         /* b-message */
217         switch(frm->prim)
218         {
219                 /* we don't care about confirms, we use rx data to sync tx */
220                 case PH_DATA | CONFIRM:
221                 case DL_DATA | CONFIRM:
222                 break;
223
224                 /* we receive audio data, we respond to it AND we send tones */
225                 case PH_DATA | INDICATION:
226                 case DL_DATA | INDICATION:
227                 case PH_CONTROL | INDICATION:
228                 i = 0;
229                 bchannel_receive(bchannel, frm);
230                 break;
231
232                 case PH_ACTIVATE | INDICATION:
233                 case DL_ESTABLISH | INDICATION:
234                 case PH_ACTIVATE | CONFIRM:
235                 case DL_ESTABLISH | CONFIRM:
236                 PDEBUG(DEBUG_BCHANNEL, "DL_ESTABLISH confirm: bchannel is now activated (address 0x%x).\n", frm->addr);
237                 bchannel_event(mISDNport, i, B_EVENT_ACTIVATED);
238                 break;
239
240                 case PH_DEACTIVATE | INDICATION:
241                 case DL_RELEASE | INDICATION:
242                 case PH_DEACTIVATE | CONFIRM:
243                 case DL_RELEASE | CONFIRM:
244                 PDEBUG(DEBUG_BCHANNEL, "DL_RELEASE confirm: bchannel is now de-activated (address 0x%x).\n", frm->addr);
245                 bchannel_event(mISDNport, i, B_EVENT_DEACTIVATED);
246                 break;
247
248                 default:
249                 PERROR("child message not handled: prim(0x%x) addr(0x%x) msg->len(%d)\n", frm->prim, frm->addr, msg->len);
250         }
251
252         out:
253         free_msg(msg);
254         return(1);
255 }
256