Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v2.6.16 350 lines 7.9 kB view raw
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 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/* 128 * 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