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