GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / linux / linux-2.6.36 / drivers / isdn / act2000 / capi.c
blob50155e6b3890e7d584894e908cda56efa89cdb09
1 /* $Id: capi.c,v 1.9.6.2 2001/09/23 22:24:32 Exp $
3 * ISDN lowlevel-module for the IBM ISDN-S0 Active 2000.
4 * CAPI encoder/decoder
6 * Author Fritz Elfert
7 * Copyright by Fritz Elfert <fritz@isdn4linux.de>
8 *
9 * This software may be used and distributed according to the terms
10 * of the GNU General Public License, incorporated herein by reference.
12 * Thanks to Friedemann Baitinger and IBM Germany
16 #include "act2000.h"
17 #include "capi.h"
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},
81 #define num_valid_imsg 27 /* MANUFACTURER_IND */
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
90 int
91 actcapi_chkhdr(act2000_card * card, actcapi_msghdr *hdr)
93 int i;
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);
104 return 0;
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;\
119 #define ACTCAPI_CHKSKB if (!skb) { \
120 printk(KERN_WARNING "actcapi: alloc_skb failed\n"); \
121 return; \
124 #define ACTCAPI_QUEUE_TX { \
125 actcapi_debug_msg(skb, 1); \
126 skb_queue_tail(&card->sndq, skb); \
127 act2000_schedule_tx(card); \
131 actcapi_listen_req(act2000_card *card)
133 __u16 eazmask = 0;
134 int i;
135 actcapi_msg *m;
136 struct sk_buff *skb;
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;
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 */
149 ACTCAPI_QUEUE_TX;
150 return 0;
154 actcapi_connect_req(act2000_card *card, act2000_chan *chan, char *phone,
155 char eaz, int si1, int si2)
157 actcapi_msg *m;
158 struct sk_buff *skb;
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;
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;
176 ACTCAPI_QUEUE_TX;
177 return 0;
180 static void
181 actcapi_connect_b3_req(act2000_card *card, act2000_chan *chan)
183 actcapi_msg *m;
184 struct sk_buff *skb;
186 ACTCAPI_MKHDR(17, 0x82, 0x00);
187 ACTCAPI_CHKSKB;
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;
193 ACTCAPI_QUEUE_TX;
197 * Set net type (1TR6) or (EDSS1)
200 actcapi_manufacturer_req_net(act2000_card *card)
202 actcapi_msg *m;
203 struct sk_buff *skb;
205 ACTCAPI_MKHDR(5, 0xff, 0x00);
206 if (!skb) {
207 printk(KERN_WARNING "actcapi: alloc_skb failed\n");
208 return -ENOMEM;
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;
213 ACTCAPI_QUEUE_TX;
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 &=
217 ~(ISDN_FEATURE_P_UNKNOWN | ISDN_FEATURE_P_EURO | ISDN_FEATURE_P_1TR6);
218 card->interface.features |=
219 ((card->ptype == ISDN_PTYPE_EURO)?ISDN_FEATURE_P_EURO:ISDN_FEATURE_P_1TR6);
220 return 0;
224 * Switch V.42 on or off
228 * Set error-handler
231 actcapi_manufacturer_req_errh(act2000_card *card)
233 actcapi_msg *m;
234 struct sk_buff *skb;
236 ACTCAPI_MKHDR(4, 0xff, 0x00);
237 if (!skb) {
239 printk(KERN_WARNING "actcapi: alloc_skb failed\n");
240 return -ENOMEM;
242 m->msg.manufacturer_req_err.manuf_msg = 0x03;
243 m->msg.manufacturer_req_err.controller = 0;
244 ACTCAPI_QUEUE_TX;
245 return 0;
249 * Set MSN-Mapping.
252 actcapi_manufacturer_req_msn(act2000_card *card)
254 msn_entry *p = card->msn_list;
255 actcapi_msg *m;
256 struct sk_buff *skb;
257 int len;
259 while (p) {
260 int i;
262 len = strlen(p->msn);
263 for (i = 0; i < 2; i++) {
264 ACTCAPI_MKHDR(6 + len, 0xff, 0x00);
265 if (!skb) {
266 printk(KERN_WARNING "actcapi: alloc_skb failed\n");
267 return -ENOMEM;
269 m->msg.manufacturer_req_msn.manuf_msg = 0x13 + i;
270 m->msg.manufacturer_req_msn.controller = 0;
271 m->msg.manufacturer_req_msn.msnmap.eaz = p->eaz;
272 m->msg.manufacturer_req_msn.msnmap.len = len;
273 memcpy(m->msg.manufacturer_req_msn.msnmap.msn, p->msn, len);
274 ACTCAPI_QUEUE_TX;
276 p = p->next;
278 return 0;
281 void
282 actcapi_select_b2_protocol_req(act2000_card *card, act2000_chan *chan)
284 actcapi_msg *m;
285 struct sk_buff *skb;
287 ACTCAPI_MKHDR(10, 0x40, 0x00);
288 ACTCAPI_CHKSKB;
289 m->msg.select_b2_protocol_req.plci = chan->plci;
290 memset(&m->msg.select_b2_protocol_req.dlpd, 0,
291 sizeof(m->msg.select_b2_protocol_req.dlpd));
292 m->msg.select_b2_protocol_req.dlpd.len = 6;
293 switch (chan->l2prot) {
294 case ISDN_PROTO_L2_TRANS:
295 m->msg.select_b2_protocol_req.protocol = 0x03;
296 m->msg.select_b2_protocol_req.dlpd.dlen = 4000;
297 break;
298 case ISDN_PROTO_L2_HDLC:
299 m->msg.select_b2_protocol_req.protocol = 0x02;
300 m->msg.select_b2_protocol_req.dlpd.dlen = 4000;
301 break;
302 case ISDN_PROTO_L2_X75I:
303 case ISDN_PROTO_L2_X75UI:
304 case ISDN_PROTO_L2_X75BUI:
305 m->msg.select_b2_protocol_req.protocol = 0x01;
306 m->msg.select_b2_protocol_req.dlpd.dlen = 4000;
307 m->msg.select_b2_protocol_req.dlpd.laa = 3;
308 m->msg.select_b2_protocol_req.dlpd.lab = 1;
309 m->msg.select_b2_protocol_req.dlpd.win = 7;
310 m->msg.select_b2_protocol_req.dlpd.modulo = 8;
311 break;
313 ACTCAPI_QUEUE_TX;
316 static void
317 actcapi_select_b3_protocol_req(act2000_card *card, act2000_chan *chan)
319 actcapi_msg *m;
320 struct sk_buff *skb;
322 ACTCAPI_MKHDR(17, 0x80, 0x00);
323 ACTCAPI_CHKSKB;
324 m->msg.select_b3_protocol_req.plci = chan->plci;
325 memset(&m->msg.select_b3_protocol_req.ncpd, 0,
326 sizeof(m->msg.select_b3_protocol_req.ncpd));
327 switch (chan->l3prot) {
328 case ISDN_PROTO_L3_TRANS:
329 m->msg.select_b3_protocol_req.protocol = 0x04;
330 m->msg.select_b3_protocol_req.ncpd.len = 13;
331 m->msg.select_b3_protocol_req.ncpd.modulo = 8;
332 break;
334 ACTCAPI_QUEUE_TX;
337 static void
338 actcapi_listen_b3_req(act2000_card *card, act2000_chan *chan)
340 actcapi_msg *m;
341 struct sk_buff *skb;
343 ACTCAPI_MKHDR(2, 0x81, 0x00);
344 ACTCAPI_CHKSKB;
345 m->msg.listen_b3_req.plci = chan->plci;
346 ACTCAPI_QUEUE_TX;
349 static void
350 actcapi_disconnect_req(act2000_card *card, act2000_chan *chan)
352 actcapi_msg *m;
353 struct sk_buff *skb;
355 ACTCAPI_MKHDR(3, 0x04, 0x00);
356 ACTCAPI_CHKSKB;
357 m->msg.disconnect_req.plci = chan->plci;
358 m->msg.disconnect_req.cause = 0;
359 ACTCAPI_QUEUE_TX;
362 void
363 actcapi_disconnect_b3_req(act2000_card *card, act2000_chan *chan)
365 actcapi_msg *m;
366 struct sk_buff *skb;
368 ACTCAPI_MKHDR(17, 0x84, 0x00);
369 ACTCAPI_CHKSKB;
370 m->msg.disconnect_b3_req.ncci = chan->ncci;
371 memset(&m->msg.disconnect_b3_req.ncpi, 0,
372 sizeof(m->msg.disconnect_b3_req.ncpi));
373 m->msg.disconnect_b3_req.ncpi.len = 13;
374 m->msg.disconnect_b3_req.ncpi.modulo = 8;
375 chan->fsm_state = ACT2000_STATE_BHWAIT;
376 ACTCAPI_QUEUE_TX;
379 void
380 actcapi_connect_resp(act2000_card *card, act2000_chan *chan, __u8 cause)
382 actcapi_msg *m;
383 struct sk_buff *skb;
385 ACTCAPI_MKHDR(3, 0x02, 0x03);
386 ACTCAPI_CHKSKB;
387 m->msg.connect_resp.plci = chan->plci;
388 m->msg.connect_resp.rejectcause = cause;
389 if (cause) {
390 chan->fsm_state = ACT2000_STATE_NULL;
391 chan->plci = 0x8000;
392 } else
393 chan->fsm_state = ACT2000_STATE_IWAIT;
394 ACTCAPI_QUEUE_TX;
397 static void
398 actcapi_connect_active_resp(act2000_card *card, act2000_chan *chan)
400 actcapi_msg *m;
401 struct sk_buff *skb;
403 ACTCAPI_MKHDR(2, 0x03, 0x03);
404 ACTCAPI_CHKSKB;
405 m->msg.connect_resp.plci = chan->plci;
406 if (chan->fsm_state == ACT2000_STATE_IWAIT)
407 chan->fsm_state = ACT2000_STATE_IBWAIT;
408 ACTCAPI_QUEUE_TX;
411 static void
412 actcapi_connect_b3_resp(act2000_card *card, act2000_chan *chan, __u8 rejectcause)
414 actcapi_msg *m;
415 struct sk_buff *skb;
417 ACTCAPI_MKHDR((rejectcause?3:17), 0x82, 0x03);
418 ACTCAPI_CHKSKB;
419 m->msg.connect_b3_resp.ncci = chan->ncci;
420 m->msg.connect_b3_resp.rejectcause = rejectcause;
421 if (!rejectcause) {
422 memset(&m->msg.connect_b3_resp.ncpi, 0,
423 sizeof(m->msg.connect_b3_resp.ncpi));
424 m->msg.connect_b3_resp.ncpi.len = 13;
425 m->msg.connect_b3_resp.ncpi.modulo = 8;
426 chan->fsm_state = ACT2000_STATE_BWAIT;
428 ACTCAPI_QUEUE_TX;
431 static void
432 actcapi_connect_b3_active_resp(act2000_card *card, act2000_chan *chan)
434 actcapi_msg *m;
435 struct sk_buff *skb;
437 ACTCAPI_MKHDR(2, 0x83, 0x03);
438 ACTCAPI_CHKSKB;
439 m->msg.connect_b3_active_resp.ncci = chan->ncci;
440 chan->fsm_state = ACT2000_STATE_ACTIVE;
441 ACTCAPI_QUEUE_TX;
444 static void
445 actcapi_info_resp(act2000_card *card, act2000_chan *chan)
447 actcapi_msg *m;
448 struct sk_buff *skb;
450 ACTCAPI_MKHDR(2, 0x07, 0x03);
451 ACTCAPI_CHKSKB;
452 m->msg.info_resp.plci = chan->plci;
453 ACTCAPI_QUEUE_TX;
456 static void
457 actcapi_disconnect_b3_resp(act2000_card *card, act2000_chan *chan)
459 actcapi_msg *m;
460 struct sk_buff *skb;
462 ACTCAPI_MKHDR(2, 0x84, 0x03);
463 ACTCAPI_CHKSKB;
464 m->msg.disconnect_b3_resp.ncci = chan->ncci;
465 chan->ncci = 0x8000;
466 chan->queued = 0;
467 ACTCAPI_QUEUE_TX;
470 static void
471 actcapi_disconnect_resp(act2000_card *card, act2000_chan *chan)
473 actcapi_msg *m;
474 struct sk_buff *skb;
476 ACTCAPI_MKHDR(2, 0x04, 0x03);
477 ACTCAPI_CHKSKB;
478 m->msg.disconnect_resp.plci = chan->plci;
479 chan->plci = 0x8000;
480 ACTCAPI_QUEUE_TX;
483 static int
484 new_plci(act2000_card *card, __u16 plci)
486 int i;
487 for (i = 0; i < ACT2000_BCH; i++)
488 if (card->bch[i].plci == 0x8000) {
489 card->bch[i].plci = plci;
490 return i;
492 return -1;
495 static int
496 find_plci(act2000_card *card, __u16 plci)
498 int i;
499 for (i = 0; i < ACT2000_BCH; i++)
500 if (card->bch[i].plci == plci)
501 return i;
502 return -1;
505 static int
506 find_ncci(act2000_card *card, __u16 ncci)
508 int i;
509 for (i = 0; i < ACT2000_BCH; i++)
510 if (card->bch[i].ncci == ncci)
511 return i;
512 return -1;
515 static int
516 find_dialing(act2000_card *card, __u16 callref)
518 int i;
519 for (i = 0; i < ACT2000_BCH; i++)
520 if ((card->bch[i].callref == callref) &&
521 (card->bch[i].fsm_state == ACT2000_STATE_OCALL))
522 return i;
523 return -1;
526 static int
527 actcapi_data_b3_ind(act2000_card *card, struct sk_buff *skb) {
528 __u16 plci;
529 __u16 ncci;
530 __u16 controller;
531 __u8 blocknr;
532 int chan;
533 actcapi_msg *msg = (actcapi_msg *)skb->data;
535 EVAL_NCCI(msg->msg.data_b3_ind.fakencci, plci, controller, ncci);
536 chan = find_ncci(card, ncci);
537 if (chan < 0)
538 return 0;
539 if (card->bch[chan].fsm_state != ACT2000_STATE_ACTIVE)
540 return 0;
541 if (card->bch[chan].plci != plci)
542 return 0;
543 blocknr = msg->msg.data_b3_ind.blocknr;
544 skb_pull(skb, 19);
545 card->interface.rcvcallb_skb(card->myid, chan, skb);
546 if (!(skb = alloc_skb(11, GFP_ATOMIC))) {
547 printk(KERN_WARNING "actcapi: alloc_skb failed\n");
548 return 1;
550 msg = (actcapi_msg *)skb_put(skb, 11);
551 msg->hdr.len = 11;
552 msg->hdr.applicationID = 1;
553 msg->hdr.cmd.cmd = 0x86;
554 msg->hdr.cmd.subcmd = 0x03;
555 msg->hdr.msgnum = actcapi_nextsmsg(card);
556 msg->msg.data_b3_resp.ncci = ncci;
557 msg->msg.data_b3_resp.blocknr = blocknr;
558 ACTCAPI_QUEUE_TX;
559 return 1;
563 * Walk over ackq, unlink DATA_B3_REQ from it, if
564 * ncci and blocknr are matching.
565 * Decrement queued-bytes counter.
567 static int
568 handle_ack(act2000_card *card, act2000_chan *chan, __u8 blocknr) {
569 unsigned long flags;
570 struct sk_buff *skb;
571 struct sk_buff *tmp;
572 struct actcapi_msg *m;
573 int ret = 0;
575 spin_lock_irqsave(&card->lock, flags);
576 skb = skb_peek(&card->ackq);
577 spin_unlock_irqrestore(&card->lock, flags);
578 if (!skb) {
579 printk(KERN_WARNING "act2000: handle_ack nothing found!\n");
580 return 0;
582 tmp = skb;
583 while (1) {
584 m = (actcapi_msg *)tmp->data;
585 if ((((m->msg.data_b3_req.fakencci >> 8) & 0xff) == chan->ncci) &&
586 (m->msg.data_b3_req.blocknr == blocknr)) {
587 /* found corresponding DATA_B3_REQ */
588 skb_unlink(tmp, &card->ackq);
589 chan->queued -= m->msg.data_b3_req.datalen;
590 if (m->msg.data_b3_req.flags)
591 ret = m->msg.data_b3_req.datalen;
592 dev_kfree_skb(tmp);
593 if (chan->queued < 0)
594 chan->queued = 0;
595 return ret;
597 spin_lock_irqsave(&card->lock, flags);
598 tmp = skb_peek((struct sk_buff_head *)tmp);
599 spin_unlock_irqrestore(&card->lock, flags);
600 if ((tmp == skb) || (tmp == NULL)) {
601 /* reached end of queue */
602 printk(KERN_WARNING "act2000: handle_ack nothing found!\n");
603 return 0;
608 void
609 actcapi_dispatch(struct work_struct *work)
611 struct act2000_card *card =
612 container_of(work, struct act2000_card, rcv_tq);
613 struct sk_buff *skb;
614 actcapi_msg *msg;
615 __u16 ccmd;
616 int chan;
617 int len;
618 act2000_chan *ctmp;
619 isdn_ctrl cmd;
620 char tmp[170];
622 while ((skb = skb_dequeue(&card->rcvq))) {
623 actcapi_debug_msg(skb, 0);
624 msg = (actcapi_msg *)skb->data;
625 ccmd = ((msg->hdr.cmd.cmd << 8) | msg->hdr.cmd.subcmd);
626 switch (ccmd) {
627 case 0x8602:
628 /* DATA_B3_IND */
629 if (actcapi_data_b3_ind(card, skb))
630 return;
631 break;
632 case 0x8601:
633 /* DATA_B3_CONF */
634 chan = find_ncci(card, msg->msg.data_b3_conf.ncci);
635 if ((chan >= 0) && (card->bch[chan].fsm_state == ACT2000_STATE_ACTIVE)) {
636 if (msg->msg.data_b3_conf.info != 0)
637 printk(KERN_WARNING "act2000: DATA_B3_CONF: %04x\n",
638 msg->msg.data_b3_conf.info);
639 len = handle_ack(card, &card->bch[chan],
640 msg->msg.data_b3_conf.blocknr);
641 if (len) {
642 cmd.driver = card->myid;
643 cmd.command = ISDN_STAT_BSENT;
644 cmd.arg = chan;
645 cmd.parm.length = len;
646 card->interface.statcallb(&cmd);
649 break;
650 case 0x0201:
651 /* CONNECT_CONF */
652 chan = find_dialing(card, msg->hdr.msgnum);
653 if (chan >= 0) {
654 if (msg->msg.connect_conf.info) {
655 card->bch[chan].fsm_state = ACT2000_STATE_NULL;
656 cmd.driver = card->myid;
657 cmd.command = ISDN_STAT_DHUP;
658 cmd.arg = chan;
659 card->interface.statcallb(&cmd);
660 } else {
661 card->bch[chan].fsm_state = ACT2000_STATE_OWAIT;
662 card->bch[chan].plci = msg->msg.connect_conf.plci;
665 break;
666 case 0x0202:
667 /* CONNECT_IND */
668 chan = new_plci(card, msg->msg.connect_ind.plci);
669 if (chan < 0) {
670 ctmp = (act2000_chan *)tmp;
671 ctmp->plci = msg->msg.connect_ind.plci;
672 actcapi_connect_resp(card, ctmp, 0x11); /* All Card-Cannels busy */
673 } else {
674 card->bch[chan].fsm_state = ACT2000_STATE_ICALL;
675 cmd.driver = card->myid;
676 cmd.command = ISDN_STAT_ICALL;
677 cmd.arg = chan;
678 cmd.parm.setup.si1 = msg->msg.connect_ind.si1;
679 cmd.parm.setup.si2 = msg->msg.connect_ind.si2;
680 if (card->ptype == ISDN_PTYPE_EURO)
681 strcpy(cmd.parm.setup.eazmsn,
682 act2000_find_eaz(card, msg->msg.connect_ind.eaz));
683 else {
684 cmd.parm.setup.eazmsn[0] = msg->msg.connect_ind.eaz;
685 cmd.parm.setup.eazmsn[1] = 0;
687 memset(cmd.parm.setup.phone, 0, sizeof(cmd.parm.setup.phone));
688 memcpy(cmd.parm.setup.phone, msg->msg.connect_ind.addr.num,
689 msg->msg.connect_ind.addr.len - 1);
690 cmd.parm.setup.plan = msg->msg.connect_ind.addr.tnp;
691 cmd.parm.setup.screen = 0;
692 if (card->interface.statcallb(&cmd) == 2)
693 actcapi_connect_resp(card, &card->bch[chan], 0x15); /* Reject Call */
695 break;
696 case 0x0302:
697 /* CONNECT_ACTIVE_IND */
698 chan = find_plci(card, msg->msg.connect_active_ind.plci);
699 if (chan >= 0)
700 switch (card->bch[chan].fsm_state) {
701 case ACT2000_STATE_IWAIT:
702 actcapi_connect_active_resp(card, &card->bch[chan]);
703 break;
704 case ACT2000_STATE_OWAIT:
705 actcapi_connect_active_resp(card, &card->bch[chan]);
706 actcapi_select_b2_protocol_req(card, &card->bch[chan]);
707 break;
709 break;
710 case 0x8202:
711 /* CONNECT_B3_IND */
712 chan = find_plci(card, msg->msg.connect_b3_ind.plci);
713 if ((chan >= 0) && (card->bch[chan].fsm_state == ACT2000_STATE_IBWAIT)) {
714 card->bch[chan].ncci = msg->msg.connect_b3_ind.ncci;
715 actcapi_connect_b3_resp(card, &card->bch[chan], 0);
716 } else {
717 ctmp = (act2000_chan *)tmp;
718 ctmp->ncci = msg->msg.connect_b3_ind.ncci;
719 actcapi_connect_b3_resp(card, ctmp, 0x11); /* All Card-Cannels busy */
721 break;
722 case 0x8302:
723 /* CONNECT_B3_ACTIVE_IND */
724 chan = find_ncci(card, msg->msg.connect_b3_active_ind.ncci);
725 if ((chan >= 0) && (card->bch[chan].fsm_state == ACT2000_STATE_BWAIT)) {
726 actcapi_connect_b3_active_resp(card, &card->bch[chan]);
727 cmd.driver = card->myid;
728 cmd.command = ISDN_STAT_BCONN;
729 cmd.arg = chan;
730 card->interface.statcallb(&cmd);
732 break;
733 case 0x8402:
734 /* DISCONNECT_B3_IND */
735 chan = find_ncci(card, msg->msg.disconnect_b3_ind.ncci);
736 if (chan >= 0) {
737 ctmp = &card->bch[chan];
738 actcapi_disconnect_b3_resp(card, ctmp);
739 switch (ctmp->fsm_state) {
740 case ACT2000_STATE_ACTIVE:
741 ctmp->fsm_state = ACT2000_STATE_DHWAIT2;
742 cmd.driver = card->myid;
743 cmd.command = ISDN_STAT_BHUP;
744 cmd.arg = chan;
745 card->interface.statcallb(&cmd);
746 break;
747 case ACT2000_STATE_BHWAIT2:
748 actcapi_disconnect_req(card, ctmp);
749 ctmp->fsm_state = ACT2000_STATE_DHWAIT;
750 cmd.driver = card->myid;
751 cmd.command = ISDN_STAT_BHUP;
752 cmd.arg = chan;
753 card->interface.statcallb(&cmd);
754 break;
757 break;
758 case 0x0402:
759 /* DISCONNECT_IND */
760 chan = find_plci(card, msg->msg.disconnect_ind.plci);
761 if (chan >= 0) {
762 ctmp = &card->bch[chan];
763 actcapi_disconnect_resp(card, ctmp);
764 ctmp->fsm_state = ACT2000_STATE_NULL;
765 cmd.driver = card->myid;
766 cmd.command = ISDN_STAT_DHUP;
767 cmd.arg = chan;
768 card->interface.statcallb(&cmd);
769 } else {
770 ctmp = (act2000_chan *)tmp;
771 ctmp->plci = msg->msg.disconnect_ind.plci;
772 actcapi_disconnect_resp(card, ctmp);
774 break;
775 case 0x4001:
776 /* SELECT_B2_PROTOCOL_CONF */
777 chan = find_plci(card, msg->msg.select_b2_protocol_conf.plci);
778 if (chan >= 0)
779 switch (card->bch[chan].fsm_state) {
780 case ACT2000_STATE_ICALL:
781 case ACT2000_STATE_OWAIT:
782 ctmp = &card->bch[chan];
783 if (msg->msg.select_b2_protocol_conf.info == 0)
784 actcapi_select_b3_protocol_req(card, ctmp);
785 else {
786 ctmp->fsm_state = ACT2000_STATE_NULL;
787 cmd.driver = card->myid;
788 cmd.command = ISDN_STAT_DHUP;
789 cmd.arg = chan;
790 card->interface.statcallb(&cmd);
792 break;
794 break;
795 case 0x8001:
796 /* SELECT_B3_PROTOCOL_CONF */
797 chan = find_plci(card, msg->msg.select_b3_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_b3_protocol_conf.info == 0)
804 actcapi_listen_b3_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);
813 break;
814 case 0x8101:
815 /* LISTEN_B3_CONF */
816 chan = find_plci(card, msg->msg.listen_b3_conf.plci);
817 if (chan >= 0)
818 switch (card->bch[chan].fsm_state) {
819 case ACT2000_STATE_ICALL:
820 ctmp = &card->bch[chan];
821 if (msg->msg.listen_b3_conf.info == 0)
822 actcapi_connect_resp(card, ctmp, 0);
823 else {
824 ctmp->fsm_state = ACT2000_STATE_NULL;
825 cmd.driver = card->myid;
826 cmd.command = ISDN_STAT_DHUP;
827 cmd.arg = chan;
828 card->interface.statcallb(&cmd);
830 break;
831 case ACT2000_STATE_OWAIT:
832 ctmp = &card->bch[chan];
833 if (msg->msg.listen_b3_conf.info == 0) {
834 actcapi_connect_b3_req(card, ctmp);
835 ctmp->fsm_state = ACT2000_STATE_OBWAIT;
836 cmd.driver = card->myid;
837 cmd.command = ISDN_STAT_DCONN;
838 cmd.arg = chan;
839 card->interface.statcallb(&cmd);
840 } else {
841 ctmp->fsm_state = ACT2000_STATE_NULL;
842 cmd.driver = card->myid;
843 cmd.command = ISDN_STAT_DHUP;
844 cmd.arg = chan;
845 card->interface.statcallb(&cmd);
847 break;
849 break;
850 case 0x8201:
851 /* CONNECT_B3_CONF */
852 chan = find_plci(card, msg->msg.connect_b3_conf.plci);
853 if ((chan >= 0) && (card->bch[chan].fsm_state == ACT2000_STATE_OBWAIT)) {
854 ctmp = &card->bch[chan];
855 if (msg->msg.connect_b3_conf.info) {
856 ctmp->fsm_state = ACT2000_STATE_NULL;
857 cmd.driver = card->myid;
858 cmd.command = ISDN_STAT_DHUP;
859 cmd.arg = chan;
860 card->interface.statcallb(&cmd);
861 } else {
862 ctmp->ncci = msg->msg.connect_b3_conf.ncci;
863 ctmp->fsm_state = ACT2000_STATE_BWAIT;
866 break;
867 case 0x8401:
868 /* DISCONNECT_B3_CONF */
869 chan = find_ncci(card, msg->msg.disconnect_b3_conf.ncci);
870 if ((chan >= 0) && (card->bch[chan].fsm_state == ACT2000_STATE_BHWAIT))
871 card->bch[chan].fsm_state = ACT2000_STATE_BHWAIT2;
872 break;
873 case 0x0702:
874 /* INFO_IND */
875 chan = find_plci(card, msg->msg.info_ind.plci);
876 if (chan >= 0)
877 /* TODO: Eval Charging info / cause */
878 actcapi_info_resp(card, &card->bch[chan]);
879 break;
880 case 0x0401:
881 /* LISTEN_CONF */
882 case 0x0501:
883 /* LISTEN_CONF */
884 case 0xff01:
885 /* MANUFACTURER_CONF */
886 break;
887 case 0xff02:
888 /* MANUFACTURER_IND */
889 if (msg->msg.manuf_msg == 3) {
890 memset(tmp, 0, sizeof(tmp));
891 strncpy(tmp,
892 &msg->msg.manufacturer_ind_err.errstring,
893 msg->hdr.len - 16);
894 if (msg->msg.manufacturer_ind_err.errcode)
895 printk(KERN_WARNING "act2000: %s\n", tmp);
896 else {
897 printk(KERN_DEBUG "act2000: %s\n", tmp);
898 if ((!strncmp(tmp, "INFO: Trace buffer con", 22)) ||
899 (!strncmp(tmp, "INFO: Compile Date/Tim", 22))) {
900 card->flags |= ACT2000_FLAGS_RUNNING;
901 cmd.command = ISDN_STAT_RUN;
902 cmd.driver = card->myid;
903 cmd.arg = 0;
904 actcapi_manufacturer_req_net(card);
905 actcapi_manufacturer_req_msn(card);
906 actcapi_listen_req(card);
907 card->interface.statcallb(&cmd);
911 break;
912 default:
913 printk(KERN_WARNING "act2000: UNHANDLED Message %04x\n", ccmd);
914 break;
916 dev_kfree_skb(skb);
920 #ifdef DEBUG_MSG
921 static void
922 actcapi_debug_caddr(actcapi_addr *addr)
924 char tmp[30];
926 printk(KERN_DEBUG " Alen = %d\n", addr->len);
927 if (addr->len > 0)
928 printk(KERN_DEBUG " Atnp = 0x%02x\n", addr->tnp);
929 if (addr->len > 1) {
930 memset(tmp, 0, 30);
931 memcpy(tmp, addr->num, addr->len - 1);
932 printk(KERN_DEBUG " Anum = '%s'\n", tmp);
936 static void
937 actcapi_debug_ncpi(actcapi_ncpi *ncpi)
939 printk(KERN_DEBUG " ncpi.len = %d\n", ncpi->len);
940 if (ncpi->len >= 2)
941 printk(KERN_DEBUG " ncpi.lic = 0x%04x\n", ncpi->lic);
942 if (ncpi->len >= 4)
943 printk(KERN_DEBUG " ncpi.hic = 0x%04x\n", ncpi->hic);
944 if (ncpi->len >= 6)
945 printk(KERN_DEBUG " ncpi.ltc = 0x%04x\n", ncpi->ltc);
946 if (ncpi->len >= 8)
947 printk(KERN_DEBUG " ncpi.htc = 0x%04x\n", ncpi->htc);
948 if (ncpi->len >= 10)
949 printk(KERN_DEBUG " ncpi.loc = 0x%04x\n", ncpi->loc);
950 if (ncpi->len >= 12)
951 printk(KERN_DEBUG " ncpi.hoc = 0x%04x\n", ncpi->hoc);
952 if (ncpi->len >= 13)
953 printk(KERN_DEBUG " ncpi.mod = %d\n", ncpi->modulo);
956 static void
957 actcapi_debug_dlpd(actcapi_dlpd *dlpd)
959 printk(KERN_DEBUG " dlpd.len = %d\n", dlpd->len);
960 if (dlpd->len >= 2)
961 printk(KERN_DEBUG " dlpd.dlen = 0x%04x\n", dlpd->dlen);
962 if (dlpd->len >= 3)
963 printk(KERN_DEBUG " dlpd.laa = 0x%02x\n", dlpd->laa);
964 if (dlpd->len >= 4)
965 printk(KERN_DEBUG " dlpd.lab = 0x%02x\n", dlpd->lab);
966 if (dlpd->len >= 5)
967 printk(KERN_DEBUG " dlpd.modulo = %d\n", dlpd->modulo);
968 if (dlpd->len >= 6)
969 printk(KERN_DEBUG " dlpd.win = %d\n", dlpd->win);
972 #ifdef DEBUG_DUMP_SKB
973 static void dump_skb(struct sk_buff *skb) {
974 char tmp[80];
975 char *p = skb->data;
976 char *t = tmp;
977 int i;
979 for (i = 0; i < skb->len; i++) {
980 t += sprintf(t, "%02x ", *p++ & 0xff);
981 if ((i & 0x0f) == 8) {
982 printk(KERN_DEBUG "dump: %s\n", tmp);
983 t = tmp;
986 if (i & 0x07)
987 printk(KERN_DEBUG "dump: %s\n", tmp);
989 #endif
991 void
992 actcapi_debug_msg(struct sk_buff *skb, int direction)
994 actcapi_msg *msg = (actcapi_msg *)skb->data;
995 char *descr;
996 int i;
997 char tmp[170];
999 #ifndef DEBUG_DATA_MSG
1000 if (msg->hdr.cmd.cmd == 0x86)
1001 return;
1002 #endif
1003 descr = "INVALID";
1004 #ifdef DEBUG_DUMP_SKB
1005 dump_skb(skb);
1006 #endif
1007 for (i = 0; i < ARRAY_SIZE(valid_msg); i++)
1008 if ((msg->hdr.cmd.cmd == valid_msg[i].cmd.cmd) &&
1009 (msg->hdr.cmd.subcmd == valid_msg[i].cmd.subcmd)) {
1010 descr = valid_msg[i].description;
1011 break;
1013 printk(KERN_DEBUG "%s %s msg\n", direction?"Outgoing":"Incoming", descr);
1014 printk(KERN_DEBUG " ApplID = %d\n", msg->hdr.applicationID);
1015 printk(KERN_DEBUG " Len = %d\n", msg->hdr.len);
1016 printk(KERN_DEBUG " MsgNum = 0x%04x\n", msg->hdr.msgnum);
1017 printk(KERN_DEBUG " Cmd = 0x%02x\n", msg->hdr.cmd.cmd);
1018 printk(KERN_DEBUG " SubCmd = 0x%02x\n", msg->hdr.cmd.subcmd);
1019 switch (i) {
1020 case 0:
1021 /* DATA B3 IND */
1022 printk(KERN_DEBUG " BLOCK = 0x%02x\n",
1023 msg->msg.data_b3_ind.blocknr);
1024 break;
1025 case 2:
1026 /* CONNECT CONF */
1027 printk(KERN_DEBUG " PLCI = 0x%04x\n",
1028 msg->msg.connect_conf.plci);
1029 printk(KERN_DEBUG " Info = 0x%04x\n",
1030 msg->msg.connect_conf.info);
1031 break;
1032 case 3:
1033 /* CONNECT IND */
1034 printk(KERN_DEBUG " PLCI = 0x%04x\n",
1035 msg->msg.connect_ind.plci);
1036 printk(KERN_DEBUG " Contr = %d\n",
1037 msg->msg.connect_ind.controller);
1038 printk(KERN_DEBUG " SI1 = %d\n",
1039 msg->msg.connect_ind.si1);
1040 printk(KERN_DEBUG " SI2 = %d\n",
1041 msg->msg.connect_ind.si2);
1042 printk(KERN_DEBUG " EAZ = '%c'\n",
1043 msg->msg.connect_ind.eaz);
1044 actcapi_debug_caddr(&msg->msg.connect_ind.addr);
1045 break;
1046 case 5:
1047 /* CONNECT ACTIVE IND */
1048 printk(KERN_DEBUG " PLCI = 0x%04x\n",
1049 msg->msg.connect_active_ind.plci);
1050 actcapi_debug_caddr(&msg->msg.connect_active_ind.addr);
1051 break;
1052 case 8:
1053 /* LISTEN CONF */
1054 printk(KERN_DEBUG " Contr = %d\n",
1055 msg->msg.listen_conf.controller);
1056 printk(KERN_DEBUG " Info = 0x%04x\n",
1057 msg->msg.listen_conf.info);
1058 break;
1059 case 11:
1060 /* INFO IND */
1061 printk(KERN_DEBUG " PLCI = 0x%04x\n",
1062 msg->msg.info_ind.plci);
1063 printk(KERN_DEBUG " Imsk = 0x%04x\n",
1064 msg->msg.info_ind.nr.mask);
1065 if (msg->hdr.len > 12) {
1066 int l = msg->hdr.len - 12;
1067 int j;
1068 char *p = tmp;
1069 for (j = 0; j < l ; j++)
1070 p += sprintf(p, "%02x ", msg->msg.info_ind.el.display[j]);
1071 printk(KERN_DEBUG " D = '%s'\n", tmp);
1073 break;
1074 case 14:
1075 /* SELECT B2 PROTOCOL CONF */
1076 printk(KERN_DEBUG " PLCI = 0x%04x\n",
1077 msg->msg.select_b2_protocol_conf.plci);
1078 printk(KERN_DEBUG " Info = 0x%04x\n",
1079 msg->msg.select_b2_protocol_conf.info);
1080 break;
1081 case 15:
1082 /* SELECT B3 PROTOCOL CONF */
1083 printk(KERN_DEBUG " PLCI = 0x%04x\n",
1084 msg->msg.select_b3_protocol_conf.plci);
1085 printk(KERN_DEBUG " Info = 0x%04x\n",
1086 msg->msg.select_b3_protocol_conf.info);
1087 break;
1088 case 16:
1089 /* LISTEN B3 CONF */
1090 printk(KERN_DEBUG " PLCI = 0x%04x\n",
1091 msg->msg.listen_b3_conf.plci);
1092 printk(KERN_DEBUG " Info = 0x%04x\n",
1093 msg->msg.listen_b3_conf.info);
1094 break;
1095 case 18:
1096 /* CONNECT B3 IND */
1097 printk(KERN_DEBUG " NCCI = 0x%04x\n",
1098 msg->msg.connect_b3_ind.ncci);
1099 printk(KERN_DEBUG " PLCI = 0x%04x\n",
1100 msg->msg.connect_b3_ind.plci);
1101 actcapi_debug_ncpi(&msg->msg.connect_b3_ind.ncpi);
1102 break;
1103 case 19:
1104 /* CONNECT B3 ACTIVE IND */
1105 printk(KERN_DEBUG " NCCI = 0x%04x\n",
1106 msg->msg.connect_b3_active_ind.ncci);
1107 actcapi_debug_ncpi(&msg->msg.connect_b3_active_ind.ncpi);
1108 break;
1109 case 26:
1110 /* MANUFACTURER IND */
1111 printk(KERN_DEBUG " Mmsg = 0x%02x\n",
1112 msg->msg.manufacturer_ind_err.manuf_msg);
1113 switch (msg->msg.manufacturer_ind_err.manuf_msg) {
1114 case 3:
1115 printk(KERN_DEBUG " Contr = %d\n",
1116 msg->msg.manufacturer_ind_err.controller);
1117 printk(KERN_DEBUG " Code = 0x%08x\n",
1118 msg->msg.manufacturer_ind_err.errcode);
1119 memset(tmp, 0, sizeof(tmp));
1120 strncpy(tmp, &msg->msg.manufacturer_ind_err.errstring,
1121 msg->hdr.len - 16);
1122 printk(KERN_DEBUG " Emsg = '%s'\n", tmp);
1123 break;
1125 break;
1126 case 30:
1127 /* LISTEN REQ */
1128 printk(KERN_DEBUG " Imsk = 0x%08x\n",
1129 msg->msg.listen_req.infomask);
1130 printk(KERN_DEBUG " Emsk = 0x%04x\n",
1131 msg->msg.listen_req.eazmask);
1132 printk(KERN_DEBUG " Smsk = 0x%04x\n",
1133 msg->msg.listen_req.simask);
1134 break;
1135 case 35:
1136 /* SELECT_B2_PROTOCOL_REQ */
1137 printk(KERN_DEBUG " PLCI = 0x%04x\n",
1138 msg->msg.select_b2_protocol_req.plci);
1139 printk(KERN_DEBUG " prot = 0x%02x\n",
1140 msg->msg.select_b2_protocol_req.protocol);
1141 if (msg->hdr.len >= 11)
1142 printk(KERN_DEBUG "No dlpd\n");
1143 else
1144 actcapi_debug_dlpd(&msg->msg.select_b2_protocol_req.dlpd);
1145 break;
1146 case 44:
1147 /* CONNECT RESP */
1148 printk(KERN_DEBUG " PLCI = 0x%04x\n",
1149 msg->msg.connect_resp.plci);
1150 printk(KERN_DEBUG " CAUSE = 0x%02x\n",
1151 msg->msg.connect_resp.rejectcause);
1152 break;
1153 case 45:
1154 /* CONNECT ACTIVE RESP */
1155 printk(KERN_DEBUG " PLCI = 0x%04x\n",
1156 msg->msg.connect_active_resp.plci);
1157 break;
1160 #endif