blob: f151f36c8255d4995efccdf53cd2097ddda406e9 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
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
37ushort last_ref_num = 1;
38
39/*
40 * send_conn_req
41 *
42 */
43
44void 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
86void 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/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128 * Incoming call received
129 * inform user
130 */
131
132void cb_in_1(struct pcbit_dev * dev, struct pcbit_chan* chan,
133 struct callb_data *cbdata)
134{
135 isdn_ctrl ictl;
136 unsigned short refnum;
137 struct sk_buff *skb;
138 int len;
139
140
141 ictl.command = ISDN_STAT_ICALL;
142 ictl.driver=dev->id;
143 ictl.arg=chan->id;
144
145 /*
146 * ictl.num >= strlen() + strlen() + 5
147 */
148
149 if (cbdata->data.setup.CallingPN == NULL) {
150 printk(KERN_DEBUG "NULL CallingPN to phone; using 0\n");
151 strcpy(ictl.parm.setup.phone, "0");
152 }
153 else {
154 strcpy(ictl.parm.setup.phone, cbdata->data.setup.CallingPN);
155 }
156 if (cbdata->data.setup.CalledPN == NULL) {
157 printk(KERN_DEBUG "NULL CalledPN to eazmsn; using 0\n");
158 strcpy(ictl.parm.setup.eazmsn, "0");
159 }
160 else {
161 strcpy(ictl.parm.setup.eazmsn, cbdata->data.setup.CalledPN);
162 }
163 ictl.parm.setup.si1 = 7;
164 ictl.parm.setup.si2 = 0;
165 ictl.parm.setup.plan = 0;
166 ictl.parm.setup.screen = 0;
167
168#ifdef DEBUG
169 printk(KERN_DEBUG "statstr: %s\n", ictl.num);
170#endif
171
172 dev->dev_if->statcallb(&ictl);
173
174
175 if ((len=capi_conn_resp(chan, &skb)) < 0) {
176 printk(KERN_DEBUG "capi_conn_resp failed\n");
177 return;
178 }
179
180 refnum = last_ref_num++ & 0x7fffU;
181 chan->s_refnum = refnum;
182
183 pcbit_l2_write(dev, MSG_CONN_RESP, refnum, skb, len);
184}
185
186/*
187 * user has replied
188 * open the channel
189 * send CONNECT message CONNECT_ACTIVE_REQ in CAPI
190 */
191
192void cb_in_2(struct pcbit_dev * dev, struct pcbit_chan* chan,
193 struct callb_data *data)
194{
195 unsigned short refnum;
196 struct sk_buff *skb;
197 int len;
198
199 if ((len = capi_conn_active_req(chan, &skb)) < 0) {
200 printk(KERN_DEBUG "capi_conn_active_req failed\n");
201 return;
202 }
203
204
205 refnum = last_ref_num++ & 0x7fffU;
206 chan->s_refnum = refnum;
207
208 printk(KERN_DEBUG "sending MSG_CONN_ACTV_REQ\n");
209 pcbit_l2_write(dev, MSG_CONN_ACTV_REQ, refnum, skb, len);
210}
211
212/*
213 * CONN_ACK arrived
214 * start b-proto selection
215 *
216 */
217
218void cb_in_3(struct pcbit_dev * dev, struct pcbit_chan* chan,
219 struct callb_data *data)
220{
221 unsigned short refnum;
222 struct sk_buff *skb;
223 int len;
224
225 if ((len = capi_select_proto_req(chan, &skb, 0 /*incoming*/)) < 0)
226 {
227 printk("capi_select_proto_req failed\n");
228 return;
229 }
230
231 refnum = last_ref_num++ & 0x7fffU;
232 chan->s_refnum = refnum;
233
234 pcbit_l2_write(dev, MSG_SELP_REQ, refnum, skb, len);
235
236}
237
238
239/*
240 * Received disconnect ind on active state
241 * send disconnect resp
242 * send msg to user
243 */
244void cb_disc_1(struct pcbit_dev * dev, struct pcbit_chan* chan,
245 struct callb_data *data)
246{
247 struct sk_buff *skb;
248 int len;
249 ushort refnum;
250 isdn_ctrl ictl;
251
252 if ((len = capi_disc_resp(chan, &skb)) < 0) {
253 printk("capi_disc_resp failed\n");
254 return;
255 }
256
257 refnum = last_ref_num++ & 0x7fffU;
258 chan->s_refnum = refnum;
259
260 pcbit_l2_write(dev, MSG_DISC_RESP, refnum, skb, len);
261
262 ictl.command = ISDN_STAT_BHUP;
263 ictl.driver=dev->id;
264 ictl.arg=chan->id;
265 dev->dev_if->statcallb(&ictl);
266}
267
268
269/*
270 * User HANGUP on active/call proceeding state
271 * send disc.req
272 */
273void cb_disc_2(struct pcbit_dev * dev, struct pcbit_chan* chan,
274 struct callb_data *data)
275{
276 struct sk_buff *skb;
277 int len;
278 ushort refnum;
279
280 if ((len = capi_disc_req(chan->callref, &skb, CAUSE_NORMAL)) < 0)
281 {
282 printk("capi_disc_req failed\n");
283 return;
284 }
285
286 refnum = last_ref_num++ & 0x7fffU;
287 chan->s_refnum = refnum;
288
289 pcbit_l2_write(dev, MSG_DISC_REQ, refnum, skb, len);
290}
291
292/*
293 * Disc confirm received send BHUP
294 * Problem: when the HL driver sends the disc req itself
295 * LL receives BHUP
296 */
297void cb_disc_3(struct pcbit_dev * dev, struct pcbit_chan* chan,
298 struct callb_data *data)
299{
300 isdn_ctrl ictl;
301
302 ictl.command = ISDN_STAT_BHUP;
303 ictl.driver=dev->id;
304 ictl.arg=chan->id;
305 dev->dev_if->statcallb(&ictl);
306}
307
308void cb_notdone(struct pcbit_dev * dev, struct pcbit_chan* chan,
309 struct callb_data *data)
310{
311}
312
313/*
314 * send activate b-chan protocol
315 */
316void cb_selp_1(struct pcbit_dev * dev, struct pcbit_chan* chan,
317 struct callb_data *data)
318{
319 struct sk_buff *skb;
320 int len;
321 ushort refnum;
322
323 if ((len = capi_activate_transp_req(chan, &skb)) < 0)
324 {
325 printk("capi_conn_activate_transp_req failed\n");
326 return;
327 }
328
329 refnum = last_ref_num++ & 0x7fffU;
330 chan->s_refnum = refnum;
331
332 pcbit_l2_write(dev, MSG_ACT_TRANSP_REQ, refnum, skb, len);
333}
334
335/*
336 * Inform User that the B-channel is available
337 */
338void cb_open(struct pcbit_dev * dev, struct pcbit_chan* chan,
339 struct callb_data *data)
340{
341 isdn_ctrl ictl;
342
343 ictl.command = ISDN_STAT_BCONN;
344 ictl.driver=dev->id;
345 ictl.arg=chan->id;
346 dev->dev_if->statcallb(&ictl);
347}
348
349
350