Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
capi.c
Go to the documentation of this file.
1 /* $Id: capi.c,v 1.9.6.2 2001/09/23 22:24:32 kai Exp $
2  *
3  * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000.
4  * CAPI encoder/decoder
5  *
6  * Author Fritz Elfert
7  * Copyright by Fritz Elfert <[email protected]>
8  *
9  * This software may be used and distributed according to the terms
10  * of the GNU General Public License, incorporated herein by reference.
11  *
12  * Thanks to Friedemann Baitinger and IBM Germany
13  *
14  */
15 
16 #include "act2000.h"
17 #include "capi.h"
18 
19 static actcapi_msgdsc valid_msg[] = {
20  {{ 0x86, 0x02}, "DATA_B3_IND"}, /* DATA_B3_IND/CONF must be first because of speed!!! */
21  {{ 0x86, 0x01}, "DATA_B3_CONF"},
22  {{ 0x02, 0x01}, "CONNECT_CONF"},
23  {{ 0x02, 0x02}, "CONNECT_IND"},
24  {{ 0x09, 0x01}, "CONNECT_INFO_CONF"},
25  {{ 0x03, 0x02}, "CONNECT_ACTIVE_IND"},
26  {{ 0x04, 0x01}, "DISCONNECT_CONF"},
27  {{ 0x04, 0x02}, "DISCONNECT_IND"},
28  {{ 0x05, 0x01}, "LISTEN_CONF"},
29  {{ 0x06, 0x01}, "GET_PARAMS_CONF"},
30  {{ 0x07, 0x01}, "INFO_CONF"},
31  {{ 0x07, 0x02}, "INFO_IND"},
32  {{ 0x08, 0x01}, "DATA_CONF"},
33  {{ 0x08, 0x02}, "DATA_IND"},
34  {{ 0x40, 0x01}, "SELECT_B2_PROTOCOL_CONF"},
35  {{ 0x80, 0x01}, "SELECT_B3_PROTOCOL_CONF"},
36  {{ 0x81, 0x01}, "LISTEN_B3_CONF"},
37  {{ 0x82, 0x01}, "CONNECT_B3_CONF"},
38  {{ 0x82, 0x02}, "CONNECT_B3_IND"},
39  {{ 0x83, 0x02}, "CONNECT_B3_ACTIVE_IND"},
40  {{ 0x84, 0x01}, "DISCONNECT_B3_CONF"},
41  {{ 0x84, 0x02}, "DISCONNECT_B3_IND"},
42  {{ 0x85, 0x01}, "GET_B3_PARAMS_CONF"},
43  {{ 0x01, 0x01}, "RESET_B3_CONF"},
44  {{ 0x01, 0x02}, "RESET_B3_IND"},
45  /* {{ 0x87, 0x02, "HANDSET_IND"}, not implemented */
46  {{ 0xff, 0x01}, "MANUFACTURER_CONF"},
47  {{ 0xff, 0x02}, "MANUFACTURER_IND"},
48 #ifdef DEBUG_MSG
49  /* Requests */
50  {{ 0x01, 0x00}, "RESET_B3_REQ"},
51  {{ 0x02, 0x00}, "CONNECT_REQ"},
52  {{ 0x04, 0x00}, "DISCONNECT_REQ"},
53  {{ 0x05, 0x00}, "LISTEN_REQ"},
54  {{ 0x06, 0x00}, "GET_PARAMS_REQ"},
55  {{ 0x07, 0x00}, "INFO_REQ"},
56  {{ 0x08, 0x00}, "DATA_REQ"},
57  {{ 0x09, 0x00}, "CONNECT_INFO_REQ"},
58  {{ 0x40, 0x00}, "SELECT_B2_PROTOCOL_REQ"},
59  {{ 0x80, 0x00}, "SELECT_B3_PROTOCOL_REQ"},
60  {{ 0x81, 0x00}, "LISTEN_B3_REQ"},
61  {{ 0x82, 0x00}, "CONNECT_B3_REQ"},
62  {{ 0x84, 0x00}, "DISCONNECT_B3_REQ"},
63  {{ 0x85, 0x00}, "GET_B3_PARAMS_REQ"},
64  {{ 0x86, 0x00}, "DATA_B3_REQ"},
65  {{ 0xff, 0x00}, "MANUFACTURER_REQ"},
66  /* Responses */
67  {{ 0x01, 0x03}, "RESET_B3_RESP"},
68  {{ 0x02, 0x03}, "CONNECT_RESP"},
69  {{ 0x03, 0x03}, "CONNECT_ACTIVE_RESP"},
70  {{ 0x04, 0x03}, "DISCONNECT_RESP"},
71  {{ 0x07, 0x03}, "INFO_RESP"},
72  {{ 0x08, 0x03}, "DATA_RESP"},
73  {{ 0x82, 0x03}, "CONNECT_B3_RESP"},
74  {{ 0x83, 0x03}, "CONNECT_B3_ACTIVE_RESP"},
75  {{ 0x84, 0x03}, "DISCONNECT_B3_RESP"},
76  {{ 0x86, 0x03}, "DATA_B3_RESP"},
77  {{ 0xff, 0x03}, "MANUFACTURER_RESP"},
78 #endif
79  {{ 0x00, 0x00}, NULL},
80 };
81 #define num_valid_imsg 27 /* MANUFACTURER_IND */
82 
83 /*
84  * Check for a valid incoming CAPI message.
85  * Return:
86  * 0 = Invalid message
87  * 1 = Valid message, no B-Channel-data
88  * 2 = Valid message, B-Channel-data
89  */
90 int
92 {
93  int i;
94 
95  if (hdr->applicationID != 1)
96  return 0;
97  if (hdr->len < 9)
98  return 0;
99  for (i = 0; i < num_valid_imsg; i++)
100  if ((hdr->cmd.cmd == valid_msg[i].cmd.cmd) &&
101  (hdr->cmd.subcmd == valid_msg[i].cmd.subcmd)) {
102  return (i ? 1 : 2);
103  }
104  return 0;
105 }
106 
107 #define ACTCAPI_MKHDR(l, c, s) { \
108  skb = alloc_skb(l + 8, GFP_ATOMIC); \
109  if (skb) { \
110  m = (actcapi_msg *)skb_put(skb, l + 8); \
111  m->hdr.len = l + 8; \
112  m->hdr.applicationID = 1; \
113  m->hdr.cmd.cmd = c; \
114  m->hdr.cmd.subcmd = s; \
115  m->hdr.msgnum = actcapi_nextsmsg(card); \
116  } else m = NULL; \
117  }
118 
119 #define ACTCAPI_CHKSKB if (!skb) { \
120  printk(KERN_WARNING "actcapi: alloc_skb failed\n"); \
121  return; \
122  }
123 
124 #define ACTCAPI_QUEUE_TX { \
125  actcapi_debug_msg(skb, 1); \
126  skb_queue_tail(&card->sndq, skb); \
127  act2000_schedule_tx(card); \
128  }
129 
130 int
131 actcapi_listen_req(act2000_card *card)
132 {
133  __u16 eazmask = 0;
134  int i;
135  actcapi_msg *m;
136  struct sk_buff *skb;
137 
138  for (i = 0; i < ACT2000_BCH; i++)
139  eazmask |= card->bch[i].eazmask;
140  ACTCAPI_MKHDR(9, 0x05, 0x00);
141  if (!skb) {
142  printk(KERN_WARNING "actcapi: alloc_skb failed\n");
143  return -ENOMEM;
144  }
145  m->msg.listen_req.controller = 0;
146  m->msg.listen_req.infomask = 0x3f; /* All information */
147  m->msg.listen_req.eazmask = eazmask;
148  m->msg.listen_req.simask = (eazmask) ? 0x86 : 0; /* All SI's */
150  return 0;
151 }
152 
153 int
154 actcapi_connect_req(act2000_card *card, act2000_chan *chan, char *phone,
155  char eaz, int si1, int si2)
156 {
157  actcapi_msg *m;
158  struct sk_buff *skb;
159 
160  ACTCAPI_MKHDR((11 + strlen(phone)), 0x02, 0x00);
161  if (!skb) {
162  printk(KERN_WARNING "actcapi: alloc_skb failed\n");
163  chan->fsm_state = ACT2000_STATE_NULL;
164  return -ENOMEM;
165  }
166  m->msg.connect_req.controller = 0;
167  m->msg.connect_req.bchan = 0x83;
168  m->msg.connect_req.infomask = 0x3f;
169  m->msg.connect_req.si1 = si1;
170  m->msg.connect_req.si2 = si2;
171  m->msg.connect_req.eaz = eaz ? eaz : '0';
172  m->msg.connect_req.addr.len = strlen(phone) + 1;
173  m->msg.connect_req.addr.tnp = 0x81;
174  memcpy(m->msg.connect_req.addr.num, phone, strlen(phone));
175  chan->callref = m->hdr.msgnum;
177  return 0;
178 }
179 
180 static void
181 actcapi_connect_b3_req(act2000_card *card, act2000_chan *chan)
182 {
183  actcapi_msg *m;
184  struct sk_buff *skb;
185 
186  ACTCAPI_MKHDR(17, 0x82, 0x00);
188  m->msg.connect_b3_req.plci = chan->plci;
189  memset(&m->msg.connect_b3_req.ncpi, 0,
190  sizeof(m->msg.connect_b3_req.ncpi));
191  m->msg.connect_b3_req.ncpi.len = 13;
192  m->msg.connect_b3_req.ncpi.modulo = 8;
194 }
195 
196 /*
197  * Set net type (1TR6) or (EDSS1)
198  */
199 int
201 {
202  actcapi_msg *m;
203  struct sk_buff *skb;
204 
205  ACTCAPI_MKHDR(5, 0xff, 0x00);
206  if (!skb) {
207  printk(KERN_WARNING "actcapi: alloc_skb failed\n");
208  return -ENOMEM;
209  }
210  m->msg.manufacturer_req_net.manuf_msg = 0x11;
211  m->msg.manufacturer_req_net.controller = 1;
212  m->msg.manufacturer_req_net.nettype = (card->ptype == ISDN_PTYPE_EURO) ? 1 : 0;
214  printk(KERN_INFO "act2000 %s: D-channel protocol now %s\n",
215  card->interface.id, (card->ptype == ISDN_PTYPE_EURO) ? "euro" : "1tr6");
216  card->interface.features &=
218  card->interface.features |=
220  return 0;
221 }
222 
223 /*
224  * Switch V.42 on or off
225  */
226 #if 0
227 int
228 actcapi_manufacturer_req_v42(act2000_card *card, ulong arg)
229 {
230  actcapi_msg *m;
231  struct sk_buff *skb;
232 
233  ACTCAPI_MKHDR(8, 0xff, 0x00);
234  if (!skb) {
235 
236  printk(KERN_WARNING "actcapi: alloc_skb failed\n");
237  return -ENOMEM;
238  }
239  m->msg.manufacturer_req_v42.manuf_msg = 0x10;
240  m->msg.manufacturer_req_v42.controller = 0;
241  m->msg.manufacturer_req_v42.v42control = (arg ? 1 : 0);
243  return 0;
244 }
245 #endif /* 0 */
246 
247 /*
248  * Set error-handler
249  */
250 int
251 actcapi_manufacturer_req_errh(act2000_card *card)
252 {
253  actcapi_msg *m;
254  struct sk_buff *skb;
255 
256  ACTCAPI_MKHDR(4, 0xff, 0x00);
257  if (!skb) {
258 
259  printk(KERN_WARNING "actcapi: alloc_skb failed\n");
260  return -ENOMEM;
261  }
262  m->msg.manufacturer_req_err.manuf_msg = 0x03;
263  m->msg.manufacturer_req_err.controller = 0;
265  return 0;
266 }
267 
268 /*
269  * Set MSN-Mapping.
270  */
271 int
272 actcapi_manufacturer_req_msn(act2000_card *card)
273 {
274  msn_entry *p = card->msn_list;
275  actcapi_msg *m;
276  struct sk_buff *skb;
277  int len;
278 
279  while (p) {
280  int i;
281 
282  len = strlen(p->msn);
283  for (i = 0; i < 2; i++) {
284  ACTCAPI_MKHDR(6 + len, 0xff, 0x00);
285  if (!skb) {
286  printk(KERN_WARNING "actcapi: alloc_skb failed\n");
287  return -ENOMEM;
288  }
289  m->msg.manufacturer_req_msn.manuf_msg = 0x13 + i;
290  m->msg.manufacturer_req_msn.controller = 0;
291  m->msg.manufacturer_req_msn.msnmap.eaz = p->eaz;
292  m->msg.manufacturer_req_msn.msnmap.len = len;
293  memcpy(m->msg.manufacturer_req_msn.msnmap.msn, p->msn, len);
295  }
296  p = p->next;
297  }
298  return 0;
299 }
300 
301 void
302 actcapi_select_b2_protocol_req(act2000_card *card, act2000_chan *chan)
303 {
304  actcapi_msg *m;
305  struct sk_buff *skb;
306 
307  ACTCAPI_MKHDR(10, 0x40, 0x00);
309  m->msg.select_b2_protocol_req.plci = chan->plci;
310  memset(&m->msg.select_b2_protocol_req.dlpd, 0,
311  sizeof(m->msg.select_b2_protocol_req.dlpd));
312  m->msg.select_b2_protocol_req.dlpd.len = 6;
313  switch (chan->l2prot) {
314  case ISDN_PROTO_L2_TRANS:
315  m->msg.select_b2_protocol_req.protocol = 0x03;
316  m->msg.select_b2_protocol_req.dlpd.dlen = 4000;
317  break;
318  case ISDN_PROTO_L2_HDLC:
319  m->msg.select_b2_protocol_req.protocol = 0x02;
320  m->msg.select_b2_protocol_req.dlpd.dlen = 4000;
321  break;
322  case ISDN_PROTO_L2_X75I:
323  case ISDN_PROTO_L2_X75UI:
325  m->msg.select_b2_protocol_req.protocol = 0x01;
326  m->msg.select_b2_protocol_req.dlpd.dlen = 4000;
327  m->msg.select_b2_protocol_req.dlpd.laa = 3;
328  m->msg.select_b2_protocol_req.dlpd.lab = 1;
329  m->msg.select_b2_protocol_req.dlpd.win = 7;
330  m->msg.select_b2_protocol_req.dlpd.modulo = 8;
331  break;
332  }
334 }
335 
336 static void
337 actcapi_select_b3_protocol_req(act2000_card *card, act2000_chan *chan)
338 {
339  actcapi_msg *m;
340  struct sk_buff *skb;
341 
342  ACTCAPI_MKHDR(17, 0x80, 0x00);
344  m->msg.select_b3_protocol_req.plci = chan->plci;
345  memset(&m->msg.select_b3_protocol_req.ncpd, 0,
346  sizeof(m->msg.select_b3_protocol_req.ncpd));
347  switch (chan->l3prot) {
348  case ISDN_PROTO_L3_TRANS:
349  m->msg.select_b3_protocol_req.protocol = 0x04;
350  m->msg.select_b3_protocol_req.ncpd.len = 13;
351  m->msg.select_b3_protocol_req.ncpd.modulo = 8;
352  break;
353  }
355 }
356 
357 static void
358 actcapi_listen_b3_req(act2000_card *card, act2000_chan *chan)
359 {
360  actcapi_msg *m;
361  struct sk_buff *skb;
362 
363  ACTCAPI_MKHDR(2, 0x81, 0x00);
365  m->msg.listen_b3_req.plci = chan->plci;
367 }
368 
369 static void
370 actcapi_disconnect_req(act2000_card *card, act2000_chan *chan)
371 {
372  actcapi_msg *m;
373  struct sk_buff *skb;
374 
375  ACTCAPI_MKHDR(3, 0x04, 0x00);
377  m->msg.disconnect_req.plci = chan->plci;
378  m->msg.disconnect_req.cause = 0;
380 }
381 
382 void
383 actcapi_disconnect_b3_req(act2000_card *card, act2000_chan *chan)
384 {
385  actcapi_msg *m;
386  struct sk_buff *skb;
387 
388  ACTCAPI_MKHDR(17, 0x84, 0x00);
390  m->msg.disconnect_b3_req.ncci = chan->ncci;
391  memset(&m->msg.disconnect_b3_req.ncpi, 0,
392  sizeof(m->msg.disconnect_b3_req.ncpi));
393  m->msg.disconnect_b3_req.ncpi.len = 13;
394  m->msg.disconnect_b3_req.ncpi.modulo = 8;
395  chan->fsm_state = ACT2000_STATE_BHWAIT;
397 }
398 
399 void
400 actcapi_connect_resp(act2000_card *card, act2000_chan *chan, __u8 cause)
401 {
402  actcapi_msg *m;
403  struct sk_buff *skb;
404 
405  ACTCAPI_MKHDR(3, 0x02, 0x03);
407  m->msg.connect_resp.plci = chan->plci;
408  m->msg.connect_resp.rejectcause = cause;
409  if (cause) {
410  chan->fsm_state = ACT2000_STATE_NULL;
411  chan->plci = 0x8000;
412  } else
413  chan->fsm_state = ACT2000_STATE_IWAIT;
415 }
416 
417 static void
418 actcapi_connect_active_resp(act2000_card *card, act2000_chan *chan)
419 {
420  actcapi_msg *m;
421  struct sk_buff *skb;
422 
423  ACTCAPI_MKHDR(2, 0x03, 0x03);
425  m->msg.connect_resp.plci = chan->plci;
426  if (chan->fsm_state == ACT2000_STATE_IWAIT)
427  chan->fsm_state = ACT2000_STATE_IBWAIT;
429 }
430 
431 static void
432 actcapi_connect_b3_resp(act2000_card *card, act2000_chan *chan, __u8 rejectcause)
433 {
434  actcapi_msg *m;
435  struct sk_buff *skb;
436 
437  ACTCAPI_MKHDR((rejectcause ? 3 : 17), 0x82, 0x03);
439  m->msg.connect_b3_resp.ncci = chan->ncci;
440  m->msg.connect_b3_resp.rejectcause = rejectcause;
441  if (!rejectcause) {
442  memset(&m->msg.connect_b3_resp.ncpi, 0,
443  sizeof(m->msg.connect_b3_resp.ncpi));
444  m->msg.connect_b3_resp.ncpi.len = 13;
445  m->msg.connect_b3_resp.ncpi.modulo = 8;
446  chan->fsm_state = ACT2000_STATE_BWAIT;
447  }
449 }
450 
451 static void
452 actcapi_connect_b3_active_resp(act2000_card *card, act2000_chan *chan)
453 {
454  actcapi_msg *m;
455  struct sk_buff *skb;
456 
457  ACTCAPI_MKHDR(2, 0x83, 0x03);
459  m->msg.connect_b3_active_resp.ncci = chan->ncci;
460  chan->fsm_state = ACT2000_STATE_ACTIVE;
462 }
463 
464 static void
465 actcapi_info_resp(act2000_card *card, act2000_chan *chan)
466 {
467  actcapi_msg *m;
468  struct sk_buff *skb;
469 
470  ACTCAPI_MKHDR(2, 0x07, 0x03);
472  m->msg.info_resp.plci = chan->plci;
474 }
475 
476 static void
477 actcapi_disconnect_b3_resp(act2000_card *card, act2000_chan *chan)
478 {
479  actcapi_msg *m;
480  struct sk_buff *skb;
481 
482  ACTCAPI_MKHDR(2, 0x84, 0x03);
484  m->msg.disconnect_b3_resp.ncci = chan->ncci;
485  chan->ncci = 0x8000;
486  chan->queued = 0;
488 }
489 
490 static void
491 actcapi_disconnect_resp(act2000_card *card, act2000_chan *chan)
492 {
493  actcapi_msg *m;
494  struct sk_buff *skb;
495 
496  ACTCAPI_MKHDR(2, 0x04, 0x03);
498  m->msg.disconnect_resp.plci = chan->plci;
499  chan->plci = 0x8000;
501 }
502 
503 static int
504 new_plci(act2000_card *card, __u16 plci)
505 {
506  int i;
507  for (i = 0; i < ACT2000_BCH; i++)
508  if (card->bch[i].plci == 0x8000) {
509  card->bch[i].plci = plci;
510  return i;
511  }
512  return -1;
513 }
514 
515 static int
516 find_plci(act2000_card *card, __u16 plci)
517 {
518  int i;
519  for (i = 0; i < ACT2000_BCH; i++)
520  if (card->bch[i].plci == plci)
521  return i;
522  return -1;
523 }
524 
525 static int
526 find_ncci(act2000_card *card, __u16 ncci)
527 {
528  int i;
529  for (i = 0; i < ACT2000_BCH; i++)
530  if (card->bch[i].ncci == ncci)
531  return i;
532  return -1;
533 }
534 
535 static int
536 find_dialing(act2000_card *card, __u16 callref)
537 {
538  int i;
539  for (i = 0; i < ACT2000_BCH; i++)
540  if ((card->bch[i].callref == callref) &&
541  (card->bch[i].fsm_state == ACT2000_STATE_OCALL))
542  return i;
543  return -1;
544 }
545 
546 static int
547 actcapi_data_b3_ind(act2000_card *card, struct sk_buff *skb) {
548  __u16 plci;
549  __u16 ncci;
551  __u8 blocknr;
552  int chan;
553  actcapi_msg *msg = (actcapi_msg *)skb->data;
554 
555  EVAL_NCCI(msg->msg.data_b3_ind.fakencci, plci, controller, ncci);
556  chan = find_ncci(card, ncci);
557  if (chan < 0)
558  return 0;
559  if (card->bch[chan].fsm_state != ACT2000_STATE_ACTIVE)
560  return 0;
561  if (card->bch[chan].plci != plci)
562  return 0;
563  blocknr = msg->msg.data_b3_ind.blocknr;
564  skb_pull(skb, 19);
565  card->interface.rcvcallb_skb(card->myid, chan, skb);
566  if (!(skb = alloc_skb(11, GFP_ATOMIC))) {
567  printk(KERN_WARNING "actcapi: alloc_skb failed\n");
568  return 1;
569  }
570  msg = (actcapi_msg *)skb_put(skb, 11);
571  msg->hdr.len = 11;
572  msg->hdr.applicationID = 1;
573  msg->hdr.cmd.cmd = 0x86;
574  msg->hdr.cmd.subcmd = 0x03;
575  msg->hdr.msgnum = actcapi_nextsmsg(card);
576  msg->msg.data_b3_resp.ncci = ncci;
577  msg->msg.data_b3_resp.blocknr = blocknr;
579  return 1;
580 }
581 
582 /*
583  * Walk over ackq, unlink DATA_B3_REQ from it, if
584  * ncci and blocknr are matching.
585  * Decrement queued-bytes counter.
586  */
587 static int
588 handle_ack(act2000_card *card, act2000_chan *chan, __u8 blocknr) {
589  unsigned long flags;
590  struct sk_buff *skb;
591  struct sk_buff *tmp;
592  struct actcapi_msg *m;
593  int ret = 0;
594 
595  spin_lock_irqsave(&card->lock, flags);
596  skb = skb_peek(&card->ackq);
597  spin_unlock_irqrestore(&card->lock, flags);
598  if (!skb) {
599  printk(KERN_WARNING "act2000: handle_ack nothing found!\n");
600  return 0;
601  }
602  tmp = skb;
603  while (1) {
604  m = (actcapi_msg *)tmp->data;
605  if ((((m->msg.data_b3_req.fakencci >> 8) & 0xff) == chan->ncci) &&
606  (m->msg.data_b3_req.blocknr == blocknr)) {
607  /* found corresponding DATA_B3_REQ */
608  skb_unlink(tmp, &card->ackq);
609  chan->queued -= m->msg.data_b3_req.datalen;
610  if (m->msg.data_b3_req.flags)
611  ret = m->msg.data_b3_req.datalen;
612  dev_kfree_skb(tmp);
613  if (chan->queued < 0)
614  chan->queued = 0;
615  return ret;
616  }
617  spin_lock_irqsave(&card->lock, flags);
618  tmp = skb_peek((struct sk_buff_head *)tmp);
619  spin_unlock_irqrestore(&card->lock, flags);
620  if ((tmp == skb) || (tmp == NULL)) {
621  /* reached end of queue */
622  printk(KERN_WARNING "act2000: handle_ack nothing found!\n");
623  return 0;
624  }
625  }
626 }
627 
628 void
630 {
631  struct act2000_card *card =
632  container_of(work, struct act2000_card, rcv_tq);
633  struct sk_buff *skb;
634  actcapi_msg *msg;
635  __u16 ccmd;
636  int chan;
637  int len;
638  act2000_chan *ctmp;
639  isdn_ctrl cmd;
640  char tmp[170];
641 
642  while ((skb = skb_dequeue(&card->rcvq))) {
643  actcapi_debug_msg(skb, 0);
644  msg = (actcapi_msg *)skb->data;
645  ccmd = ((msg->hdr.cmd.cmd << 8) | msg->hdr.cmd.subcmd);
646  switch (ccmd) {
647  case 0x8602:
648  /* DATA_B3_IND */
649  if (actcapi_data_b3_ind(card, skb))
650  return;
651  break;
652  case 0x8601:
653  /* DATA_B3_CONF */
654  chan = find_ncci(card, msg->msg.data_b3_conf.ncci);
655  if ((chan >= 0) && (card->bch[chan].fsm_state == ACT2000_STATE_ACTIVE)) {
656  if (msg->msg.data_b3_conf.info != 0)
657  printk(KERN_WARNING "act2000: DATA_B3_CONF: %04x\n",
658  msg->msg.data_b3_conf.info);
659  len = handle_ack(card, &card->bch[chan],
660  msg->msg.data_b3_conf.blocknr);
661  if (len) {
662  cmd.driver = card->myid;
663  cmd.command = ISDN_STAT_BSENT;
664  cmd.arg = chan;
665  cmd.parm.length = len;
666  card->interface.statcallb(&cmd);
667  }
668  }
669  break;
670  case 0x0201:
671  /* CONNECT_CONF */
672  chan = find_dialing(card, msg->hdr.msgnum);
673  if (chan >= 0) {
674  if (msg->msg.connect_conf.info) {
675  card->bch[chan].fsm_state = ACT2000_STATE_NULL;
676  cmd.driver = card->myid;
677  cmd.command = ISDN_STAT_DHUP;
678  cmd.arg = chan;
679  card->interface.statcallb(&cmd);
680  } else {
681  card->bch[chan].fsm_state = ACT2000_STATE_OWAIT;
682  card->bch[chan].plci = msg->msg.connect_conf.plci;
683  }
684  }
685  break;
686  case 0x0202:
687  /* CONNECT_IND */
688  chan = new_plci(card, msg->msg.connect_ind.plci);
689  if (chan < 0) {
690  ctmp = (act2000_chan *)tmp;
691  ctmp->plci = msg->msg.connect_ind.plci;
692  actcapi_connect_resp(card, ctmp, 0x11); /* All Card-Cannels busy */
693  } else {
694  card->bch[chan].fsm_state = ACT2000_STATE_ICALL;
695  cmd.driver = card->myid;
696  cmd.command = ISDN_STAT_ICALL;
697  cmd.arg = chan;
698  cmd.parm.setup.si1 = msg->msg.connect_ind.si1;
699  cmd.parm.setup.si2 = msg->msg.connect_ind.si2;
700  if (card->ptype == ISDN_PTYPE_EURO)
701  strcpy(cmd.parm.setup.eazmsn,
702  act2000_find_eaz(card, msg->msg.connect_ind.eaz));
703  else {
704  cmd.parm.setup.eazmsn[0] = msg->msg.connect_ind.eaz;
705  cmd.parm.setup.eazmsn[1] = 0;
706  }
707  memset(cmd.parm.setup.phone, 0, sizeof(cmd.parm.setup.phone));
708  memcpy(cmd.parm.setup.phone, msg->msg.connect_ind.addr.num,
709  msg->msg.connect_ind.addr.len - 1);
710  cmd.parm.setup.plan = msg->msg.connect_ind.addr.tnp;
711  cmd.parm.setup.screen = 0;
712  if (card->interface.statcallb(&cmd) == 2)
713  actcapi_connect_resp(card, &card->bch[chan], 0x15); /* Reject Call */
714  }
715  break;
716  case 0x0302:
717  /* CONNECT_ACTIVE_IND */
718  chan = find_plci(card, msg->msg.connect_active_ind.plci);
719  if (chan >= 0)
720  switch (card->bch[chan].fsm_state) {
721  case ACT2000_STATE_IWAIT:
722  actcapi_connect_active_resp(card, &card->bch[chan]);
723  break;
724  case ACT2000_STATE_OWAIT:
725  actcapi_connect_active_resp(card, &card->bch[chan]);
726  actcapi_select_b2_protocol_req(card, &card->bch[chan]);
727  break;
728  }
729  break;
730  case 0x8202:
731  /* CONNECT_B3_IND */
732  chan = find_plci(card, msg->msg.connect_b3_ind.plci);
733  if ((chan >= 0) && (card->bch[chan].fsm_state == ACT2000_STATE_IBWAIT)) {
734  card->bch[chan].ncci = msg->msg.connect_b3_ind.ncci;
735  actcapi_connect_b3_resp(card, &card->bch[chan], 0);
736  } else {
737  ctmp = (act2000_chan *)tmp;
738  ctmp->ncci = msg->msg.connect_b3_ind.ncci;
739  actcapi_connect_b3_resp(card, ctmp, 0x11); /* All Card-Cannels busy */
740  }
741  break;
742  case 0x8302:
743  /* CONNECT_B3_ACTIVE_IND */
744  chan = find_ncci(card, msg->msg.connect_b3_active_ind.ncci);
745  if ((chan >= 0) && (card->bch[chan].fsm_state == ACT2000_STATE_BWAIT)) {
746  actcapi_connect_b3_active_resp(card, &card->bch[chan]);
747  cmd.driver = card->myid;
748  cmd.command = ISDN_STAT_BCONN;
749  cmd.arg = chan;
750  card->interface.statcallb(&cmd);
751  }
752  break;
753  case 0x8402:
754  /* DISCONNECT_B3_IND */
755  chan = find_ncci(card, msg->msg.disconnect_b3_ind.ncci);
756  if (chan >= 0) {
757  ctmp = &card->bch[chan];
758  actcapi_disconnect_b3_resp(card, ctmp);
759  switch (ctmp->fsm_state) {
760  case ACT2000_STATE_ACTIVE:
761  ctmp->fsm_state = ACT2000_STATE_DHWAIT2;
762  cmd.driver = card->myid;
763  cmd.command = ISDN_STAT_BHUP;
764  cmd.arg = chan;
765  card->interface.statcallb(&cmd);
766  break;
767  case ACT2000_STATE_BHWAIT2:
768  actcapi_disconnect_req(card, ctmp);
769  ctmp->fsm_state = ACT2000_STATE_DHWAIT;
770  cmd.driver = card->myid;
771  cmd.command = ISDN_STAT_BHUP;
772  cmd.arg = chan;
773  card->interface.statcallb(&cmd);
774  break;
775  }
776  }
777  break;
778  case 0x0402:
779  /* DISCONNECT_IND */
780  chan = find_plci(card, msg->msg.disconnect_ind.plci);
781  if (chan >= 0) {
782  ctmp = &card->bch[chan];
783  actcapi_disconnect_resp(card, ctmp);
784  ctmp->fsm_state = ACT2000_STATE_NULL;
785  cmd.driver = card->myid;
786  cmd.command = ISDN_STAT_DHUP;
787  cmd.arg = chan;
788  card->interface.statcallb(&cmd);
789  } else {
790  ctmp = (act2000_chan *)tmp;
791  ctmp->plci = msg->msg.disconnect_ind.plci;
792  actcapi_disconnect_resp(card, ctmp);
793  }
794  break;
795  case 0x4001:
796  /* SELECT_B2_PROTOCOL_CONF */
797  chan = find_plci(card, msg->msg.select_b2_protocol_conf.plci);
798  if (chan >= 0)
799  switch (card->bch[chan].fsm_state) {
800  case ACT2000_STATE_ICALL:
801  case ACT2000_STATE_OWAIT:
802  ctmp = &card->bch[chan];
803  if (msg->msg.select_b2_protocol_conf.info == 0)
804  actcapi_select_b3_protocol_req(card, ctmp);
805  else {
806  ctmp->fsm_state = ACT2000_STATE_NULL;
807  cmd.driver = card->myid;
808  cmd.command = ISDN_STAT_DHUP;
809  cmd.arg = chan;
810  card->interface.statcallb(&cmd);
811  }
812  break;
813  }
814  break;
815  case 0x8001:
816  /* SELECT_B3_PROTOCOL_CONF */
817  chan = find_plci(card, msg->msg.select_b3_protocol_conf.plci);
818  if (chan >= 0)
819  switch (card->bch[chan].fsm_state) {
820  case ACT2000_STATE_ICALL:
821  case ACT2000_STATE_OWAIT:
822  ctmp = &card->bch[chan];
823  if (msg->msg.select_b3_protocol_conf.info == 0)
824  actcapi_listen_b3_req(card, ctmp);
825  else {
826  ctmp->fsm_state = ACT2000_STATE_NULL;
827  cmd.driver = card->myid;
828  cmd.command = ISDN_STAT_DHUP;
829  cmd.arg = chan;
830  card->interface.statcallb(&cmd);
831  }
832  }
833  break;
834  case 0x8101:
835  /* LISTEN_B3_CONF */
836  chan = find_plci(card, msg->msg.listen_b3_conf.plci);
837  if (chan >= 0)
838  switch (card->bch[chan].fsm_state) {
839  case ACT2000_STATE_ICALL:
840  ctmp = &card->bch[chan];
841  if (msg->msg.listen_b3_conf.info == 0)
842  actcapi_connect_resp(card, ctmp, 0);
843  else {
844  ctmp->fsm_state = ACT2000_STATE_NULL;
845  cmd.driver = card->myid;
846  cmd.command = ISDN_STAT_DHUP;
847  cmd.arg = chan;
848  card->interface.statcallb(&cmd);
849  }
850  break;
851  case ACT2000_STATE_OWAIT:
852  ctmp = &card->bch[chan];
853  if (msg->msg.listen_b3_conf.info == 0) {
854  actcapi_connect_b3_req(card, ctmp);
855  ctmp->fsm_state = ACT2000_STATE_OBWAIT;
856  cmd.driver = card->myid;
857  cmd.command = ISDN_STAT_DCONN;
858  cmd.arg = chan;
859  card->interface.statcallb(&cmd);
860  } else {
861  ctmp->fsm_state = ACT2000_STATE_NULL;
862  cmd.driver = card->myid;
863  cmd.command = ISDN_STAT_DHUP;
864  cmd.arg = chan;
865  card->interface.statcallb(&cmd);
866  }
867  break;
868  }
869  break;
870  case 0x8201:
871  /* CONNECT_B3_CONF */
872  chan = find_plci(card, msg->msg.connect_b3_conf.plci);
873  if ((chan >= 0) && (card->bch[chan].fsm_state == ACT2000_STATE_OBWAIT)) {
874  ctmp = &card->bch[chan];
875  if (msg->msg.connect_b3_conf.info) {
876  ctmp->fsm_state = ACT2000_STATE_NULL;
877  cmd.driver = card->myid;
878  cmd.command = ISDN_STAT_DHUP;
879  cmd.arg = chan;
880  card->interface.statcallb(&cmd);
881  } else {
882  ctmp->ncci = msg->msg.connect_b3_conf.ncci;
883  ctmp->fsm_state = ACT2000_STATE_BWAIT;
884  }
885  }
886  break;
887  case 0x8401:
888  /* DISCONNECT_B3_CONF */
889  chan = find_ncci(card, msg->msg.disconnect_b3_conf.ncci);
890  if ((chan >= 0) && (card->bch[chan].fsm_state == ACT2000_STATE_BHWAIT))
891  card->bch[chan].fsm_state = ACT2000_STATE_BHWAIT2;
892  break;
893  case 0x0702:
894  /* INFO_IND */
895  chan = find_plci(card, msg->msg.info_ind.plci);
896  if (chan >= 0)
897  /* TODO: Eval Charging info / cause */
898  actcapi_info_resp(card, &card->bch[chan]);
899  break;
900  case 0x0401:
901  /* LISTEN_CONF */
902  case 0x0501:
903  /* LISTEN_CONF */
904  case 0xff01:
905  /* MANUFACTURER_CONF */
906  break;
907  case 0xff02:
908  /* MANUFACTURER_IND */
909  if (msg->msg.manuf_msg == 3) {
910  memset(tmp, 0, sizeof(tmp));
911  strncpy(tmp,
912  &msg->msg.manufacturer_ind_err.errstring,
913  msg->hdr.len - 16);
914  if (msg->msg.manufacturer_ind_err.errcode)
915  printk(KERN_WARNING "act2000: %s\n", tmp);
916  else {
917  printk(KERN_DEBUG "act2000: %s\n", tmp);
918  if ((!strncmp(tmp, "INFO: Trace buffer con", 22)) ||
919  (!strncmp(tmp, "INFO: Compile Date/Tim", 22))) {
920  card->flags |= ACT2000_FLAGS_RUNNING;
921  cmd.command = ISDN_STAT_RUN;
922  cmd.driver = card->myid;
923  cmd.arg = 0;
926  actcapi_listen_req(card);
927  card->interface.statcallb(&cmd);
928  }
929  }
930  }
931  break;
932  default:
933  printk(KERN_WARNING "act2000: UNHANDLED Message %04x\n", ccmd);
934  break;
935  }
936  dev_kfree_skb(skb);
937  }
938 }
939 
940 #ifdef DEBUG_MSG
941 static void
942 actcapi_debug_caddr(actcapi_addr *addr)
943 {
944  char tmp[30];
945 
946  printk(KERN_DEBUG " Alen = %d\n", addr->len);
947  if (addr->len > 0)
948  printk(KERN_DEBUG " Atnp = 0x%02x\n", addr->tnp);
949  if (addr->len > 1) {
950  memset(tmp, 0, 30);
951  memcpy(tmp, addr->num, addr->len - 1);
952  printk(KERN_DEBUG " Anum = '%s'\n", tmp);
953  }
954 }
955 
956 static void
957 actcapi_debug_ncpi(actcapi_ncpi *ncpi)
958 {
959  printk(KERN_DEBUG " ncpi.len = %d\n", ncpi->len);
960  if (ncpi->len >= 2)
961  printk(KERN_DEBUG " ncpi.lic = 0x%04x\n", ncpi->lic);
962  if (ncpi->len >= 4)
963  printk(KERN_DEBUG " ncpi.hic = 0x%04x\n", ncpi->hic);
964  if (ncpi->len >= 6)
965  printk(KERN_DEBUG " ncpi.ltc = 0x%04x\n", ncpi->ltc);
966  if (ncpi->len >= 8)
967  printk(KERN_DEBUG " ncpi.htc = 0x%04x\n", ncpi->htc);
968  if (ncpi->len >= 10)
969  printk(KERN_DEBUG " ncpi.loc = 0x%04x\n", ncpi->loc);
970  if (ncpi->len >= 12)
971  printk(KERN_DEBUG " ncpi.hoc = 0x%04x\n", ncpi->hoc);
972  if (ncpi->len >= 13)
973  printk(KERN_DEBUG " ncpi.mod = %d\n", ncpi->modulo);
974 }
975 
976 static void
977 actcapi_debug_dlpd(actcapi_dlpd *dlpd)
978 {
979  printk(KERN_DEBUG " dlpd.len = %d\n", dlpd->len);
980  if (dlpd->len >= 2)
981  printk(KERN_DEBUG " dlpd.dlen = 0x%04x\n", dlpd->dlen);
982  if (dlpd->len >= 3)
983  printk(KERN_DEBUG " dlpd.laa = 0x%02x\n", dlpd->laa);
984  if (dlpd->len >= 4)
985  printk(KERN_DEBUG " dlpd.lab = 0x%02x\n", dlpd->lab);
986  if (dlpd->len >= 5)
987  printk(KERN_DEBUG " dlpd.modulo = %d\n", dlpd->modulo);
988  if (dlpd->len >= 6)
989  printk(KERN_DEBUG " dlpd.win = %d\n", dlpd->win);
990 }
991 
992 #ifdef DEBUG_DUMP_SKB
993 static void dump_skb(struct sk_buff *skb) {
994  char tmp[80];
995  char *p = skb->data;
996  char *t = tmp;
997  int i;
998 
999  for (i = 0; i < skb->len; i++) {
1000  t += sprintf(t, "%02x ", *p++ & 0xff);
1001  if ((i & 0x0f) == 8) {
1002  printk(KERN_DEBUG "dump: %s\n", tmp);
1003  t = tmp;
1004  }
1005  }
1006  if (i & 0x07)
1007  printk(KERN_DEBUG "dump: %s\n", tmp);
1008 }
1009 #endif
1010 
1011 void
1013 {
1014  actcapi_msg *msg = (actcapi_msg *)skb->data;
1015  char *descr;
1016  int i;
1017  char tmp[170];
1018 
1019 #ifndef DEBUG_DATA_MSG
1020  if (msg->hdr.cmd.cmd == 0x86)
1021  return;
1022 #endif
1023  descr = "INVALID";
1024 #ifdef DEBUG_DUMP_SKB
1025  dump_skb(skb);
1026 #endif
1027  for (i = 0; i < ARRAY_SIZE(valid_msg); i++)
1028  if ((msg->hdr.cmd.cmd == valid_msg[i].cmd.cmd) &&
1029  (msg->hdr.cmd.subcmd == valid_msg[i].cmd.subcmd)) {
1030  descr = valid_msg[i].description;
1031  break;
1032  }
1033  printk(KERN_DEBUG "%s %s msg\n", direction ? "Outgoing" : "Incoming", descr);
1034  printk(KERN_DEBUG " ApplID = %d\n", msg->hdr.applicationID);
1035  printk(KERN_DEBUG " Len = %d\n", msg->hdr.len);
1036  printk(KERN_DEBUG " MsgNum = 0x%04x\n", msg->hdr.msgnum);
1037  printk(KERN_DEBUG " Cmd = 0x%02x\n", msg->hdr.cmd.cmd);
1038  printk(KERN_DEBUG " SubCmd = 0x%02x\n", msg->hdr.cmd.subcmd);
1039  switch (i) {
1040  case 0:
1041  /* DATA B3 IND */
1042  printk(KERN_DEBUG " BLOCK = 0x%02x\n",
1043  msg->msg.data_b3_ind.blocknr);
1044  break;
1045  case 2:
1046  /* CONNECT CONF */
1047  printk(KERN_DEBUG " PLCI = 0x%04x\n",
1048  msg->msg.connect_conf.plci);
1049  printk(KERN_DEBUG " Info = 0x%04x\n",
1050  msg->msg.connect_conf.info);
1051  break;
1052  case 3:
1053  /* CONNECT IND */
1054  printk(KERN_DEBUG " PLCI = 0x%04x\n",
1055  msg->msg.connect_ind.plci);
1056  printk(KERN_DEBUG " Contr = %d\n",
1057  msg->msg.connect_ind.controller);
1058  printk(KERN_DEBUG " SI1 = %d\n",
1059  msg->msg.connect_ind.si1);
1060  printk(KERN_DEBUG " SI2 = %d\n",
1061  msg->msg.connect_ind.si2);
1062  printk(KERN_DEBUG " EAZ = '%c'\n",
1063  msg->msg.connect_ind.eaz);
1064  actcapi_debug_caddr(&msg->msg.connect_ind.addr);
1065  break;
1066  case 5:
1067  /* CONNECT ACTIVE IND */
1068  printk(KERN_DEBUG " PLCI = 0x%04x\n",
1069  msg->msg.connect_active_ind.plci);
1070  actcapi_debug_caddr(&msg->msg.connect_active_ind.addr);
1071  break;
1072  case 8:
1073  /* LISTEN CONF */
1074  printk(KERN_DEBUG " Contr = %d\n",
1075  msg->msg.listen_conf.controller);
1076  printk(KERN_DEBUG " Info = 0x%04x\n",
1077  msg->msg.listen_conf.info);
1078  break;
1079  case 11:
1080  /* INFO IND */
1081  printk(KERN_DEBUG " PLCI = 0x%04x\n",
1082  msg->msg.info_ind.plci);
1083  printk(KERN_DEBUG " Imsk = 0x%04x\n",
1084  msg->msg.info_ind.nr.mask);
1085  if (msg->hdr.len > 12) {
1086  int l = msg->hdr.len - 12;
1087  int j;
1088  char *p = tmp;
1089  for (j = 0; j < l; j++)
1090  p += sprintf(p, "%02x ", msg->msg.info_ind.el.display[j]);
1091  printk(KERN_DEBUG " D = '%s'\n", tmp);
1092  }
1093  break;
1094  case 14:
1095  /* SELECT B2 PROTOCOL CONF */
1096  printk(KERN_DEBUG " PLCI = 0x%04x\n",
1097  msg->msg.select_b2_protocol_conf.plci);
1098  printk(KERN_DEBUG " Info = 0x%04x\n",
1099  msg->msg.select_b2_protocol_conf.info);
1100  break;
1101  case 15:
1102  /* SELECT B3 PROTOCOL CONF */
1103  printk(KERN_DEBUG " PLCI = 0x%04x\n",
1104  msg->msg.select_b3_protocol_conf.plci);
1105  printk(KERN_DEBUG " Info = 0x%04x\n",
1106  msg->msg.select_b3_protocol_conf.info);
1107  break;
1108  case 16:
1109  /* LISTEN B3 CONF */
1110  printk(KERN_DEBUG " PLCI = 0x%04x\n",
1111  msg->msg.listen_b3_conf.plci);
1112  printk(KERN_DEBUG " Info = 0x%04x\n",
1113  msg->msg.listen_b3_conf.info);
1114  break;
1115  case 18:
1116  /* CONNECT B3 IND */
1117  printk(KERN_DEBUG " NCCI = 0x%04x\n",
1118  msg->msg.connect_b3_ind.ncci);
1119  printk(KERN_DEBUG " PLCI = 0x%04x\n",
1120  msg->msg.connect_b3_ind.plci);
1121  actcapi_debug_ncpi(&msg->msg.connect_b3_ind.ncpi);
1122  break;
1123  case 19:
1124  /* CONNECT B3 ACTIVE IND */
1125  printk(KERN_DEBUG " NCCI = 0x%04x\n",
1126  msg->msg.connect_b3_active_ind.ncci);
1127  actcapi_debug_ncpi(&msg->msg.connect_b3_active_ind.ncpi);
1128  break;
1129  case 26:
1130  /* MANUFACTURER IND */
1131  printk(KERN_DEBUG " Mmsg = 0x%02x\n",
1132  msg->msg.manufacturer_ind_err.manuf_msg);
1133  switch (msg->msg.manufacturer_ind_err.manuf_msg) {
1134  case 3:
1135  printk(KERN_DEBUG " Contr = %d\n",
1136  msg->msg.manufacturer_ind_err.controller);
1137  printk(KERN_DEBUG " Code = 0x%08x\n",
1138  msg->msg.manufacturer_ind_err.errcode);
1139  memset(tmp, 0, sizeof(tmp));
1140  strncpy(tmp, &msg->msg.manufacturer_ind_err.errstring,
1141  msg->hdr.len - 16);
1142  printk(KERN_DEBUG " Emsg = '%s'\n", tmp);
1143  break;
1144  }
1145  break;
1146  case 30:
1147  /* LISTEN REQ */
1148  printk(KERN_DEBUG " Imsk = 0x%08x\n",
1149  msg->msg.listen_req.infomask);
1150  printk(KERN_DEBUG " Emsk = 0x%04x\n",
1151  msg->msg.listen_req.eazmask);
1152  printk(KERN_DEBUG " Smsk = 0x%04x\n",
1153  msg->msg.listen_req.simask);
1154  break;
1155  case 35:
1156  /* SELECT_B2_PROTOCOL_REQ */
1157  printk(KERN_DEBUG " PLCI = 0x%04x\n",
1158  msg->msg.select_b2_protocol_req.plci);
1159  printk(KERN_DEBUG " prot = 0x%02x\n",
1160  msg->msg.select_b2_protocol_req.protocol);
1161  if (msg->hdr.len >= 11)
1162  printk(KERN_DEBUG "No dlpd\n");
1163  else
1164  actcapi_debug_dlpd(&msg->msg.select_b2_protocol_req.dlpd);
1165  break;
1166  case 44:
1167  /* CONNECT RESP */
1168  printk(KERN_DEBUG " PLCI = 0x%04x\n",
1169  msg->msg.connect_resp.plci);
1170  printk(KERN_DEBUG " CAUSE = 0x%02x\n",
1171  msg->msg.connect_resp.rejectcause);
1172  break;
1173  case 45:
1174  /* CONNECT ACTIVE RESP */
1175  printk(KERN_DEBUG " PLCI = 0x%04x\n",
1176  msg->msg.connect_active_resp.plci);
1177  break;
1178  }
1179 }
1180 #endif