/* $Id: capi.c,v 1.9.6.2 2001/09/23 22:24:32 kai Exp $
*
* ISDN lowlevel-module for the IBM ISDN-S0 Active 2000.
* CAPI encoder/decoder
*
* Author Fritz Elfert
* Copyright by Fritz Elfert <fritz@isdn4linux.de>
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
* Thanks to Friedemann Baitinger and IBM Germany
*
*/
#include "act2000.h"
#include "capi.h"
static actcapi_msgdsc valid_msg[] = {
{{ 0x86, 0x02}, "DATA_B3_IND"}, /* DATA_B3_IND/CONF must be first because of speed!!! */
{{ 0x86, 0x01}, "DATA_B3_CONF"},
{{ 0x02, 0x01}, "CONNECT_CONF"},
{{ 0x02, 0x02}, "CONNECT_IND"},
{{ 0x09, 0x01}, "CONNECT_INFO_CONF"},
{{ 0x03, 0x02}, "CONNECT_ACTIVE_IND"},
{{ 0x04, 0x01}, "DISCONNECT_CONF"},
{{ 0x04, 0x02}, "DISCONNECT_IND"},
{{ 0x05, 0x01}, "LISTEN_CONF"},
{{ 0x06, 0x01}, "GET_PARAMS_CONF"},
{{ 0x07, 0x01}, "INFO_CONF"},
{{ 0x07, 0x02}, "INFO_IND"},
{{ 0x08, 0x01}, "DATA_CONF"},
{{ 0x08, 0x02}, "DATA_IND"},
{{ 0x40, 0x01}, "SELECT_B2_PROTOCOL_CONF"},
{{ 0x80, 0x01}, "SELECT_B3_PROTOCOL_CONF"},
{{ 0x81, 0x01}, "LISTEN_B3_CONF"},
{{ 0x82, 0x01}, "CONNECT_B3_CONF"},
{{ 0x82, 0x02}, "CONNECT_B3_IND"},
{{ 0x83, 0x02}, "CONNECT_B3_ACTIVE_IND"},
{{ 0x84, 0x01}, "DISCONNECT_B3_CONF"},
{{ 0x84, 0x02}, "DISCONNECT_B3_IND"},
{{ 0x85, 0x01}, "GET_B3_PARAMS_CONF"},
{{ 0x01, 0x01}, "RESET_B3_CONF"},
{{ 0x01, 0x02}, "RESET_B3_IND"},
/* {{ 0x87, 0x02, "HANDSET_IND"}, not implemented */
{{ 0xff, 0x01}, "MANUFACTURER_CONF"},
{{ 0xff, 0x02}, "MANUFACTURER_IND"},
#ifdef DEBUG_MSG
/* Requests */
{{ 0x01, 0x00}, "RESET_B3_REQ"},
{{ 0x02, 0x00}, "CONNECT_REQ"},
{{ 0x04, 0x00}, "DISCONNECT_REQ"},
{{ 0x05, 0x00}, "LISTEN_REQ"},
{{ 0x06, 0x00}, "GET_PARAMS_REQ"},
{{ 0x07, 0x00}, "INFO_REQ"},
{{ 0x08, 0x00}, "DATA_REQ"},
{{ 0x09, 0x00}, "CONNECT_INFO_REQ"},
{{ 0x40, 0x00}, "SELECT_B2_PROTOCOL_REQ"},
{{ 0x80, 0x00}, "SELECT_B3_PROTOCOL_REQ"},
{{ 0x81, 0x00}, "LISTEN_B3_REQ"},
{{ 0x82, 0x00}, "CONNECT_B3_REQ"},
{{ 0x84, 0x00}, "DISCONNECT_B3_REQ"},
{{ 0x85, 0x00}, "GET_B3_PARAMS_REQ"},
{{ 0x86, 0x00}, "DATA_B3_REQ"},
{{ 0xff, 0x00}, "MANUFACTURER_REQ"},
/* Responses */
{{ 0x01, 0x03}, "RESET_B3_RESP"},
{{ 0x02, 0x03}, "CONNECT_RESP"},
{{ 0x03, 0x03}, "CONNECT_ACTIVE_RESP"},
{{ 0x04, 0x03}, "DISCONNECT_RESP"},
{{ 0x07, 0x03}, "INFO_RESP"},
{{ 0x08, 0x03}, "DATA_RESP"},
{{ 0x82, 0x03}, "CONNECT_B3_RESP"},
{{ 0x83, 0x03}, "CONNECT_B3_ACTIVE_RESP"},
{{ 0x84, 0x03}, "DISCONNECT_B3_RESP"},
{{ 0x86, 0x03}, "DATA_B3_RESP"},
{{ 0xff, 0x03}, "MANUFACTURER_RESP"},
#endif
{{ 0x00, 0x00}, NULL},
};
#define num_valid_imsg 27 /* MANUFACTURER_IND */
/*
* Check for a valid incoming CAPI message.
* Return:
* 0 = Invalid message
* 1 = Valid message, no B-Channel-data
* 2 = Valid message, B-Channel-data
*/
int
actcapi_chkhdr(act2000_card *card, actcapi_msghdr *hdr)
{
int i;
if (hdr->applicationID != 1)
return 0;
if (hdr->len < 9)
return 0;
for (i = 0; i < num_valid_imsg; i++)
if ((hdr->cmd.cmd == valid_msg[i].cmd.cmd) &&
(hdr->cmd.subcmd == valid_msg[i].cmd.subcmd)) {
return (i ? 1 : 2);
}
return 0;
}
#define ACTCAPI_MKHDR(l, c, s) { \
skb = alloc_skb(l + 8, GFP_ATOMIC); \
if (skb) { \
m = (actcapi_msg *)skb_put(skb, l + 8); \
m->hdr.len = l + 8; \
m->hdr.applicationID = 1; \
m->hdr.cmd.cmd = c; \
m->hdr.cmd.subcmd = s; \
m->hdr.msgnum = actcapi_nextsmsg(card); \
} else m = NULL; \
}
#define ACTCAPI_CHKSKB if (!skb) { \
printk(KERN_WARNING "actcapi: alloc_skb failed\n"); \
return; \
}
#define ACTCAPI_QUEUE_TX { \
actcapi_debug_msg(skb, 1); \
skb_queue_tail(&card->sndq, skb); \
act2000_schedule_tx(card); \
}
int
actcapi_listen_req(act2000_card *card)
{
__u16 eazmask = 0;
int i;
actcapi_msg *m;
struct sk_buff *skb;
for (i = 0; i < ACT2000_BCH; i++)
eazmask |= card->bch[i].eazmask;
ACTCAPI_MKHDR(9, 0x05, 0x00);
if (!skb) {
printk(KERN_WARNING "actcapi: alloc_skb failed\n");
return -ENOMEM;
}
m->msg
|