📄 isdn_v110.c
字号:
/* $Id: isdn_v110.c,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $ * * Linux ISDN subsystem, V.110 related functions (linklevel). * * Copyright by Thomas Pfeiffer (pfeiffer@pds.de) * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. * */#include <linux/string.h>#include <linux/kernel.h>#include <linux/slab.h>#include <linux/mm.h>#include <linux/delay.h>#include <linux/isdn.h>#include "isdn_v110.h"#undef ISDN_V110_DEBUGchar *isdn_v110_revision = "$Revision: 1.1.2.2 $";#define V110_38400 255#define V110_19200 15#define V110_9600 3/* * The following data are precoded matrices, online and offline matrix * for 9600, 19200 und 38400, respectively */static unsigned char V110_OnMatrix_9600[] ={0xfc, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfd, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfd};static unsigned char V110_OffMatrix_9600[] ={0xfc, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};static unsigned char V110_OnMatrix_19200[] ={0xf0, 0xf0, 0xff, 0xf7, 0xff, 0xf7, 0xff, 0xf7, 0xff, 0xf7, 0xfd, 0xff, 0xff, 0xf7, 0xff, 0xf7, 0xff, 0xf7, 0xff, 0xf7};static unsigned char V110_OffMatrix_19200[] ={0xf0, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};static unsigned char V110_OnMatrix_38400[] ={0x00, 0x7f, 0x7f, 0x7f, 0x7f, 0xfd, 0x7f, 0x7f, 0x7f, 0x7f};static unsigned char V110_OffMatrix_38400[] ={0x00, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff};/* * FlipBits reorders sequences of keylen bits in one byte. * E.g. source order 7654321 will be converted to 45670123 when keylen = 4, * and to 67452301 when keylen = 2. This is necessary because ordering on * the isdn line is the other way. */static __inline unsigned charFlipBits(unsigned char c, int keylen){ unsigned char b = c; unsigned char bit = 128; int i; int j; int hunks = (8 / keylen); c = 0; for (i = 0; i < hunks; i++) { for (j = 0; j < keylen; j++) { if (b & (bit >> j)) c |= bit >> (keylen - j - 1); } bit >>= keylen; } return c;}/* isdn_v110_open allocates and initializes private V.110 data * structures and returns a pointer to these. */static isdn_v110_stream *isdn_v110_open(unsigned char key, int hdrlen, int maxsize){ int i; isdn_v110_stream *v; if ((v = kmalloc(sizeof(isdn_v110_stream), GFP_ATOMIC)) == NULL) return NULL; memset(v, 0, sizeof(isdn_v110_stream)); v->key = key; v->nbits = 0; for (i = 0; key & (1 << i); i++) v->nbits++; v->nbytes = 8 / v->nbits; v->decodelen = 0; switch (key) { case V110_38400: v->OnlineFrame = V110_OnMatrix_38400; v->OfflineFrame = V110_OffMatrix_38400; break; case V110_19200: v->OnlineFrame = V110_OnMatrix_19200; v->OfflineFrame = V110_OffMatrix_19200; break; default: v->OnlineFrame = V110_OnMatrix_9600; v->OfflineFrame = V110_OffMatrix_9600; break; } v->framelen = v->nbytes * 10; v->SyncInit = 5; v->introducer = 0; v->dbit = 1; v->b = 0; v->skbres = hdrlen; v->maxsize = maxsize - hdrlen; if ((v->encodebuf = kmalloc(maxsize, GFP_ATOMIC)) == NULL) { kfree(v); return NULL; } return v;}/* isdn_v110_close frees private V.110 data structures */voidisdn_v110_close(isdn_v110_stream * v){ if (v == NULL) return;#ifdef ISDN_V110_DEBUG printk(KERN_DEBUG "v110 close\n");#endif kfree(v->encodebuf); kfree(v);}/* * ValidHeaderBytes return the number of valid bytes in v->decodebuf */static intValidHeaderBytes(isdn_v110_stream * v){ int i; for (i = 0; (i < v->decodelen) && (i < v->nbytes); i++) if ((v->decodebuf[i] & v->key) != 0) break; return i;}/* * SyncHeader moves the decodebuf ptr to the next valid header */static voidSyncHeader(isdn_v110_stream * v){ unsigned char *rbuf = v->decodebuf; int len = v->decodelen; if (len == 0) return; for (rbuf++, len--; len > 0; len--, rbuf++) /* such den SyncHeader in buf ! */ if ((*rbuf & v->key) == 0) /* erstes byte gefunden ? */ break; /* jupp! */ if (len) memcpy(v->decodebuf, rbuf, len); v->decodelen = len;#ifdef ISDN_V110_DEBUG printk(KERN_DEBUG "isdn_v110: Header resync\n");#endif}/* DecodeMatrix takes n (n>=1) matrices (v110 frames, 10 bytes) where len is the number of matrix-lines. len must be a multiple of 10, i.e. only complete matices must be given. From these, netto data is extracted and returned in buf. The return-value is the bytecount of the decoded data. */static intDecodeMatrix(isdn_v110_stream * v, unsigned char *m, int len, unsigned char *buf){ int line = 0; int buflen = 0; int mbit = 64; int introducer = v->introducer; int dbit = v->dbit; unsigned char b = v->b; while (line < len) { /* Are we done with all lines of the matrix? */ if ((line % 10) == 0) { /* the 0. line of the matrix is always 0 ! */ if (m[line] != 0x00) { /* not 0 ? -> error! */#ifdef ISDN_V110_DEBUG printk(KERN_DEBUG "isdn_v110: DecodeMatrix, V110 Bad Header\n"); /* returning now is not the right thing, though :-( */#endif } line++; /* next line of matrix */ continue; } else if ((line % 10) == 5) { /* in line 5 there's only e-bits ! */ if ((m[line] & 0x70) != 0x30) { /* 011 has to be at the beginning! */#ifdef ISDN_V110_DEBUG printk(KERN_DEBUG "isdn_v110: DecodeMatrix, V110 Bad 5th line\n"); /* returning now is not the right thing, though :-( */#endif } line++; /* next line */ continue; } else if (!introducer) { /* every byte starts with 10 (stopbit, startbit) */ introducer = (m[line] & mbit) ? 0 : 1; /* current bit of the matrix */ next_byte: if (mbit > 2) { /* was it the last bit in this line ? */ mbit >>= 1; /* no -> take next */ continue; } /* otherwise start with leftmost bit in the next line */ mbit = 64; line++; continue; } else { /* otherwise we need to set a data bit */ if (m[line] & mbit) /* was that bit set in the matrix ? */ b |= dbit; /* yes -> set it in the data byte */ else b &= dbit - 1; /* no -> clear it in the data byte */ if (dbit < 128) /* is that data byte done ? */ dbit <<= 1; /* no, got the next bit */ else { /* data byte is done */ buf[buflen++] = b; /* copy byte into the output buffer */ introducer = b = 0; /* init of the intro sequence and of the data byte */ dbit = 1; /* next we look for the 0th bit */ } goto next_byte; /* look for next bit in the matrix */ } } v->introducer = introducer; v->dbit = dbit; v->b = b; return buflen; /* return number of bytes in the output buffer */}/* * DecodeStream receives V.110 coded data from the input stream. It recovers the * original frames. * The input stream doesn't need to be framed */struct sk_buff *isdn_v110_decode(isdn_v110_stream * v, struct sk_buff *skb){ int i; int j; int len; unsigned char *v110_buf; unsigned char *rbuf; if (!skb) { printk(KERN_WARNING "isdn_v110_decode called with NULL skb!\n"); return NULL; } rbuf = skb->data; len = skb->len; if (v == NULL) { /* invalid handle, no chance to proceed */ printk(KERN_WARNING "isdn_v110_decode called with NULL stream!\n"); dev_kfree_skb(skb); return NULL; } if (v->decodelen == 0) /* cache empty? */ for (; len > 0; len--, rbuf++) /* scan for SyncHeader in buf */ if ((*rbuf & v->key) == 0) break; /* found first byte */ if (len == 0) { dev_kfree_skb(skb); return NULL; } /* copy new data to decode-buffer */ memcpy(&(v->decodebuf[v->decodelen]), rbuf, len); v->decodelen += len; ReSync: if (v->decodelen < v->nbytes) { /* got a new header ? */ dev_kfree_skb(skb); return NULL; /* no, try later */ } if (ValidHeaderBytes(v) != v->nbytes) { /* is that a valid header? */ SyncHeader(v); /* no -> look for header */ goto ReSync; } len = (v->decodelen - (v->decodelen % (10 * v->nbytes))) / v->nbytes; if ((v110_buf = kmalloc(len, GFP_ATOMIC)) == NULL) { printk(KERN_WARNING "isdn_v110_decode: Couldn't allocate v110_buf\n"); dev_kfree_skb(skb); return NULL; } for (i = 0; i < len; i++) { v110_buf[i] = 0; for (j = 0; j < v->nbytes; j++) v110_buf[i] |= (v->decodebuf[(i * v->nbytes) + j] & v->key) << (8 - ((j + 1) * v->nbits)); v110_buf[i] = FlipBits(v110_buf[i], v->nbits); } v->decodelen = (v->decodelen % (10 * v->nbytes)); memcpy(v->decodebuf, &(v->decodebuf[len * v->nbytes]), v->decodelen);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -