]> git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/blob - drivers/isdn/pcbit/callbacks.c
Linux-2.6.12-rc2
[mirror_ubuntu-focal-kernel.git] / drivers / isdn / pcbit / callbacks.c
1 /*
2 * Callbacks for the FSM
3 *
4 * Copyright (C) 1996 Universidade de Lisboa
5 *
6 * Written by Pedro Roque Marques (roque@di.fc.ul.pt)
7 *
8 * This software may be used and distributed according to the terms of
9 * the GNU General Public License, incorporated herein by reference.
10 */
11
12 /*
13 * Fix: 19981230 - Carlos Morgado <chbm@techie.com>
14 * Port of Nelson Escravana's <nelson.escravana@usa.net> fix to CalledPN
15 * NULL pointer dereference in cb_in_1 (originally fixed in 2.0)
16 */
17
18 #include <linux/sched.h>
19 #include <linux/string.h>
20 #include <linux/kernel.h>
21
22 #include <linux/types.h>
23 #include <linux/slab.h>
24 #include <linux/mm.h>
25 #include <linux/skbuff.h>
26
27 #include <asm/io.h>
28
29 #include <linux/isdnif.h>
30
31 #include "pcbit.h"
32 #include "layer2.h"
33 #include "edss1.h"
34 #include "callbacks.h"
35 #include "capi.h"
36
37 ushort last_ref_num = 1;
38
39 /*
40 * send_conn_req
41 *
42 */
43
44 void cb_out_1(struct pcbit_dev * dev, struct pcbit_chan* chan,
45 struct callb_data *cbdata)
46 {
47 struct sk_buff *skb;
48 int len;
49 ushort refnum;
50
51
52 #ifdef DEBUG
53 printk(KERN_DEBUG "Called Party Number: %s\n",
54 cbdata->data.setup.CalledPN);
55 #endif
56 /*
57 * hdr - kmalloc in capi_conn_req
58 * - kfree when msg has been sent
59 */
60
61 if ((len = capi_conn_req(cbdata->data.setup.CalledPN, &skb,
62 chan->proto)) < 0)
63 {
64 printk("capi_conn_req failed\n");
65 return;
66 }
67
68
69 refnum = last_ref_num++ & 0x7fffU;
70
71 chan->callref = 0;
72 chan->layer2link = 0;
73 chan->snum = 0;
74 chan->s_refnum = refnum;
75
76 pcbit_l2_write(dev, MSG_CONN_REQ, refnum, skb, len);
77 }
78
79 /*
80 * rcv CONNECT
81 * will go into ACTIVE state
82 * send CONN_ACTIVE_RESP
83 * send Select protocol request
84 */
85
86 void cb_out_2(struct pcbit_dev * dev, struct pcbit_chan* chan,
87 struct callb_data *data)
88 {
89 isdn_ctrl ictl;
90 struct sk_buff *skb;
91 int len;
92 ushort refnum;
93
94 if ((len=capi_conn_active_resp(chan, &skb)) < 0)
95 {
96 printk("capi_conn_active_req failed\n");
97 return;
98 }
99
100 refnum = last_ref_num++ & 0x7fffU;
101 chan->s_refnum = refnum;
102
103 pcbit_l2_write(dev, MSG_CONN_ACTV_RESP, refnum, skb, len);
104
105
106 ictl.command = ISDN_STAT_DCONN;
107 ictl.driver=dev->id;
108 ictl.arg=chan->id;
109 dev->dev_if->statcallb(&ictl);
110
111 /* ACTIVE D-channel */
112
113 /* Select protocol */
114
115 if ((len=capi_select_proto_req(chan, &skb, 1 /*outgoing*/)) < 0) {
116 printk("capi_select_proto_req failed\n");
117 return;
118 }
119
120 refnum = last_ref_num++ & 0x7fffU;
121 chan->s_refnum = refnum;
122
123 pcbit_l2_write(dev, MSG_SELP_REQ, refnum, skb, len);
124 }
125
126
127 /*
128 * Disconnect received (actually RELEASE COMPLETE)
129 * This means we were not able to establish connection with remote
130 * Inform the big boss above
131 */
132 void cb_out_3(struct pcbit_dev * dev, struct pcbit_chan* chan,
133 struct callb_data *data)
134 {
135 isdn_ctrl ictl;
136
137 ictl.command = ISDN_STAT_DHUP;
138 ictl.driver=dev->id;
139 ictl.arg=chan->id;
140 dev->dev_if->statcallb(&ictl);
141 }
142
143
144 /*
145 * Incoming call received
146 * inform user
147 */
148
149 void cb_in_1(struct pcbit_dev * dev, struct pcbit_chan* chan,
150 struct callb_data *cbdata)
151 {
152 isdn_ctrl ictl;
153 unsigned short refnum;
154 struct sk_buff *skb;
155 int len;
156
157
158 ictl.command = ISDN_STAT_ICALL;
159 ictl.driver=dev->id;
160 ictl.arg=chan->id;
161
162 /*
163 * ictl.num >= strlen() + strlen() + 5
164 */
165
166 if (cbdata->data.setup.CallingPN == NULL) {
167 printk(KERN_DEBUG "NULL CallingPN to phone; using 0\n");
168 strcpy(ictl.parm.setup.phone, "0");
169 }
170 else {
171 strcpy(ictl.parm.setup.phone, cbdata->data.setup.CallingPN);
172 }
173 if (cbdata->data.setup.CalledPN == NULL) {
174 printk(KERN_DEBUG "NULL CalledPN to eazmsn; using 0\n");
175 strcpy(ictl.parm.setup.eazmsn, "0");
176 }
177 else {
178 strcpy(ictl.parm.setup.eazmsn, cbdata->data.setup.CalledPN);
179 }
180 ictl.parm.setup.si1 = 7;
181 ictl.parm.setup.si2 = 0;
182 ictl.parm.setup.plan = 0;
183 ictl.parm.setup.screen = 0;
184
185 #ifdef DEBUG
186 printk(KERN_DEBUG "statstr: %s\n", ictl.num);
187 #endif
188
189 dev->dev_if->statcallb(&ictl);
190
191
192 if ((len=capi_conn_resp(chan, &skb)) < 0) {
193 printk(KERN_DEBUG "capi_conn_resp failed\n");
194 return;
195 }
196
197 refnum = last_ref_num++ & 0x7fffU;
198 chan->s_refnum = refnum;
199
200 pcbit_l2_write(dev, MSG_CONN_RESP, refnum, skb, len);
201 }
202
203 /*
204 * user has replied
205 * open the channel
206 * send CONNECT message CONNECT_ACTIVE_REQ in CAPI
207 */
208
209 void cb_in_2(struct pcbit_dev * dev, struct pcbit_chan* chan,
210 struct callb_data *data)
211 {
212 unsigned short refnum;
213 struct sk_buff *skb;
214 int len;
215
216 if ((len = capi_conn_active_req(chan, &skb)) < 0) {
217 printk(KERN_DEBUG "capi_conn_active_req failed\n");
218 return;
219 }
220
221
222 refnum = last_ref_num++ & 0x7fffU;
223 chan->s_refnum = refnum;
224
225 printk(KERN_DEBUG "sending MSG_CONN_ACTV_REQ\n");
226 pcbit_l2_write(dev, MSG_CONN_ACTV_REQ, refnum, skb, len);
227 }
228
229 /*
230 * CONN_ACK arrived
231 * start b-proto selection
232 *
233 */
234
235 void cb_in_3(struct pcbit_dev * dev, struct pcbit_chan* chan,
236 struct callb_data *data)
237 {
238 unsigned short refnum;
239 struct sk_buff *skb;
240 int len;
241
242 if ((len = capi_select_proto_req(chan, &skb, 0 /*incoming*/)) < 0)
243 {
244 printk("capi_select_proto_req failed\n");
245 return;
246 }
247
248 refnum = last_ref_num++ & 0x7fffU;
249 chan->s_refnum = refnum;
250
251 pcbit_l2_write(dev, MSG_SELP_REQ, refnum, skb, len);
252
253 }
254
255
256 /*
257 * Received disconnect ind on active state
258 * send disconnect resp
259 * send msg to user
260 */
261 void cb_disc_1(struct pcbit_dev * dev, struct pcbit_chan* chan,
262 struct callb_data *data)
263 {
264 struct sk_buff *skb;
265 int len;
266 ushort refnum;
267 isdn_ctrl ictl;
268
269 if ((len = capi_disc_resp(chan, &skb)) < 0) {
270 printk("capi_disc_resp failed\n");
271 return;
272 }
273
274 refnum = last_ref_num++ & 0x7fffU;
275 chan->s_refnum = refnum;
276
277 pcbit_l2_write(dev, MSG_DISC_RESP, refnum, skb, len);
278
279 ictl.command = ISDN_STAT_BHUP;
280 ictl.driver=dev->id;
281 ictl.arg=chan->id;
282 dev->dev_if->statcallb(&ictl);
283 }
284
285
286 /*
287 * User HANGUP on active/call proceeding state
288 * send disc.req
289 */
290 void cb_disc_2(struct pcbit_dev * dev, struct pcbit_chan* chan,
291 struct callb_data *data)
292 {
293 struct sk_buff *skb;
294 int len;
295 ushort refnum;
296
297 if ((len = capi_disc_req(chan->callref, &skb, CAUSE_NORMAL)) < 0)
298 {
299 printk("capi_disc_req failed\n");
300 return;
301 }
302
303 refnum = last_ref_num++ & 0x7fffU;
304 chan->s_refnum = refnum;
305
306 pcbit_l2_write(dev, MSG_DISC_REQ, refnum, skb, len);
307 }
308
309 /*
310 * Disc confirm received send BHUP
311 * Problem: when the HL driver sends the disc req itself
312 * LL receives BHUP
313 */
314 void cb_disc_3(struct pcbit_dev * dev, struct pcbit_chan* chan,
315 struct callb_data *data)
316 {
317 isdn_ctrl ictl;
318
319 ictl.command = ISDN_STAT_BHUP;
320 ictl.driver=dev->id;
321 ictl.arg=chan->id;
322 dev->dev_if->statcallb(&ictl);
323 }
324
325 void cb_notdone(struct pcbit_dev * dev, struct pcbit_chan* chan,
326 struct callb_data *data)
327 {
328 }
329
330 /*
331 * send activate b-chan protocol
332 */
333 void cb_selp_1(struct pcbit_dev * dev, struct pcbit_chan* chan,
334 struct callb_data *data)
335 {
336 struct sk_buff *skb;
337 int len;
338 ushort refnum;
339
340 if ((len = capi_activate_transp_req(chan, &skb)) < 0)
341 {
342 printk("capi_conn_activate_transp_req failed\n");
343 return;
344 }
345
346 refnum = last_ref_num++ & 0x7fffU;
347 chan->s_refnum = refnum;
348
349 pcbit_l2_write(dev, MSG_ACT_TRANSP_REQ, refnum, skb, len);
350 }
351
352 /*
353 * Inform User that the B-channel is available
354 */
355 void cb_open(struct pcbit_dev * dev, struct pcbit_chan* chan,
356 struct callb_data *data)
357 {
358 isdn_ctrl ictl;
359
360 ictl.command = ISDN_STAT_BCONN;
361 ictl.driver=dev->id;
362 ictl.arg=chan->id;
363 dev->dev_if->statcallb(&ictl);
364 }
365
366
367