diff options
-rw-r--r-- | drivers/isdn/mISDN/Kconfig | 19 | ||||
-rw-r--r-- | drivers/isdn/mISDN/Makefile | 2 | ||||
-rw-r--r-- | drivers/isdn/mISDN/l1oip.h | 91 | ||||
-rw-r--r-- | drivers/isdn/mISDN/l1oip_codec.c | 374 | ||||
-rw-r--r-- | drivers/isdn/mISDN/l1oip_core.c | 1518 |
5 files changed, 2003 insertions, 1 deletions
diff --git a/drivers/isdn/mISDN/Kconfig b/drivers/isdn/mISDN/Kconfig index 6a97e86e7f21..4938355c4072 100644 --- a/drivers/isdn/mISDN/Kconfig +++ b/drivers/isdn/mISDN/Kconfig | |||
@@ -23,5 +23,22 @@ config MISDN_DSP | |||
23 | and get more informations about this module and it's usage. | 23 | and get more informations about this module and it's usage. |
24 | If unsure, say 'N'. | 24 | If unsure, say 'N'. |
25 | 25 | ||
26 | source "drivers/isdn/hardware/mISDN/Kconfig" | 26 | config MISDN_L1OIP |
27 | tristate "ISDN over IP tunnel" | ||
28 | depends on MISDN | ||
29 | help | ||
30 | Enable support for ISDN over IP tunnel. | ||
31 | |||
32 | It features: | ||
33 | - dynamic IP exchange, if one or both peers have dynamic IPs | ||
34 | - BRI (S0) and PRI (S2M) interface | ||
35 | - layer 1 control via network keepalive frames | ||
36 | - direct tunneling of physical interface via IP | ||
37 | |||
38 | NOTE: This protocol is called 'Layer 1 over IP' and is not | ||
39 | compatible with ISDNoIP (Agfeo) or TDMoIP. Protocol description is | ||
40 | provided in the source code. | ||
41 | |||
42 | source "drivers/isdn/hardware/mISDN/Kconfig" | ||
43 | |||
27 | endif #MISDN | 44 | endif #MISDN |
diff --git a/drivers/isdn/mISDN/Makefile b/drivers/isdn/mISDN/Makefile index 7f1a21804208..1cb5e633cf75 100644 --- a/drivers/isdn/mISDN/Makefile +++ b/drivers/isdn/mISDN/Makefile | |||
@@ -4,8 +4,10 @@ | |||
4 | 4 | ||
5 | obj-$(CONFIG_MISDN) += mISDN_core.o | 5 | obj-$(CONFIG_MISDN) += mISDN_core.o |
6 | obj-$(CONFIG_MISDN_DSP) += mISDN_dsp.o | 6 | obj-$(CONFIG_MISDN_DSP) += mISDN_dsp.o |
7 | obj-$(CONFIG_MISDN_L1OIP) += l1oip.o | ||
7 | 8 | ||
8 | # multi objects | 9 | # multi objects |
9 | 10 | ||
10 | mISDN_core-objs := core.o fsm.o socket.o hwchannel.o stack.o layer1.o layer2.o tei.o timerdev.o | 11 | mISDN_core-objs := core.o fsm.o socket.o hwchannel.o stack.o layer1.o layer2.o tei.o timerdev.o |
11 | mISDN_dsp-objs := dsp_core.o dsp_cmx.o dsp_tones.o dsp_dtmf.o dsp_audio.o dsp_blowfish.o dsp_pipeline.o dsp_hwec.o | 12 | mISDN_dsp-objs := dsp_core.o dsp_cmx.o dsp_tones.o dsp_dtmf.o dsp_audio.o dsp_blowfish.o dsp_pipeline.o dsp_hwec.o |
13 | l1oip-objs := l1oip_core.o l1oip_codec.o | ||
diff --git a/drivers/isdn/mISDN/l1oip.h b/drivers/isdn/mISDN/l1oip.h new file mode 100644 index 000000000000..a23d575449f6 --- /dev/null +++ b/drivers/isdn/mISDN/l1oip.h | |||
@@ -0,0 +1,91 @@ | |||
1 | /* | ||
2 | * see notice in l1oip.c | ||
3 | */ | ||
4 | |||
5 | /* debugging */ | ||
6 | #define DEBUG_L1OIP_INIT 0x00010000 | ||
7 | #define DEBUG_L1OIP_SOCKET 0x00020000 | ||
8 | #define DEBUG_L1OIP_MGR 0x00040000 | ||
9 | #define DEBUG_L1OIP_MSG 0x00080000 | ||
10 | |||
11 | /* enable to disorder received bchannels by sequence 2143658798... */ | ||
12 | /* | ||
13 | #define REORDER_DEBUG | ||
14 | */ | ||
15 | |||
16 | /* frames */ | ||
17 | #define L1OIP_MAX_LEN 2048 /* max packet size form l2 */ | ||
18 | #define L1OIP_MAX_PERFRAME 1400 /* max data size in one frame */ | ||
19 | |||
20 | |||
21 | /* timers */ | ||
22 | #define L1OIP_KEEPALIVE 15 | ||
23 | #define L1OIP_TIMEOUT 65 | ||
24 | |||
25 | |||
26 | /* socket */ | ||
27 | #define L1OIP_DEFAULTPORT 931 | ||
28 | |||
29 | |||
30 | /* channel structure */ | ||
31 | struct l1oip_chan { | ||
32 | struct dchannel *dch; | ||
33 | struct bchannel *bch; | ||
34 | u32 tx_counter; /* counts xmit bytes/packets */ | ||
35 | u32 rx_counter; /* counts recv bytes/packets */ | ||
36 | u32 codecstate; /* used by codec to save data */ | ||
37 | #ifdef REORDER_DEBUG | ||
38 | int disorder_flag; | ||
39 | struct sk_buff *disorder_skb; | ||
40 | u32 disorder_cnt; | ||
41 | #endif | ||
42 | }; | ||
43 | |||
44 | |||
45 | /* card structure */ | ||
46 | struct l1oip { | ||
47 | struct list_head list; | ||
48 | |||
49 | /* card */ | ||
50 | int registered; /* if registered with mISDN */ | ||
51 | char name[MISDN_MAX_IDLEN]; | ||
52 | int idx; /* card index */ | ||
53 | int pri; /* 1=pri, 0=bri */ | ||
54 | int d_idx; /* current dchannel number */ | ||
55 | int b_num; /* number of bchannels */ | ||
56 | u32 id; /* id of connection */ | ||
57 | int ondemand; /* if transmis. is on demand */ | ||
58 | int bundle; /* bundle channels in one frm */ | ||
59 | int codec; /* codec to use for transmis. */ | ||
60 | int limit; /* limit number of bchannels */ | ||
61 | |||
62 | /* timer */ | ||
63 | struct timer_list keep_tl; | ||
64 | struct timer_list timeout_tl; | ||
65 | int timeout_on; | ||
66 | struct work_struct workq; | ||
67 | |||
68 | /* socket */ | ||
69 | struct socket *socket; /* if set, socket is created */ | ||
70 | struct completion socket_complete;/* completion of sock thread */ | ||
71 | struct task_struct *socket_thread; | ||
72 | spinlock_t socket_lock; /* access sock outside thread */ | ||
73 | u32 remoteip; /* if all set, ip is assigned */ | ||
74 | u16 localport; /* must always be set */ | ||
75 | u16 remoteport; /* must always be set */ | ||
76 | struct sockaddr_in sin_local; /* local socket name */ | ||
77 | struct sockaddr_in sin_remote; /* remote socket name */ | ||
78 | struct msghdr sendmsg; /* ip message to send */ | ||
79 | struct iovec sendiov; /* iov for message */ | ||
80 | |||
81 | /* frame */ | ||
82 | struct l1oip_chan chan[128]; /* channel instances */ | ||
83 | }; | ||
84 | |||
85 | extern int l1oip_law_to_4bit(u8 *data, int len, u8 *result, u32 *state); | ||
86 | extern int l1oip_4bit_to_law(u8 *data, int len, u8 *result); | ||
87 | extern int l1oip_alaw_to_ulaw(u8 *data, int len, u8 *result); | ||
88 | extern int l1oip_ulaw_to_alaw(u8 *data, int len, u8 *result); | ||
89 | extern void l1oip_4bit_free(void); | ||
90 | extern int l1oip_4bit_alloc(int ulaw); | ||
91 | |||
diff --git a/drivers/isdn/mISDN/l1oip_codec.c b/drivers/isdn/mISDN/l1oip_codec.c new file mode 100644 index 000000000000..a2dc4570ef43 --- /dev/null +++ b/drivers/isdn/mISDN/l1oip_codec.c | |||
@@ -0,0 +1,374 @@ | |||
1 | /* | ||
2 | |||
3 | * l1oip_codec.c generic codec using lookup table | ||
4 | * -> conversion from a-Law to u-Law | ||
5 | * -> conversion from u-Law to a-Law | ||
6 | * -> compression by reducing the number of sample resolution to 4 | ||
7 | * | ||
8 | * NOTE: It is not compatible with any standard codec like ADPCM. | ||
9 | * | ||
10 | * Author Andreas Eversberg (jolly@eversberg.eu) | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2, or (at your option) | ||
15 | * any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with this program; if not, write to the Free Software | ||
24 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
25 | |||
26 | */ | ||
27 | |||
28 | /* | ||
29 | |||
30 | How the codec works: | ||
31 | -------------------- | ||
32 | |||
33 | The volume is increased to increase the dynamic range of the audio signal. | ||
34 | Each sample is converted to a-LAW with only 16 steps of level resolution. | ||
35 | A pair of two samples are stored in one byte. | ||
36 | |||
37 | The first byte is stored in the upper bits, the second byte is stored in the | ||
38 | lower bits. | ||
39 | |||
40 | To speed up compression and decompression, two lookup tables are formed: | ||
41 | |||
42 | - 16 bits index for two samples (law encoded) with 8 bit compressed result. | ||
43 | - 8 bits index for one compressed data with 16 bits decompressed result. | ||
44 | |||
45 | NOTE: The bytes are handled as they are law-encoded. | ||
46 | |||
47 | */ | ||
48 | |||
49 | #include <linux/vmalloc.h> | ||
50 | #include <linux/mISDNif.h> | ||
51 | #include "core.h" | ||
52 | |||
53 | /* definitions of codec. don't use calculations, code may run slower. */ | ||
54 | |||
55 | static u8 *table_com; | ||
56 | static u16 *table_dec; | ||
57 | |||
58 | |||
59 | /* alaw -> ulaw */ | ||
60 | static u8 alaw_to_ulaw[256] = | ||
61 | { | ||
62 | 0xab, 0x2b, 0xe3, 0x63, 0x8b, 0x0b, 0xc9, 0x49, | ||
63 | 0xba, 0x3a, 0xf6, 0x76, 0x9b, 0x1b, 0xd7, 0x57, | ||
64 | 0xa3, 0x23, 0xdd, 0x5d, 0x83, 0x03, 0xc1, 0x41, | ||
65 | 0xb2, 0x32, 0xeb, 0x6b, 0x93, 0x13, 0xcf, 0x4f, | ||
66 | 0xaf, 0x2f, 0xe7, 0x67, 0x8f, 0x0f, 0xcd, 0x4d, | ||
67 | 0xbe, 0x3e, 0xfe, 0x7e, 0x9f, 0x1f, 0xdb, 0x5b, | ||
68 | 0xa7, 0x27, 0xdf, 0x5f, 0x87, 0x07, 0xc5, 0x45, | ||
69 | 0xb6, 0x36, 0xef, 0x6f, 0x97, 0x17, 0xd3, 0x53, | ||
70 | 0xa9, 0x29, 0xe1, 0x61, 0x89, 0x09, 0xc7, 0x47, | ||
71 | 0xb8, 0x38, 0xf2, 0x72, 0x99, 0x19, 0xd5, 0x55, | ||
72 | 0xa1, 0x21, 0xdc, 0x5c, 0x81, 0x01, 0xbf, 0x3f, | ||
73 | 0xb0, 0x30, 0xe9, 0x69, 0x91, 0x11, 0xce, 0x4e, | ||
74 | 0xad, 0x2d, 0xe5, 0x65, 0x8d, 0x0d, 0xcb, 0x4b, | ||
75 | 0xbc, 0x3c, 0xfa, 0x7a, 0x9d, 0x1d, 0xd9, 0x59, | ||
76 | 0xa5, 0x25, 0xde, 0x5e, 0x85, 0x05, 0xc3, 0x43, | ||
77 | 0xb4, 0x34, 0xed, 0x6d, 0x95, 0x15, 0xd1, 0x51, | ||
78 | 0xac, 0x2c, 0xe4, 0x64, 0x8c, 0x0c, 0xca, 0x4a, | ||
79 | 0xbb, 0x3b, 0xf8, 0x78, 0x9c, 0x1c, 0xd8, 0x58, | ||
80 | 0xa4, 0x24, 0xde, 0x5e, 0x84, 0x04, 0xc2, 0x42, | ||
81 | 0xb3, 0x33, 0xec, 0x6c, 0x94, 0x14, 0xd0, 0x50, | ||
82 | 0xb0, 0x30, 0xe8, 0x68, 0x90, 0x10, 0xce, 0x4e, | ||
83 | 0xbf, 0x3f, 0xfe, 0x7e, 0xa0, 0x20, 0xdc, 0x5c, | ||
84 | 0xa8, 0x28, 0xe0, 0x60, 0x88, 0x08, 0xc6, 0x46, | ||
85 | 0xb7, 0x37, 0xf0, 0x70, 0x98, 0x18, 0xd4, 0x54, | ||
86 | 0xaa, 0x2a, 0xe2, 0x62, 0x8a, 0x0a, 0xc8, 0x48, | ||
87 | 0xb9, 0x39, 0xf4, 0x74, 0x9a, 0x1a, 0xd6, 0x56, | ||
88 | 0xa2, 0x22, 0xdd, 0x5d, 0x82, 0x02, 0xc0, 0x40, | ||
89 | 0xb1, 0x31, 0xea, 0x6a, 0x92, 0x12, 0xcf, 0x4f, | ||
90 | 0xae, 0x2e, 0xe6, 0x66, 0x8e, 0x0e, 0xcc, 0x4c, | ||
91 | 0xbd, 0x3d, 0xfc, 0x7c, 0x9e, 0x1e, 0xda, 0x5a, | ||
92 | 0xa6, 0x26, 0xdf, 0x5f, 0x86, 0x06, 0xc4, 0x44, | ||
93 | 0xb5, 0x35, 0xee, 0x6e, 0x96, 0x16, 0xd2, 0x52 | ||
94 | }; | ||
95 | |||
96 | /* ulaw -> alaw */ | ||
97 | static u8 ulaw_to_alaw[256] = | ||
98 | { | ||
99 | 0xab, 0x55, 0xd5, 0x15, 0x95, 0x75, 0xf5, 0x35, | ||
100 | 0xb5, 0x45, 0xc5, 0x05, 0x85, 0x65, 0xe5, 0x25, | ||
101 | 0xa5, 0x5d, 0xdd, 0x1d, 0x9d, 0x7d, 0xfd, 0x3d, | ||
102 | 0xbd, 0x4d, 0xcd, 0x0d, 0x8d, 0x6d, 0xed, 0x2d, | ||
103 | 0xad, 0x51, 0xd1, 0x11, 0x91, 0x71, 0xf1, 0x31, | ||
104 | 0xb1, 0x41, 0xc1, 0x01, 0x81, 0x61, 0xe1, 0x21, | ||
105 | 0x59, 0xd9, 0x19, 0x99, 0x79, 0xf9, 0x39, 0xb9, | ||
106 | 0x49, 0xc9, 0x09, 0x89, 0x69, 0xe9, 0x29, 0xa9, | ||
107 | 0xd7, 0x17, 0x97, 0x77, 0xf7, 0x37, 0xb7, 0x47, | ||
108 | 0xc7, 0x07, 0x87, 0x67, 0xe7, 0x27, 0xa7, 0xdf, | ||
109 | 0x9f, 0x7f, 0xff, 0x3f, 0xbf, 0x4f, 0xcf, 0x0f, | ||
110 | 0x8f, 0x6f, 0xef, 0x2f, 0x53, 0x13, 0x73, 0x33, | ||
111 | 0xb3, 0x43, 0xc3, 0x03, 0x83, 0x63, 0xe3, 0x23, | ||
112 | 0xa3, 0x5b, 0xdb, 0x1b, 0x9b, 0x7b, 0xfb, 0x3b, | ||
113 | 0xbb, 0xbb, 0x4b, 0x4b, 0xcb, 0xcb, 0x0b, 0x0b, | ||
114 | 0x8b, 0x8b, 0x6b, 0x6b, 0xeb, 0xeb, 0x2b, 0x2b, | ||
115 | 0xab, 0x54, 0xd4, 0x14, 0x94, 0x74, 0xf4, 0x34, | ||
116 | 0xb4, 0x44, 0xc4, 0x04, 0x84, 0x64, 0xe4, 0x24, | ||
117 | 0xa4, 0x5c, 0xdc, 0x1c, 0x9c, 0x7c, 0xfc, 0x3c, | ||
118 | 0xbc, 0x4c, 0xcc, 0x0c, 0x8c, 0x6c, 0xec, 0x2c, | ||
119 | 0xac, 0x50, 0xd0, 0x10, 0x90, 0x70, 0xf0, 0x30, | ||
120 | 0xb0, 0x40, 0xc0, 0x00, 0x80, 0x60, 0xe0, 0x20, | ||
121 | 0x58, 0xd8, 0x18, 0x98, 0x78, 0xf8, 0x38, 0xb8, | ||
122 | 0x48, 0xc8, 0x08, 0x88, 0x68, 0xe8, 0x28, 0xa8, | ||
123 | 0xd6, 0x16, 0x96, 0x76, 0xf6, 0x36, 0xb6, 0x46, | ||
124 | 0xc6, 0x06, 0x86, 0x66, 0xe6, 0x26, 0xa6, 0xde, | ||
125 | 0x9e, 0x7e, 0xfe, 0x3e, 0xbe, 0x4e, 0xce, 0x0e, | ||
126 | 0x8e, 0x6e, 0xee, 0x2e, 0x52, 0x12, 0x72, 0x32, | ||
127 | 0xb2, 0x42, 0xc2, 0x02, 0x82, 0x62, 0xe2, 0x22, | ||
128 | 0xa2, 0x5a, 0xda, 0x1a, 0x9a, 0x7a, 0xfa, 0x3a, | ||
129 | 0xba, 0xba, 0x4a, 0x4a, 0xca, 0xca, 0x0a, 0x0a, | ||
130 | 0x8a, 0x8a, 0x6a, 0x6a, 0xea, 0xea, 0x2a, 0x2a | ||
131 | }; | ||
132 | |||
133 | /* alaw -> 4bit compression */ | ||
134 | static u8 alaw_to_4bit[256] = { | ||
135 | 0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03, | ||
136 | 0x0d, 0x02, 0x08, 0x07, 0x0f, 0x00, 0x0b, 0x04, | ||
137 | 0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03, | ||
138 | 0x0d, 0x02, 0x09, 0x06, 0x0f, 0x00, 0x0b, 0x04, | ||
139 | 0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03, | ||
140 | 0x0d, 0x02, 0x08, 0x07, 0x0f, 0x00, 0x0b, 0x04, | ||
141 | 0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03, | ||
142 | 0x0d, 0x02, 0x09, 0x06, 0x0f, 0x00, 0x0b, 0x04, | ||
143 | 0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03, | ||
144 | 0x0d, 0x02, 0x08, 0x07, 0x0f, 0x00, 0x0b, 0x04, | ||
145 | 0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0d, 0x02, | ||
146 | 0x0e, 0x02, 0x09, 0x06, 0x0f, 0x00, 0x0b, 0x04, | ||
147 | 0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03, | ||
148 | 0x0d, 0x02, 0x08, 0x07, 0x0f, 0x00, 0x0b, 0x04, | ||
149 | 0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03, | ||
150 | 0x0d, 0x02, 0x09, 0x06, 0x0f, 0x00, 0x0b, 0x04, | ||
151 | 0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03, | ||
152 | 0x0d, 0x02, 0x08, 0x07, 0x0f, 0x00, 0x0b, 0x04, | ||
153 | 0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03, | ||
154 | 0x0d, 0x02, 0x09, 0x06, 0x0f, 0x00, 0x0b, 0x04, | ||
155 | 0x0e, 0x02, 0x09, 0x06, 0x0f, 0x00, 0x0b, 0x04, | ||
156 | 0x0d, 0x02, 0x08, 0x07, 0x0f, 0x01, 0x0a, 0x05, | ||
157 | 0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03, | ||
158 | 0x0d, 0x02, 0x09, 0x07, 0x0f, 0x00, 0x0b, 0x04, | ||
159 | 0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03, | ||
160 | 0x0d, 0x02, 0x08, 0x07, 0x0f, 0x00, 0x0b, 0x04, | ||
161 | 0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03, | ||
162 | 0x0d, 0x02, 0x09, 0x06, 0x0f, 0x00, 0x0b, 0x04, | ||
163 | 0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03, | ||
164 | 0x0d, 0x02, 0x08, 0x07, 0x0f, 0x00, 0x0b, 0x04, | ||
165 | 0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03, | ||
166 | 0x0d, 0x02, 0x09, 0x06, 0x0f, 0x00, 0x0b, 0x04, | ||
167 | }; | ||
168 | |||
169 | /* 4bit -> alaw decompression */ | ||
170 | static u8 _4bit_to_alaw[16] = { | ||
171 | 0x5d, 0x51, 0xd9, 0xd7, 0x5f, 0x53, 0xa3, 0x4b, | ||
172 | 0x2a, 0x3a, 0x22, 0x2e, 0x26, 0x56, 0x20, 0x2c, | ||
173 | }; | ||
174 | |||
175 | /* ulaw -> 4bit compression */ | ||
176 | static u8 ulaw_to_4bit[256] = { | ||
177 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
178 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
179 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
180 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
181 | 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, | ||
182 | 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, | ||
183 | 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, | ||
184 | 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, | ||
185 | 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, | ||
186 | 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, | ||
187 | 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, | ||
188 | 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, | ||
189 | 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, | ||
190 | 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, | ||
191 | 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, | ||
192 | 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x08, | ||
193 | 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, | ||
194 | 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, | ||
195 | 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, | ||
196 | 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, | ||
197 | 0x0f, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, | ||
198 | 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, | ||
199 | 0x0e, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, | ||
200 | 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, | ||
201 | 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, | ||
202 | 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b, | ||
203 | 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, | ||
204 | 0x0b, 0x0b, 0x0b, 0x0b, 0x0a, 0x0a, 0x0a, 0x0a, | ||
205 | 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, | ||
206 | 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, | ||
207 | 0x09, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, | ||
208 | 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, | ||
209 | }; | ||
210 | |||
211 | /* 4bit -> ulaw decompression */ | ||
212 | static u8 _4bit_to_ulaw[16] = { | ||
213 | 0x11, 0x21, 0x31, 0x40, 0x4e, 0x5c, 0x68, 0x71, | ||
214 | 0xfe, 0xef, 0xe7, 0xdb, 0xcd, 0xbf, 0xaf, 0x9f, | ||
215 | }; | ||
216 | |||
217 | |||
218 | /* | ||
219 | * Compresses data to the result buffer | ||
220 | * The result size must be at least half of the input buffer. | ||
221 | * The number of samples also must be even! | ||
222 | */ | ||
223 | int | ||
224 | l1oip_law_to_4bit(u8 *data, int len, u8 *result, u32 *state) | ||
225 | { | ||
226 | int ii, i = 0, o = 0; | ||
227 | |||
228 | if (!len) | ||
229 | return 0; | ||
230 | |||
231 | /* send saved byte and first input byte */ | ||
232 | if (*state) { | ||
233 | *result++ = table_com[(((*state)<<8)&0xff00) | (*data++)]; | ||
234 | len--; | ||
235 | o++; | ||
236 | } | ||
237 | |||
238 | ii = len >> 1; | ||
239 | |||
240 | while (i < ii) { | ||
241 | *result++ = table_com[(data[0]<<8) | (data[1])]; | ||
242 | data += 2; | ||
243 | i++; | ||
244 | o++; | ||
245 | } | ||
246 | |||
247 | /* if len has an odd number, we save byte for next call */ | ||
248 | if (len & 1) | ||
249 | *state = 0x100 + *data; | ||
250 | else | ||
251 | *state = 0; | ||
252 | |||
253 | return o; | ||
254 | } | ||
255 | |||
256 | /* Decompress data to the result buffer | ||
257 | * The result size must be the number of sample in packet. (2 * input data) | ||
258 | * The number of samples in the result are even! | ||
259 | */ | ||
260 | int | ||
261 | l1oip_4bit_to_law(u8 *data, int len, u8 *result) | ||
262 | { | ||
263 | int i = 0; | ||
264 | u16 r; | ||
265 | |||
266 | while (i < len) { | ||
267 | r = table_dec[*data++]; | ||
268 | *result++ = r>>8; | ||
269 | *result++ = r; | ||
270 | i++; | ||
271 | } | ||
272 | |||
273 | return len << 1; | ||
274 | } | ||
275 | |||
276 | |||
277 | /* | ||
278 | * law conversion | ||
279 | */ | ||
280 | int | ||
281 | l1oip_alaw_to_ulaw(u8 *data, int len, u8 *result) | ||
282 | { | ||
283 | int i = 0; | ||
284 | |||
285 | while (i < len) { | ||
286 | *result++ = alaw_to_ulaw[*data++]; | ||
287 | i++; | ||
288 | } | ||
289 | |||
290 | return len; | ||
291 | } | ||
292 | |||
293 | int | ||
294 | l1oip_ulaw_to_alaw(u8 *data, int len, u8 *result) | ||
295 | { | ||
296 | int i = 0; | ||
297 | |||
298 | while (i < len) { | ||
299 | *result++ = ulaw_to_alaw[*data++]; | ||
300 | i++; | ||
301 | } | ||
302 | |||
303 | return len; | ||
304 | } | ||
305 | |||
306 | |||
307 | /* | ||
308 | * generate/free compression and decompression table | ||
309 | */ | ||
310 | void | ||
311 | l1oip_4bit_free(void) | ||
312 | { | ||
313 | if (table_dec) | ||
314 | vfree(table_dec); | ||
315 | if (table_com) | ||
316 | vfree(table_com); | ||
317 | table_com = NULL; | ||
318 | table_dec = NULL; | ||
319 | } | ||
320 | |||
321 | int | ||
322 | l1oip_4bit_alloc(int ulaw) | ||
323 | { | ||
324 | int i1, i2, c, sample; | ||
325 | |||
326 | /* in case, it is called again */ | ||
327 | if (table_dec) | ||
328 | return 0; | ||
329 | |||
330 | /* alloc conversion tables */ | ||
331 | table_com = vmalloc(65536); | ||
332 | table_dec = vmalloc(512); | ||
333 | if (!table_com | !table_dec) { | ||
334 | l1oip_4bit_free(); | ||
335 | return -ENOMEM; | ||
336 | } | ||
337 | memset(table_com, 0, 65536); | ||
338 | memset(table_dec, 0, 512); | ||
339 | /* generate compression table */ | ||
340 | i1 = 0; | ||
341 | while (i1 < 256) { | ||
342 | if (ulaw) | ||
343 | c = ulaw_to_4bit[i1]; | ||
344 | else | ||
345 | c = alaw_to_4bit[i1]; | ||
346 | i2 = 0; | ||
347 | while (i2 < 256) { | ||
348 | table_com[(i1<<8) | i2] |= (c<<4); | ||
349 | table_com[(i2<<8) | i1] |= c; | ||
350 | i2++; | ||
351 | } | ||
352 | i1++; | ||
353 | } | ||
354 | |||
355 | /* generate decompression table */ | ||
356 | i1 = 0; | ||
357 | while (i1 < 16) { | ||
358 | if (ulaw) | ||
359 | sample = _4bit_to_ulaw[i1]; | ||
360 | else | ||
361 | sample = _4bit_to_alaw[i1]; | ||
362 | i2 = 0; | ||
363 | while (i2 < 16) { | ||
364 | table_dec[(i1<<4) | i2] |= (sample<<8); | ||
365 | table_dec[(i2<<4) | i1] |= sample; | ||
366 | i2++; | ||
367 | } | ||
368 | i1++; | ||
369 | } | ||
370 | |||
371 | return 0; | ||
372 | } | ||
373 | |||
374 | |||
diff --git a/drivers/isdn/mISDN/l1oip_core.c b/drivers/isdn/mISDN/l1oip_core.c new file mode 100644 index 000000000000..155b99780c4f --- /dev/null +++ b/drivers/isdn/mISDN/l1oip_core.c | |||
@@ -0,0 +1,1518 @@ | |||
1 | /* | ||
2 | |||
3 | * l1oip.c low level driver for tunneling layer 1 over IP | ||
4 | * | ||
5 | * NOTE: It is not compatible with TDMoIP nor "ISDN over IP". | ||
6 | * | ||
7 | * Author Andreas Eversberg (jolly@eversberg.eu) | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2, or (at your option) | ||
12 | * any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | /* module parameters: | ||
26 | * type: | ||
27 | Value 1 = BRI | ||
28 | Value 2 = PRI | ||
29 | Value 3 = BRI (multi channel frame, not supported yet) | ||
30 | Value 4 = PRI (multi channel frame, not supported yet) | ||
31 | A multi channel frame reduces overhead to a single frame for all | ||
32 | b-channels, but increases delay. | ||
33 | (NOTE: Multi channel frames are not implemented yet.) | ||
34 | |||
35 | * codec: | ||
36 | Value 0 = transparent (default) | ||
37 | Value 1 = transfer ALAW | ||
38 | Value 2 = transfer ULAW | ||
39 | Value 3 = transfer generic 4 bit compression. | ||
40 | |||
41 | * ulaw: | ||
42 | 0 = we use a-Law (default) | ||
43 | 1 = we use u-Law | ||
44 | |||
45 | * limit: | ||
46 | limitation of B-channels to control bandwidth (1...126) | ||
47 | BRI: 1 or 2 | ||
48 | PRI: 1-30, 31-126 (126, because dchannel ist not counted here) | ||
49 | Also limited ressources are used for stack, resulting in less channels. | ||
50 | It is possible to have more channels than 30 in PRI mode, this must | ||
51 | be supported by the application. | ||
52 | |||
53 | * ip: | ||
54 | byte representation of remote ip address (127.0.0.1 -> 127,0,0,1) | ||
55 | If not given or four 0, no remote address is set. | ||
56 | For multiple interfaces, concat ip addresses. (127,0,0,1,127,0,0,1) | ||
57 | |||
58 | * port: | ||
59 | port number (local interface) | ||
60 | If not given or 0, port 931 is used for fist instance, 932 for next... | ||
61 | For multiple interfaces, different ports must be given. | ||
62 | |||
63 | * remoteport: | ||
64 | port number (remote interface) | ||
65 | If not given or 0, remote port equals local port | ||
66 | For multiple interfaces on equal sites, different ports must be given. | ||
67 | |||
68 | * ondemand: | ||
69 | 0 = fixed (always transmit packets, even when remote side timed out) | ||
70 | 1 = on demand (only transmit packets, when remote side is detected) | ||
71 | the default is 0 | ||
72 | NOTE: ID must also be set for on demand. | ||
73 | |||
74 | * id: | ||
75 | optional value to identify frames. This value must be equal on both | ||
76 | peers and should be random. If omitted or 0, no ID is transmitted. | ||
77 | |||
78 | * debug: | ||
79 | NOTE: only one debug value must be given for all cards | ||
80 | enable debugging (see l1oip.h for debug options) | ||
81 | |||
82 | |||
83 | Special mISDN controls: | ||
84 | |||
85 | op = MISDN_CTRL_SETPEER* | ||
86 | p1 = bytes 0-3 : remote IP address in network order (left element first) | ||
87 | p2 = bytes 1-2 : remote port in network order (high byte first) | ||
88 | optional: | ||
89 | p2 = bytes 3-4 : local port in network order (high byte first) | ||
90 | |||
91 | op = MISDN_CTRL_UNSETPEER* | ||
92 | |||
93 | * Use l1oipctrl for comfortable setting or removing ip address. | ||
94 | (Layer 1 Over IP CTRL) | ||
95 | |||
96 | |||
97 | L1oIP-Protocol | ||
98 | -------------- | ||
99 | |||
100 | Frame Header: | ||
101 | |||
102 | 7 6 5 4 3 2 1 0 | ||
103 | +---------------+ | ||
104 | |Ver|T|I|Coding | | ||
105 | +---------------+ | ||
106 | | ID byte 3 * | | ||
107 | +---------------+ | ||
108 | | ID byte 2 * | | ||
109 | +---------------+ | ||
110 | | ID byte 1 * | | ||
111 | +---------------+ | ||
112 | | ID byte 0 * | | ||
113 | +---------------+ | ||
114 | |M| Channel | | ||
115 | +---------------+ | ||
116 | | Length * | | ||
117 | +---------------+ | ||
118 | | Time Base MSB | | ||
119 | +---------------+ | ||
120 | | Time Base LSB | | ||
121 | +---------------+ | ||
122 | | Data.... | | ||
123 | |||
124 | ... | ||
125 | |||
126 | | | | ||
127 | +---------------+ | ||
128 | |M| Channel | | ||
129 | +---------------+ | ||
130 | | Length * | | ||
131 | +---------------+ | ||
132 | | Time Base MSB | | ||
133 | +---------------+ | ||
134 | | Time Base LSB | | ||
135 | +---------------+ | ||
136 | | Data.... | | ||
137 | |||
138 | ... | ||
139 | |||
140 | |||
141 | * Only included in some cases. | ||
142 | |||
143 | - Ver = Version | ||
144 | If version is missmatch, the frame must be ignored. | ||
145 | |||
146 | - T = Type of interface | ||
147 | Must be 0 for S0 or 1 for E1. | ||
148 | |||
149 | - I = Id present | ||
150 | If bit is set, four ID bytes are included in frame. | ||
151 | |||
152 | - ID = Connection ID | ||
153 | Additional ID to prevent Denial of Service attacs. Also it prevents hijacking | ||
154 | connections with dynamic IP. The ID should be random and must not be 0. | ||
155 | |||
156 | - Coding = Type of codec | ||
157 | Must be 0 for no transcoding. Also for D-channel and other HDLC frames. | ||
158 | 1 and 2 are reserved for explicitly use of a-LAW or u-LAW codec. | ||
159 | 3 is used for generic table compressor. | ||
160 | |||
161 | - M = More channels to come. If this flag is 1, the following byte contains | ||
162 | the length of the channel data. After the data block, the next channel will | ||
163 | be defined. The flag for the last channel block (or if only one channel is | ||
164 | transmitted), must be 0 and no length is given. | ||
165 | |||
166 | - Channel = Channel number | ||
167 | 0 reserved | ||
168 | 1-3 channel data for S0 (3 is D-channel) | ||
169 | 1-31 channel data for E1 (16 is D-channel) | ||
170 | 32-127 channel data for extended E1 (16 is D-channel) | ||
171 | |||
172 | - The length is used if the M-flag is 1. It is used to find the next channel | ||
173 | inside frame. | ||
174 | NOTE: A value of 0 equals 256 bytes of data. | ||
175 | -> For larger data blocks, a single frame must be used. | ||
176 | -> For larger streams, a single frame or multiple blocks with same channel ID | ||
177 | must be used. | ||
178 | |||
179 | - Time Base = Timestamp of first sample in frame | ||
180 | The "Time Base" is used to rearange packets and to detect packet loss. | ||
181 | The 16 bits are sent in network order (MSB first) and count 1/8000 th of a | ||
182 | second. This causes a wrap arround each 8,192 seconds. There is no requirement | ||
183 | for the initial "Time Base", but 0 should be used for the first packet. | ||
184 | In case of HDLC data, this timestamp counts the packet or byte number. | ||
185 | |||
186 | |||
187 | Two Timers: | ||
188 | |||
189 | After initialisation, a timer of 15 seconds is started. Whenever a packet is | ||
190 | transmitted, the timer is reset to 15 seconds again. If the timer expires, an | ||
191 | empty packet is transmitted. This keep the connection alive. | ||
192 | |||
193 | When a valid packet is received, a timer 65 seconds is started. The interface | ||
194 | become ACTIVE. If the timer expires, the interface becomes INACTIVE. | ||
195 | |||
196 | |||
197 | Dynamic IP handling: | ||
198 | |||
199 | To allow dynamic IP, the ID must be non 0. In this case, any packet with the | ||
200 | correct port number and ID will be accepted. If the remote side changes its IP | ||
201 | the new IP is used for all transmitted packets until it changes again. | ||
202 | |||
203 | |||
204 | On Demand: | ||
205 | |||
206 | If the ondemand parameter is given, the remote IP is set to 0 on timeout. | ||
207 | This will stop keepalive traffic to remote. If the remote is online again, | ||
208 | traffic will continue to the remote address. This is usefull for road warriors. | ||
209 | This feature only works with ID set, otherwhise it is highly unsecure. | ||
210 | |||
211 | |||
212 | Socket and Thread | ||
213 | ----------------- | ||
214 | |||
215 | The complete socket opening and closing is done by a thread. | ||
216 | When the thread opened a socket, the hc->socket descriptor is set. Whenever a | ||
217 | packet shall be sent to the socket, the hc->socket must be checked wheter not | ||
218 | NULL. To prevent change in socket descriptor, the hc->socket_lock must be used. | ||
219 | To change the socket, a recall of l1oip_socket_open() will safely kill the | ||
220 | socket process and create a new one. | ||
221 | |||
222 | */ | ||
223 | |||
224 | #define L1OIP_VERSION 0 /* 0...3 */ | ||
225 | |||
226 | #include <linux/module.h> | ||
227 | #include <linux/delay.h> | ||
228 | #include <linux/mISDNif.h> | ||
229 | #include <linux/mISDNhw.h> | ||
230 | #include <linux/mISDNdsp.h> | ||
231 | #include <linux/init.h> | ||
232 | #include <linux/in.h> | ||
233 | #include <linux/inet.h> | ||
234 | #include <linux/workqueue.h> | ||
235 | #include <linux/kthread.h> | ||
236 | #include <net/sock.h> | ||
237 | #include "core.h" | ||
238 | #include "l1oip.h" | ||
239 | |||
240 | static const char *l1oip_revision = "2.00"; | ||
241 | |||
242 | static int l1oip_cnt; | ||
243 | static spinlock_t l1oip_lock; | ||
244 | static struct list_head l1oip_ilist; | ||
245 | |||
246 | #define MAX_CARDS 16 | ||
247 | static u_int type[MAX_CARDS]; | ||
248 | static u_int codec[MAX_CARDS]; | ||
249 | static u_int ip[MAX_CARDS*4]; | ||
250 | static u_int port[MAX_CARDS]; | ||
251 | static u_int remoteport[MAX_CARDS]; | ||
252 | static u_int ondemand[MAX_CARDS]; | ||
253 | static u_int limit[MAX_CARDS]; | ||
254 | static u_int id[MAX_CARDS]; | ||
255 | static int debug; | ||
256 | static int ulaw; | ||
257 | |||
258 | MODULE_AUTHOR("Andreas Eversberg"); | ||
259 | MODULE_LICENSE("GPL"); | ||
260 | module_param_array(type, uint, NULL, S_IRUGO | S_IWUSR); | ||
261 | module_param_array(codec, uint, NULL, S_IRUGO | S_IWUSR); | ||
262 | module_param_array(ip, uint, NULL, S_IRUGO | S_IWUSR); | ||
263 | module_param_array(port, uint, NULL, S_IRUGO | S_IWUSR); | ||
264 | module_param_array(remoteport, uint, NULL, S_IRUGO | S_IWUSR); | ||
265 | module_param_array(ondemand, uint, NULL, S_IRUGO | S_IWUSR); | ||
266 | module_param_array(limit, uint, NULL, S_IRUGO | S_IWUSR); | ||
267 | module_param_array(id, uint, NULL, S_IRUGO | S_IWUSR); | ||
268 | module_param(ulaw, uint, S_IRUGO | S_IWUSR); | ||
269 | module_param(debug, uint, S_IRUGO | S_IWUSR); | ||
270 | |||
271 | /* | ||
272 | * send a frame via socket, if open and restart timer | ||
273 | */ | ||
274 | static int | ||
275 | l1oip_socket_send(struct l1oip *hc, u8 localcodec, u8 channel, u32 chanmask, | ||
276 | u16 timebase, u8 *buf, int len) | ||
277 | { | ||
278 | u8 *p; | ||
279 | int multi = 0; | ||
280 | u8 frame[len+32]; | ||
281 | struct socket *socket = NULL; | ||
282 | mm_segment_t oldfs; | ||
283 | |||
284 | if (debug & DEBUG_L1OIP_MSG) | ||
285 | printk(KERN_DEBUG "%s: sending data to socket (len = %d)\n", | ||
286 | __func__, len); | ||
287 | |||
288 | p = frame; | ||
289 | |||
290 | /* restart timer */ | ||
291 | if ((int)(hc->keep_tl.expires-jiffies) < 5*HZ) { | ||
292 | del_timer(&hc->keep_tl); | ||
293 | hc->keep_tl.expires = jiffies + L1OIP_KEEPALIVE*HZ; | ||
294 | add_timer(&hc->keep_tl); | ||
295 | } else | ||
296 | hc->keep_tl.expires = jiffies + L1OIP_KEEPALIVE*HZ; | ||
297 | |||
298 | if (debug & DEBUG_L1OIP_MSG) | ||
299 | printk(KERN_DEBUG "%s: resetting timer\n", __func__); | ||
300 | |||
301 | /* drop if we have no remote ip or port */ | ||
302 | if (!hc->sin_remote.sin_addr.s_addr || !hc->sin_remote.sin_port) { | ||
303 | if (debug & DEBUG_L1OIP_MSG) | ||
304 | printk(KERN_DEBUG "%s: dropping frame, because remote " | ||
305 | "IP is not set.\n", __func__); | ||
306 | return len; | ||
307 | } | ||
308 | |||
309 | /* assemble frame */ | ||
310 | *p++ = (L1OIP_VERSION<<6) /* version and coding */ | ||
311 | | (hc->pri?0x20:0x00) /* type */ | ||
312 | | (hc->id?0x10:0x00) /* id */ | ||
313 | | localcodec; | ||
314 | if (hc->id) { | ||
315 | *p++ = hc->id>>24; /* id */ | ||
316 | *p++ = hc->id>>16; | ||
317 | *p++ = hc->id>>8; | ||
318 | *p++ = hc->id; | ||
319 | } | ||
320 | *p++ = (multi == 1)?0x80:0x00 + channel; /* m-flag, channel */ | ||
321 | if (multi == 1) | ||
322 | *p++ = len; /* length */ | ||
323 | *p++ = timebase>>8; /* time base */ | ||
324 | *p++ = timebase; | ||
325 | |||
326 | if (buf && len) { /* add data to frame */ | ||
327 | if (localcodec == 1 && ulaw) | ||
328 | l1oip_ulaw_to_alaw(buf, len, p); | ||
329 | else if (localcodec == 2 && !ulaw) | ||
330 | l1oip_alaw_to_ulaw(buf, len, p); | ||
331 | else if (localcodec == 3) | ||
332 | len = l1oip_law_to_4bit(buf, len, p, | ||
333 | &hc->chan[channel].codecstate); | ||
334 | else | ||
335 | memcpy(p, buf, len); | ||
336 | } | ||
337 | len += p - frame; | ||
338 | |||
339 | /* check for socket in safe condition */ | ||
340 | spin_lock(&hc->socket_lock); | ||
341 | if (!hc->socket) { | ||
342 | spin_unlock(&hc->socket_lock); | ||
343 | return 0; | ||
344 | } | ||
345 | /* seize socket */ | ||
346 | socket = hc->socket; | ||
347 | hc->socket = NULL; | ||
348 | spin_unlock(&hc->socket_lock); | ||
349 | /* send packet */ | ||
350 | if (debug & DEBUG_L1OIP_MSG) | ||
351 | printk(KERN_DEBUG "%s: sending packet to socket (len " | ||
352 | "= %d)\n", __func__, len); | ||
353 | hc->sendiov.iov_base = frame; | ||
354 | hc->sendiov.iov_len = len; | ||
355 | oldfs = get_fs(); | ||
356 | set_fs(KERNEL_DS); | ||
357 | len = sock_sendmsg(socket, &hc->sendmsg, len); | ||
358 | set_fs(oldfs); | ||
359 | /* give socket back */ | ||
360 | hc->socket = socket; /* no locking required */ | ||
361 | |||
362 | return len; | ||
363 | } | ||
364 | |||
365 | |||
366 | /* | ||
367 | * receive channel data from socket | ||
368 | */ | ||
369 | static void | ||
370 | l1oip_socket_recv(struct l1oip *hc, u8 remotecodec, u8 channel, u16 timebase, | ||
371 | u8 *buf, int len) | ||
372 | { | ||
373 | struct sk_buff *nskb; | ||
374 | struct bchannel *bch; | ||
375 | struct dchannel *dch; | ||
376 | u8 *p; | ||
377 | u32 rx_counter; | ||
378 | |||
379 | if (len == 0) { | ||
380 | if (debug & DEBUG_L1OIP_MSG) | ||
381 | printk(KERN_DEBUG "%s: received empty keepalive data, " | ||
382 | "ignoring\n", __func__); | ||
383 | return; | ||
384 | } | ||
385 | |||
386 | if (debug & DEBUG_L1OIP_MSG) | ||
387 | printk(KERN_DEBUG "%s: received data, sending to mISDN (%d)\n", | ||
388 | __func__, len); | ||
389 | |||
390 | if (channel < 1 || channel > 127) { | ||
391 | printk(KERN_WARNING "%s: packet error - channel %d out of " | ||
392 | "range\n", __func__, channel); | ||
393 | return; | ||
394 | } | ||
395 | dch = hc->chan[channel].dch; | ||
396 | bch = hc->chan[channel].bch; | ||
397 | if (!dch && !bch) { | ||
398 | printk(KERN_WARNING "%s: packet error - channel %d not in " | ||
399 | "stack\n", __func__, channel); | ||
400 | return; | ||
401 | } | ||
402 | |||
403 | /* prepare message */ | ||
404 | nskb = mI_alloc_skb((remotecodec == 3)?(len<<1):len, GFP_ATOMIC); | ||
405 | if (!nskb) { | ||
406 | printk(KERN_ERR "%s: No mem for skb.\n", __func__); | ||
407 | return; | ||
408 | } | ||
409 | p = skb_put(nskb, (remotecodec == 3)?(len<<1):len); | ||
410 | |||
411 | if (remotecodec == 1 && ulaw) | ||
412 | l1oip_alaw_to_ulaw(buf, len, p); | ||
413 | else if (remotecodec == 2 && !ulaw) | ||
414 | l1oip_ulaw_to_alaw(buf, len, p); | ||
415 | else if (remotecodec == 3) | ||
416 | len = l1oip_4bit_to_law(buf, len, p); | ||
417 | else | ||
418 | memcpy(p, buf, len); | ||
419 | |||
420 | /* send message up */ | ||
421 | if (dch && len >= 2) { | ||
422 | dch->rx_skb = nskb; | ||
423 | recv_Dchannel(dch); | ||
424 | } | ||
425 | if (bch) { | ||
426 | /* expand 16 bit sequence number to 32 bit sequence number */ | ||
427 | rx_counter = hc->chan[channel].rx_counter; | ||
428 | if (((s16)(timebase - rx_counter)) >= 0) { | ||
429 | /* time has changed forward */ | ||
430 | if (timebase >= (rx_counter & 0xffff)) | ||
431 | rx_counter = | ||
432 | (rx_counter & 0xffff0000) | timebase; | ||
433 | else | ||
434 | rx_counter = ((rx_counter & 0xffff0000)+0x10000) | ||
435 | | timebase; | ||
436 | } else { | ||
437 | /* time has changed backwards */ | ||
438 | if (timebase < (rx_counter & 0xffff)) | ||
439 | rx_counter = | ||
440 | (rx_counter & 0xffff0000) | timebase; | ||
441 | else | ||
442 | rx_counter = ((rx_counter & 0xffff0000)-0x10000) | ||
443 | | timebase; | ||
444 | } | ||
445 | hc->chan[channel].rx_counter = rx_counter; | ||
446 | |||
447 | #ifdef REORDER_DEBUG | ||
448 | if (hc->chan[channel].disorder_flag) { | ||
449 | struct sk_buff *skb; | ||
450 | int cnt; | ||
451 | skb = hc->chan[channel].disorder_skb; | ||
452 | hc->chan[channel].disorder_skb = nskb; | ||
453 | nskb = skb; | ||
454 | cnt = hc->chan[channel].disorder_cnt; | ||
455 | hc->chan[channel].disorder_cnt = rx_counter; | ||
456 | rx_counter = cnt; | ||
457 | } | ||
458 | hc->chan[channel].disorder_flag ^= 1; | ||
459 | if (nskb) | ||
460 | #endif | ||
461 | queue_ch_frame(&bch->ch, PH_DATA_IND, rx_counter, nskb); | ||
462 | } | ||
463 | } | ||
464 | |||
465 | |||
466 | /* | ||
467 | * parse frame and extract channel data | ||
468 | */ | ||
469 | static void | ||
470 | l1oip_socket_parse(struct l1oip *hc, struct sockaddr_in *sin, u8 *buf, int len) | ||
471 | { | ||
472 | u32 id; | ||
473 | u8 channel; | ||
474 | u8 remotecodec; | ||
475 | u16 timebase; | ||
476 | int m, mlen; | ||
477 | int len_start = len; /* initial frame length */ | ||
478 | struct dchannel *dch = hc->chan[hc->d_idx].dch; | ||
479 | |||
480 | if (debug & DEBUG_L1OIP_MSG) | ||
481 | printk(KERN_DEBUG "%s: received frame, parsing... (%d)\n", | ||
482 | __func__, len); | ||
483 | |||
484 | /* check lenght */ | ||
485 | if (len < 1+1+2) { | ||
486 | printk(KERN_WARNING "%s: packet error - length %d below " | ||
487 | "4 bytes\n", __func__, len); | ||
488 | return; | ||
489 | } | ||
490 | |||
491 | /* check version */ | ||
492 | if (((*buf)>>6) != L1OIP_VERSION) { | ||
493 | printk(KERN_WARNING "%s: packet error - unknown version %d\n", | ||
494 | __func__, buf[0]>>6); | ||
495 | return; | ||
496 | } | ||
497 | |||
498 | /* check type */ | ||
499 | if (((*buf)&0x20) && !hc->pri) { | ||
500 | printk(KERN_WARNING "%s: packet error - received E1 packet " | ||
501 | "on S0 interface\n", __func__); | ||
502 | return; | ||
503 | } | ||
504 | if (!((*buf)&0x20) && hc->pri) { | ||
505 | printk(KERN_WARNING "%s: packet error - received S0 packet " | ||
506 | "on E1 interface\n", __func__); | ||
507 | return; | ||
508 | } | ||
509 | |||
510 | /* get id flag */ | ||
511 | id = (*buf>>4)&1; | ||
512 | |||
513 | /* check coding */ | ||
514 | remotecodec = (*buf) & 0x0f; | ||
515 | if (remotecodec > 3) { | ||
516 | printk(KERN_WARNING "%s: packet error - remotecodec %d " | ||
517 | "unsupported\n", __func__, remotecodec); | ||
518 | return; | ||
519 | } | ||
520 | buf++; | ||
521 | len--; | ||
522 | |||
523 | /* check id */ | ||
524 | if (id) { | ||
525 | if (!hc->id) { | ||
526 | printk(KERN_WARNING "%s: packet error - packet has id " | ||
527 | "0x%x, but we have not\n", __func__, id); | ||
528 | return; | ||
529 | } | ||
530 | if (len < 4) { | ||
531 | printk(KERN_WARNING "%s: packet error - packet too " | ||
532 | "short for ID value\n", __func__); | ||
533 | return; | ||
534 | } | ||
535 | id = (*buf++) << 24; | ||
536 | id += (*buf++) << 16; | ||
537 | id += (*buf++) << 8; | ||
538 | id += (*buf++); | ||
539 | len -= 4; | ||
540 | |||
541 | if (id != hc->id) { | ||
542 | printk(KERN_WARNING "%s: packet error - ID mismatch, " | ||
543 | "got 0x%x, we 0x%x\n", | ||
544 | __func__, id, hc->id); | ||
545 | return; | ||
546 | } | ||
547 | } else { | ||
548 | if (hc->id) { | ||
549 | printk(KERN_WARNING "%s: packet error - packet has no " | ||
550 | "ID, but we have\n", __func__); | ||
551 | return; | ||
552 | } | ||
553 | } | ||
554 | |||
555 | multiframe: | ||
556 | if (len < 1) { | ||
557 | printk(KERN_WARNING "%s: packet error - packet too short, " | ||
558 | "channel expected at position %d.\n", | ||
559 | __func__, len-len_start+1); | ||
560 | return; | ||
561 | } | ||
562 | |||
563 | /* get channel and multiframe flag */ | ||
564 | channel = *buf&0x7f; | ||
565 | m = *buf >> 7; | ||
566 | buf++; | ||
567 | len--; | ||
568 | |||
569 | /* check length on multiframe */ | ||
570 | if (m) { | ||
571 | if (len < 1) { | ||
572 | printk(KERN_WARNING "%s: packet error - packet too " | ||
573 | "short, length expected at position %d.\n", | ||
574 | __func__, len_start-len-1); | ||
575 | return; | ||
576 | } | ||
577 | |||
578 | mlen = *buf++; | ||
579 | len--; | ||
580 | if (mlen == 0) | ||
581 | mlen = 256; | ||
582 | if (len < mlen+3) { | ||
583 | printk(KERN_WARNING "%s: packet error - length %d at " | ||
584 | "position %d exceeds total length %d.\n", | ||
585 | __func__, mlen, len_start-len-1, len_start); | ||
586 | return; | ||
587 | } | ||
588 | if (len == mlen+3) { | ||
589 | printk(KERN_WARNING "%s: packet error - length %d at " | ||
590 | "position %d will not allow additional " | ||
591 | "packet.\n", | ||
592 | __func__, mlen, len_start-len+1); | ||
593 | return; | ||
594 | } | ||
595 | } else | ||
596 | mlen = len-2; /* single frame, substract timebase */ | ||
597 | |||
598 | if (len < 2) { | ||
599 | printk(KERN_WARNING "%s: packet error - packet too short, time " | ||
600 | "base expected at position %d.\n", | ||
601 | __func__, len-len_start+1); | ||
602 | return; | ||
603 | } | ||
604 | |||
605 | /* get time base */ | ||
606 | timebase = (*buf++) << 8; | ||
607 | timebase |= (*buf++); | ||
608 | len -= 2; | ||
609 | |||
610 | /* if inactive, we send up a PH_ACTIVATE and activate */ | ||
611 | if (!test_bit(FLG_ACTIVE, &dch->Flags)) { | ||
612 | if (debug & (DEBUG_L1OIP_MSG|DEBUG_L1OIP_SOCKET)) | ||
613 | printk(KERN_DEBUG "%s: interface become active due to " | ||
614 | "received packet\n", __func__); | ||
615 | test_and_set_bit(FLG_ACTIVE, &dch->Flags); | ||
616 | _queue_data(&dch->dev.D, PH_ACTIVATE_IND, MISDN_ID_ANY, 0, | ||
617 | NULL, GFP_ATOMIC); | ||
618 | } | ||
619 | |||
620 | /* distribute packet */ | ||
621 | l1oip_socket_recv(hc, remotecodec, channel, timebase, buf, mlen); | ||
622 | buf += mlen; | ||
623 | len -= mlen; | ||
624 | |||
625 | /* multiframe */ | ||
626 | if (m) | ||
627 | goto multiframe; | ||
628 | |||
629 | /* restart timer */ | ||
630 | if ((int)(hc->timeout_tl.expires-jiffies) < 5*HZ || !hc->timeout_on) { | ||
631 | hc->timeout_on = 1; | ||
632 | del_timer(&hc->timeout_tl); | ||
633 | hc->timeout_tl.expires = jiffies + L1OIP_TIMEOUT*HZ; | ||
634 | add_timer(&hc->timeout_tl); | ||
635 | } else /* only adjust timer */ | ||
636 | hc->timeout_tl.expires = jiffies + L1OIP_TIMEOUT*HZ; | ||
637 | |||
638 | /* if ip or source port changes */ | ||
639 | if ((hc->sin_remote.sin_addr.s_addr != sin->sin_addr.s_addr) | ||
640 | || (hc->sin_remote.sin_port != sin->sin_port)) { | ||
641 | if (debug & DEBUG_L1OIP_SOCKET) | ||
642 | printk(KERN_DEBUG "%s: remote address changes from " | ||
643 | "0x%08x to 0x%08x (port %d to %d)\n", __func__, | ||
644 | ntohl(hc->sin_remote.sin_addr.s_addr), | ||
645 | ntohl(sin->sin_addr.s_addr), | ||
646 | ntohs(hc->sin_remote.sin_port), | ||
647 | ntohs(sin->sin_port)); | ||
648 | hc->sin_remote.sin_addr.s_addr = sin->sin_addr.s_addr; | ||
649 | hc->sin_remote.sin_port = sin->sin_port; | ||
650 | } | ||
651 | } | ||
652 | |||
653 | |||
654 | /* | ||
655 | * socket stuff | ||
656 | */ | ||
657 | static int | ||
658 | l1oip_socket_thread(void *data) | ||
659 | { | ||
660 | struct l1oip *hc = (struct l1oip *)data; | ||
661 | int ret = 0; | ||
662 | struct msghdr msg; | ||
663 | struct iovec iov; | ||
664 | mm_segment_t oldfs; | ||
665 | struct sockaddr_in sin_rx; | ||
666 | unsigned char recvbuf[1500]; | ||
667 | int recvlen; | ||
668 | struct socket *socket = NULL; | ||
669 | DECLARE_COMPLETION(wait); | ||
670 | |||
671 | /* make daemon */ | ||
672 | allow_signal(SIGTERM); | ||
673 | |||
674 | /* create socket */ | ||
675 | if (sock_create(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &socket)) { | ||
676 | printk(KERN_ERR "%s: Failed to create socket.\n", __func__); | ||
677 | return -EIO; | ||
678 | } | ||
679 | |||
680 | /* set incoming address */ | ||
681 | hc->sin_local.sin_family = AF_INET; | ||
682 | hc->sin_local.sin_addr.s_addr = INADDR_ANY; | ||
683 | hc->sin_local.sin_port = htons((unsigned short)hc->localport); | ||
684 | |||
685 | /* set outgoing address */ | ||
686 | hc->sin_remote.sin_family = AF_INET; | ||
687 | hc->sin_remote.sin_addr.s_addr = htonl(hc->remoteip); | ||
688 | hc->sin_remote.sin_port = htons((unsigned short)hc->remoteport); | ||
689 | |||
690 | /* bind to incomming port */ | ||
691 | if (socket->ops->bind(socket, (struct sockaddr *)&hc->sin_local, | ||
692 | sizeof(hc->sin_local))) { | ||
693 | printk(KERN_ERR "%s: Failed to bind socket to port %d.\n", | ||
694 | __func__, hc->localport); | ||
695 | ret = -EINVAL; | ||
696 | goto fail; | ||
697 | } | ||
698 | |||
699 | /* check sk */ | ||
700 | if (socket->sk == NULL) { | ||
701 | printk(KERN_ERR "%s: socket->sk == NULL\n", __func__); | ||
702 | ret = -EIO; | ||
703 | goto fail; | ||
704 | } | ||
705 | |||
706 | /* build receive message */ | ||
707 | msg.msg_name = &sin_rx; | ||
708 | msg.msg_namelen = sizeof(sin_rx); | ||
709 | msg.msg_control = NULL; | ||
710 | msg.msg_controllen = 0; | ||
711 | msg.msg_iov = &iov; | ||
712 | msg.msg_iovlen = 1; | ||
713 | |||
714 | /* build send message */ | ||
715 | hc->sendmsg.msg_name = &hc->sin_remote; | ||
716 | hc->sendmsg.msg_namelen = sizeof(hc->sin_remote); | ||
717 | hc->sendmsg.msg_control = NULL; | ||
718 | hc->sendmsg.msg_controllen = 0; | ||
719 | hc->sendmsg.msg_iov = &hc->sendiov; | ||
720 | hc->sendmsg.msg_iovlen = 1; | ||
721 | |||
722 | /* give away socket */ | ||
723 | spin_lock(&hc->socket_lock); | ||
724 | hc->socket = socket; | ||
725 | spin_unlock(&hc->socket_lock); | ||
726 | |||
727 | /* read loop */ | ||
728 | if (debug & DEBUG_L1OIP_SOCKET) | ||
729 | printk(KERN_DEBUG "%s: socket created and open\n", | ||
730 | __func__); | ||
731 | while (!signal_pending(current)) { | ||
732 | iov.iov_base = recvbuf; | ||
733 | iov.iov_len = sizeof(recvbuf); | ||
734 | oldfs = get_fs(); | ||
735 | set_fs(KERNEL_DS); | ||
736 | recvlen = sock_recvmsg(socket, &msg, sizeof(recvbuf), 0); | ||
737 | set_fs(oldfs); | ||
738 | if (recvlen > 0) { | ||
739 | l1oip_socket_parse(hc, &sin_rx, recvbuf, recvlen); | ||
740 | } else { | ||
741 | if (debug & DEBUG_L1OIP_SOCKET) | ||
742 | printk(KERN_WARNING "%s: broken pipe on socket\n", | ||
743 | __func__); | ||
744 | } | ||
745 | } | ||
746 | |||
747 | /* get socket back, check first if in use, maybe by send function */ | ||
748 | spin_lock(&hc->socket_lock); | ||
749 | /* if hc->socket is NULL, it is in use until it is given back */ | ||
750 | while (!hc->socket) { | ||
751 | spin_unlock(&hc->socket_lock); | ||
752 | schedule_timeout(HZ/10); | ||
753 | spin_lock(&hc->socket_lock); | ||
754 | } | ||
755 | hc->socket = NULL; | ||
756 | spin_unlock(&hc->socket_lock); | ||
757 | |||
758 | if (debug & DEBUG_L1OIP_SOCKET) | ||
759 | printk(KERN_DEBUG "%s: socket thread terminating\n", | ||
760 | __func__); | ||
761 | |||
762 | fail: | ||
763 | /* close socket */ | ||
764 | if (socket) | ||
765 | sock_release(socket); | ||
766 | |||
767 | /* if we got killed, signal completion */ | ||
768 | complete(&hc->socket_complete); | ||
769 | hc->socket_thread = NULL; /* show termination of thread */ | ||
770 | |||
771 | if (debug & DEBUG_L1OIP_SOCKET) | ||
772 | printk(KERN_DEBUG "%s: socket thread terminated\n", | ||
773 | __func__); | ||
774 | return ret; | ||
775 | } | ||
776 | |||
777 | static void | ||
778 | l1oip_socket_close(struct l1oip *hc) | ||
779 | { | ||
780 | /* kill thread */ | ||
781 | if (hc->socket_thread) { | ||
782 | if (debug & DEBUG_L1OIP_SOCKET) | ||
783 | printk(KERN_DEBUG "%s: socket thread exists, " | ||
784 | "killing...\n", __func__); | ||
785 | send_sig(SIGTERM, hc->socket_thread, 0); | ||
786 | wait_for_completion(&hc->socket_complete); | ||
787 | } | ||
788 | } | ||
789 | |||
790 | static int | ||
791 | l1oip_socket_open(struct l1oip *hc) | ||
792 | { | ||
793 | /* in case of reopen, we need to close first */ | ||
794 | l1oip_socket_close(hc); | ||
795 | |||
796 | init_completion(&hc->socket_complete); | ||
797 | |||
798 | /* create receive process */ | ||
799 | hc->socket_thread = kthread_run(l1oip_socket_thread, hc, "l1oip_%s", | ||
800 | hc->name); | ||
801 | if (IS_ERR(hc->socket_thread)) { | ||
802 | int err = PTR_ERR(hc->socket_thread); | ||
803 | printk(KERN_ERR "%s: Failed (%d) to create socket process.\n", | ||
804 | __func__, err); | ||
805 | hc->socket_thread = NULL; | ||
806 | sock_release(hc->socket); | ||
807 | return err; | ||
808 | } | ||
809 | if (debug & DEBUG_L1OIP_SOCKET) | ||
810 | printk(KERN_DEBUG "%s: socket thread created\n", __func__); | ||
811 | |||
812 | return 0; | ||
813 | } | ||
814 | |||
815 | |||
816 | static void | ||
817 | l1oip_send_bh(struct work_struct *work) | ||
818 | { | ||
819 | struct l1oip *hc = container_of(work, struct l1oip, workq); | ||
820 | |||
821 | if (debug & (DEBUG_L1OIP_MSG|DEBUG_L1OIP_SOCKET)) | ||
822 | printk(KERN_DEBUG "%s: keepalive timer expired, sending empty " | ||
823 | "frame on dchannel\n", __func__); | ||
824 | |||
825 | /* send an empty l1oip frame at D-channel */ | ||
826 | l1oip_socket_send(hc, 0, hc->d_idx, 0, 0, NULL, 0); | ||
827 | } | ||
828 | |||
829 | |||
830 | /* | ||
831 | * timer stuff | ||
832 | */ | ||
833 | static void | ||
834 | l1oip_keepalive(void *data) | ||
835 | { | ||
836 | struct l1oip *hc = (struct l1oip *)data; | ||
837 | |||
838 | schedule_work(&hc->workq); | ||
839 | } | ||
840 | |||
841 | static void | ||
842 | l1oip_timeout(void *data) | ||
843 | { | ||
844 | struct l1oip *hc = (struct l1oip *)data; | ||
845 | struct dchannel *dch = hc->chan[hc->d_idx].dch; | ||
846 | |||
847 | if (debug & DEBUG_L1OIP_MSG) | ||
848 | printk(KERN_DEBUG "%s: timeout timer expired, turn layer one " | ||
849 | "down.\n", __func__); | ||
850 | |||
851 | hc->timeout_on = 0; /* state that timer must be initialized next time */ | ||
852 | |||
853 | /* if timeout, we send up a PH_DEACTIVATE and deactivate */ | ||
854 | if (test_bit(FLG_ACTIVE, &dch->Flags)) { | ||
855 | if (debug & (DEBUG_L1OIP_MSG|DEBUG_L1OIP_SOCKET)) | ||
856 | printk(KERN_DEBUG "%s: interface become deactivated " | ||
857 | "due to timeout\n", __func__); | ||
858 | test_and_clear_bit(FLG_ACTIVE, &dch->Flags); | ||
859 | _queue_data(&dch->dev.D, PH_DEACTIVATE_IND, MISDN_ID_ANY, 0, | ||
860 | NULL, GFP_ATOMIC); | ||
861 | } | ||
862 | |||
863 | /* if we have ondemand set, we remove ip address */ | ||
864 | if (hc->ondemand) { | ||
865 | if (debug & DEBUG_L1OIP_MSG) | ||
866 | printk(KERN_DEBUG "%s: on demand causes ip address to " | ||
867 | "be removed\n", __func__); | ||
868 | hc->sin_remote.sin_addr.s_addr = 0; | ||
869 | } | ||
870 | } | ||
871 | |||
872 | |||
873 | /* | ||
874 | * message handling | ||
875 | */ | ||
876 | static int | ||
877 | handle_dmsg(struct mISDNchannel *ch, struct sk_buff *skb) | ||
878 | { | ||
879 | struct mISDNdevice *dev = container_of(ch, struct mISDNdevice, D); | ||
880 | struct dchannel *dch = container_of(dev, struct dchannel, dev); | ||
881 | struct l1oip *hc = dch->hw; | ||
882 | struct mISDNhead *hh = mISDN_HEAD_P(skb); | ||
883 | int ret = -EINVAL; | ||
884 | int l, ll; | ||
885 | unsigned char *p; | ||
886 | |||
887 | switch (hh->prim) { | ||
888 | case PH_DATA_REQ: | ||
889 | if (skb->len < 1) { | ||
890 | printk(KERN_WARNING "%s: skb too small\n", | ||
891 | __func__); | ||
892 | break; | ||
893 | } | ||
894 | if (skb->len > MAX_DFRAME_LEN_L1 || skb->len > L1OIP_MAX_LEN) { | ||
895 | printk(KERN_WARNING "%s: skb too large\n", | ||
896 | __func__); | ||
897 | break; | ||
898 | } | ||
899 | /* send frame */ | ||
900 | p = skb->data; | ||
901 | l = skb->len; | ||
902 | while (l) { | ||
903 | ll = (l < L1OIP_MAX_PERFRAME)?l:L1OIP_MAX_PERFRAME; | ||
904 | l1oip_socket_send(hc, 0, dch->slot, 0, | ||
905 | hc->chan[dch->slot].tx_counter++, p, ll); | ||
906 | p += ll; | ||
907 | l -= ll; | ||
908 | } | ||
909 | skb_trim(skb, 0); | ||
910 | queue_ch_frame(ch, PH_DATA_CNF, hh->id, skb); | ||
911 | return 0; | ||
912 | case PH_ACTIVATE_REQ: | ||
913 | if (debug & (DEBUG_L1OIP_MSG|DEBUG_L1OIP_SOCKET)) | ||
914 | printk(KERN_DEBUG "%s: PH_ACTIVATE channel %d (1..%d)\n" | ||
915 | , __func__, dch->slot, hc->b_num+1); | ||
916 | skb_trim(skb, 0); | ||
917 | if (test_bit(FLG_ACTIVE, &dch->Flags)) | ||
918 | queue_ch_frame(ch, PH_ACTIVATE_IND, hh->id, skb); | ||
919 | else | ||
920 | queue_ch_frame(ch, PH_DEACTIVATE_IND, hh->id, skb); | ||
921 | return 0; | ||
922 | case PH_DEACTIVATE_REQ: | ||
923 | if (debug & (DEBUG_L1OIP_MSG|DEBUG_L1OIP_SOCKET)) | ||
924 | printk(KERN_DEBUG "%s: PH_DEACTIVATE channel %d " | ||
925 | "(1..%d)\n", __func__, dch->slot, | ||
926 | hc->b_num+1); | ||
927 | skb_trim(skb, 0); | ||
928 | if (test_bit(FLG_ACTIVE, &dch->Flags)) | ||
929 | queue_ch_frame(ch, PH_ACTIVATE_IND, hh->id, skb); | ||
930 | else | ||
931 | queue_ch_frame(ch, PH_DEACTIVATE_IND, hh->id, skb); | ||
932 | return 0; | ||
933 | } | ||
934 | if (!ret) | ||
935 | dev_kfree_skb(skb); | ||
936 | return ret; | ||
937 | } | ||
938 | |||
939 | static int | ||
940 | channel_dctrl(struct dchannel *dch, struct mISDN_ctrl_req *cq) | ||
941 | { | ||
942 | int ret = 0; | ||
943 | struct l1oip *hc = dch->hw; | ||
944 | |||
945 | switch (cq->op) { | ||
946 | case MISDN_CTRL_GETOP: | ||
947 | cq->op = MISDN_CTRL_SETPEER | MISDN_CTRL_UNSETPEER; | ||
948 | break; | ||
949 | case MISDN_CTRL_SETPEER: | ||
950 | hc->remoteip = (u32)cq->p1; | ||
951 | hc->remoteport = cq->p2 & 0xffff; | ||
952 | hc->localport = cq->p2 >> 16; | ||
953 | if (!hc->remoteport) | ||
954 | hc->remoteport = hc->localport; | ||
955 | if (debug & DEBUG_L1OIP_SOCKET) | ||
956 | printk(KERN_DEBUG "%s: got new ip address from user " | ||
957 | "space.\n", __func__); | ||
958 | l1oip_socket_open(hc); | ||
959 | break; | ||
960 | case MISDN_CTRL_UNSETPEER: | ||
961 | if (debug & DEBUG_L1OIP_SOCKET) | ||
962 | printk(KERN_DEBUG "%s: removing ip address.\n", | ||
963 | __func__); | ||
964 | hc->remoteip = 0; | ||
965 | l1oip_socket_open(hc); | ||
966 | break; | ||
967 | default: | ||
968 | printk(KERN_WARNING "%s: unknown Op %x\n", | ||
969 | __func__, cq->op); | ||
970 | ret = -EINVAL; | ||
971 | break; | ||
972 | } | ||
973 | return ret; | ||
974 | } | ||
975 | |||
976 | static int | ||
977 | open_dchannel(struct l1oip *hc, struct dchannel *dch, struct channel_req *rq) | ||
978 | { | ||
979 | if (debug & DEBUG_HW_OPEN) | ||
980 | printk(KERN_DEBUG "%s: dev(%d) open from %p\n", __func__, | ||
981 | dch->dev.id, __builtin_return_address(0)); | ||
982 | if (rq->protocol == ISDN_P_NONE) | ||
983 | return -EINVAL; | ||
984 | if ((dch->dev.D.protocol != ISDN_P_NONE) && | ||
985 | (dch->dev.D.protocol != rq->protocol)) { | ||
986 | if (debug & DEBUG_HW_OPEN) | ||
987 | printk(KERN_WARNING "%s: change protocol %x to %x\n", | ||
988 | __func__, dch->dev.D.protocol, rq->protocol); | ||
989 | } | ||
990 | if (dch->dev.D.protocol != rq->protocol) | ||
991 | dch->dev.D.protocol = rq->protocol; | ||
992 | |||
993 | if (test_bit(FLG_ACTIVE, &dch->Flags)) { | ||
994 | _queue_data(&dch->dev.D, PH_ACTIVATE_IND, MISDN_ID_ANY, | ||
995 | 0, NULL, GFP_KERNEL); | ||
996 | } | ||
997 | rq->ch = &dch->dev.D; | ||
998 | if (!try_module_get(THIS_MODULE)) | ||
999 | printk(KERN_WARNING "%s:cannot get module\n", __func__); | ||
1000 | return 0; | ||
1001 | } | ||
1002 | |||
1003 | static int | ||
1004 | open_bchannel(struct l1oip *hc, struct dchannel *dch, struct channel_req *rq) | ||
1005 | { | ||
1006 | struct bchannel *bch; | ||
1007 | int ch; | ||
1008 | |||
1009 | if (!test_bit(rq->adr.channel & 0x1f, | ||
1010 | &dch->dev.channelmap[rq->adr.channel >> 5])) | ||
1011 | return -EINVAL; | ||
1012 | if (rq->protocol == ISDN_P_NONE) | ||
1013 | return -EINVAL; | ||
1014 | ch = rq->adr.channel; /* BRI: 1=B1 2=B2 PRI: 1..15,17.. */ | ||
1015 | bch = hc->chan[ch].bch; | ||
1016 | if (!bch) { | ||
1017 | printk(KERN_ERR "%s:internal error ch %d has no bch\n", | ||
1018 | __func__, ch); | ||
1019 | return -EINVAL; | ||
1020 | } | ||
1021 | if (test_and_set_bit(FLG_OPEN, &bch->Flags)) | ||
1022 | return -EBUSY; /* b-channel can be only open once */ | ||
1023 | bch->ch.protocol = rq->protocol; | ||
1024 | rq->ch = &bch->ch; | ||
1025 | if (!try_module_get(THIS_MODULE)) | ||
1026 | printk(KERN_WARNING "%s:cannot get module\n", __func__); | ||
1027 | return 0; | ||
1028 | } | ||
1029 | |||
1030 | static int | ||
1031 | l1oip_dctrl(struct mISDNchannel *ch, u_int cmd, void *arg) | ||
1032 | { | ||
1033 | struct mISDNdevice *dev = container_of(ch, struct mISDNdevice, D); | ||
1034 | struct dchannel *dch = container_of(dev, struct dchannel, dev); | ||
1035 | struct l1oip *hc = dch->hw; | ||
1036 | struct channel_req *rq; | ||
1037 | int err = 0; | ||
1038 | |||
1039 | if (dch->debug & DEBUG_HW) | ||
1040 | printk(KERN_DEBUG "%s: cmd:%x %p\n", | ||
1041 | __func__, cmd, arg); | ||
1042 | switch (cmd) { | ||
1043 | case OPEN_CHANNEL: | ||
1044 | rq = arg; | ||
1045 | switch (rq->protocol) { | ||
1046 | case ISDN_P_TE_S0: | ||
1047 | case ISDN_P_NT_S0: | ||
1048 | if (hc->pri) { | ||
1049 | err = -EINVAL; | ||
1050 | break; | ||
1051 | } | ||
1052 | err = open_dchannel(hc, dch, rq); | ||
1053 | break; | ||
1054 | case ISDN_P_TE_E1: | ||
1055 | case ISDN_P_NT_E1: | ||
1056 | if (!hc->pri) { | ||
1057 | err = -EINVAL; | ||
1058 | break; | ||
1059 | } | ||
1060 | err = open_dchannel(hc, dch, rq); | ||
1061 | break; | ||
1062 | default: | ||
1063 | err = open_bchannel(hc, dch, rq); | ||
1064 | } | ||
1065 | break; | ||
1066 | case CLOSE_CHANNEL: | ||
1067 | if (debug & DEBUG_HW_OPEN) | ||
1068 | printk(KERN_DEBUG "%s: dev(%d) close from %p\n", | ||
1069 | __func__, dch->dev.id, | ||
1070 | __builtin_return_address(0)); | ||
1071 | module_put(THIS_MODULE); | ||
1072 | break; | ||
1073 | case CONTROL_CHANNEL: | ||
1074 | err = channel_dctrl(dch, arg); | ||
1075 | break; | ||
1076 | default: | ||
1077 | if (dch->debug & DEBUG_HW) | ||
1078 | printk(KERN_DEBUG "%s: unknown command %x\n", | ||
1079 | __func__, cmd); | ||
1080 | err = -EINVAL; | ||
1081 | } | ||
1082 | return err; | ||
1083 | } | ||
1084 | |||
1085 | static int | ||
1086 | handle_bmsg(struct mISDNchannel *ch, struct sk_buff *skb) | ||
1087 | { | ||
1088 | struct bchannel *bch = container_of(ch, struct bchannel, ch); | ||
1089 | struct l1oip *hc = bch->hw; | ||
1090 | int ret = -EINVAL; | ||
1091 | struct mISDNhead *hh = mISDN_HEAD_P(skb); | ||
1092 | int l, ll, i; | ||
1093 | unsigned char *p; | ||
1094 | |||
1095 | switch (hh->prim) { | ||
1096 | case PH_DATA_REQ: | ||
1097 | if (skb->len <= 0) { | ||
1098 | printk(KERN_WARNING "%s: skb too small\n", | ||
1099 | __func__); | ||
1100 | break; | ||
1101 | } | ||
1102 | if (skb->len > MAX_DFRAME_LEN_L1 || skb->len > L1OIP_MAX_LEN) { | ||
1103 | printk(KERN_WARNING "%s: skb too large\n", | ||
1104 | __func__); | ||
1105 | break; | ||
1106 | } | ||
1107 | /* check for AIS / ulaw-silence */ | ||
1108 | p = skb->data; | ||
1109 | l = skb->len; | ||
1110 | for (i = 0; i < l; i++) { | ||
1111 | if (*p++ != 0xff) | ||
1112 | break; | ||
1113 | } | ||
1114 | if (i == l) { | ||
1115 | if (debug & DEBUG_L1OIP_MSG) | ||
1116 | printk(KERN_DEBUG "%s: got AIS, not sending, " | ||
1117 | "but counting\n", __func__); | ||
1118 | hc->chan[bch->slot].tx_counter += l; | ||
1119 | skb_trim(skb, 0); | ||
1120 | queue_ch_frame(ch, PH_DATA_CNF, hh->id, skb); | ||
1121 | return 0; | ||
1122 | } | ||
1123 | /* check for silence */ | ||
1124 | p = skb->data; | ||
1125 | l = skb->len; | ||
1126 | for (i = 0; i < l; i++) { | ||
1127 | if (*p++ != 0x2a) | ||
1128 | break; | ||
1129 | } | ||
1130 | if (i == l) { | ||
1131 | if (debug & DEBUG_L1OIP_MSG) | ||
1132 | printk(KERN_DEBUG "%s: got silence, not sending" | ||
1133 | ", but counting\n", __func__); | ||
1134 | hc->chan[bch->slot].tx_counter += l; | ||
1135 | skb_trim(skb, 0); | ||
1136 | queue_ch_frame(ch, PH_DATA_CNF, hh->id, skb); | ||
1137 | return 0; | ||
1138 | } | ||
1139 | |||
1140 | /* send frame */ | ||
1141 | p = skb->data; | ||
1142 | l = skb->len; | ||
1143 | while (l) { | ||
1144 | ll = (l < L1OIP_MAX_PERFRAME)?l:L1OIP_MAX_PERFRAME; | ||
1145 | l1oip_socket_send(hc, hc->codec, bch->slot, 0, | ||
1146 | hc->chan[bch->slot].tx_counter, p, ll); | ||
1147 | hc->chan[bch->slot].tx_counter += ll; | ||
1148 | p += ll; | ||
1149 | l -= ll; | ||
1150 | } | ||
1151 | skb_trim(skb, 0); | ||
1152 | queue_ch_frame(ch, PH_DATA_CNF, hh->id, skb); | ||
1153 | return 0; | ||
1154 | case PH_ACTIVATE_REQ: | ||
1155 | if (debug & (DEBUG_L1OIP_MSG|DEBUG_L1OIP_SOCKET)) | ||
1156 | printk(KERN_DEBUG "%s: PH_ACTIVATE channel %d (1..%d)\n" | ||
1157 | , __func__, bch->slot, hc->b_num+1); | ||
1158 | hc->chan[bch->slot].codecstate = 0; | ||
1159 | test_and_set_bit(FLG_ACTIVE, &bch->Flags); | ||
1160 | skb_trim(skb, 0); | ||
1161 | queue_ch_frame(ch, PH_ACTIVATE_IND, hh->id, skb); | ||
1162 | return 0; | ||
1163 | case PH_DEACTIVATE_REQ: | ||
1164 | if (debug & (DEBUG_L1OIP_MSG|DEBUG_L1OIP_SOCKET)) | ||
1165 | printk(KERN_DEBUG "%s: PH_DEACTIVATE channel %d " | ||
1166 | "(1..%d)\n", __func__, bch->slot, | ||
1167 | hc->b_num+1); | ||
1168 | test_and_clear_bit(FLG_ACTIVE, &bch->Flags); | ||
1169 | skb_trim(skb, 0); | ||
1170 | queue_ch_frame(ch, PH_DEACTIVATE_IND, hh->id, skb); | ||
1171 | return 0; | ||
1172 | } | ||
1173 | if (!ret) | ||
1174 | dev_kfree_skb(skb); | ||
1175 | return ret; | ||
1176 | } | ||
1177 | |||
1178 | static int | ||
1179 | channel_bctrl(struct bchannel *bch, struct mISDN_ctrl_req *cq) | ||
1180 | { | ||
1181 | int ret = 0; | ||
1182 | struct dsp_features *features = | ||
1183 | (struct dsp_features *)(*((u_long *)&cq->p1)); | ||
1184 | |||
1185 | switch (cq->op) { | ||
1186 | case MISDN_CTRL_GETOP: | ||
1187 | cq->op = MISDN_CTRL_HW_FEATURES_OP; | ||
1188 | break; | ||
1189 | case MISDN_CTRL_HW_FEATURES: /* fill features structure */ | ||
1190 | if (debug & DEBUG_L1OIP_MSG) | ||
1191 | printk(KERN_DEBUG "%s: HW_FEATURE request\n", | ||
1192 | __func__); | ||
1193 | /* create confirm */ | ||
1194 | features->unclocked = 1; | ||
1195 | features->unordered = 1; | ||
1196 | break; | ||
1197 | default: | ||
1198 | printk(KERN_WARNING "%s: unknown Op %x\n", | ||
1199 | __func__, cq->op); | ||
1200 | ret = -EINVAL; | ||
1201 | break; | ||
1202 | } | ||
1203 | return ret; | ||
1204 | } | ||
1205 | |||
1206 | static int | ||
1207 | l1oip_bctrl(struct mISDNchannel *ch, u_int cmd, void *arg) | ||
1208 | { | ||
1209 | struct bchannel *bch = container_of(ch, struct bchannel, ch); | ||
1210 | int err = -EINVAL; | ||
1211 | |||
1212 | if (bch->debug & DEBUG_HW) | ||
1213 | printk(KERN_DEBUG "%s: cmd:%x %p\n", | ||
1214 | __func__, cmd, arg); | ||
1215 | switch (cmd) { | ||
1216 | case CLOSE_CHANNEL: | ||
1217 | test_and_clear_bit(FLG_OPEN, &bch->Flags); | ||
1218 | test_and_clear_bit(FLG_ACTIVE, &bch->Flags); | ||
1219 | ch->protocol = ISDN_P_NONE; | ||
1220 | ch->peer = NULL; | ||
1221 | module_put(THIS_MODULE); | ||
1222 | err = 0; | ||
1223 | break; | ||
1224 | case CONTROL_CHANNEL: | ||
1225 | err = channel_bctrl(bch, arg); | ||
1226 | break; | ||
1227 | default: | ||
1228 | printk(KERN_WARNING "%s: unknown prim(%x)\n", | ||
1229 | __func__, cmd); | ||
1230 | } | ||
1231 | return err; | ||
1232 | } | ||
1233 | |||
1234 | |||
1235 | /* | ||
1236 | * cleanup module and stack | ||
1237 | */ | ||
1238 | static void | ||
1239 | release_card(struct l1oip *hc) | ||
1240 | { | ||
1241 | int ch; | ||
1242 | |||
1243 | if (timer_pending(&hc->keep_tl)) | ||
1244 | del_timer(&hc->keep_tl); | ||
1245 | |||
1246 | if (timer_pending(&hc->timeout_tl)) | ||
1247 | del_timer(&hc->timeout_tl); | ||
1248 | |||
1249 | if (hc->socket_thread) | ||
1250 | l1oip_socket_close(hc); | ||
1251 | |||
1252 | if (hc->registered && hc->chan[hc->d_idx].dch) | ||
1253 | mISDN_unregister_device(&hc->chan[hc->d_idx].dch->dev); | ||
1254 | for (ch = 0; ch < 128; ch++) { | ||
1255 | if (hc->chan[ch].dch) { | ||
1256 | mISDN_freedchannel(hc->chan[ch].dch); | ||
1257 | kfree(hc->chan[ch].dch); | ||
1258 | } | ||
1259 | if (hc->chan[ch].bch) { | ||
1260 | mISDN_freebchannel(hc->chan[ch].bch); | ||
1261 | kfree(hc->chan[ch].bch); | ||
1262 | #ifdef REORDER_DEBUG | ||
1263 | if (hc->chan[ch].disorder_skb) | ||
1264 | dev_kfree_skb(hc->chan[ch].disorder_skb); | ||
1265 | #endif | ||
1266 | } | ||
1267 | } | ||
1268 | |||
1269 | spin_lock(&l1oip_lock); | ||
1270 | list_del(&hc->list); | ||
1271 | spin_unlock(&l1oip_lock); | ||
1272 | |||
1273 | kfree(hc); | ||
1274 | } | ||
1275 | |||
1276 | static void | ||
1277 | l1oip_cleanup(void) | ||
1278 | { | ||
1279 | struct l1oip *hc, *next; | ||
1280 | |||
1281 | list_for_each_entry_safe(hc, next, &l1oip_ilist, list) | ||
1282 | release_card(hc); | ||
1283 | |||
1284 | l1oip_4bit_free(); | ||
1285 | } | ||
1286 | |||
1287 | |||
1288 | /* | ||
1289 | * module and stack init | ||
1290 | */ | ||
1291 | static int | ||
1292 | init_card(struct l1oip *hc, int pri, int bundle) | ||
1293 | { | ||
1294 | struct dchannel *dch; | ||
1295 | struct bchannel *bch; | ||
1296 | int ret; | ||
1297 | int i, ch; | ||
1298 | |||
1299 | spin_lock_init(&hc->socket_lock); | ||
1300 | hc->idx = l1oip_cnt; | ||
1301 | hc->pri = pri; | ||
1302 | hc->d_idx = pri?16:3; | ||
1303 | hc->b_num = pri?30:2; | ||
1304 | hc->bundle = bundle; | ||
1305 | if (hc->pri) | ||
1306 | sprintf(hc->name, "l1oip-e1.%d", l1oip_cnt + 1); | ||
1307 | else | ||
1308 | sprintf(hc->name, "l1oip-s0.%d", l1oip_cnt + 1); | ||
1309 | |||
1310 | switch (codec[l1oip_cnt]) { | ||
1311 | case 0: /* as is */ | ||
1312 | case 1: /* alaw */ | ||
1313 | case 2: /* ulaw */ | ||
1314 | case 3: /* 4bit */ | ||
1315 | break; | ||
1316 | default: | ||
1317 | printk(KERN_ERR "Codec(%d) not supported.\n", | ||
1318 | codec[l1oip_cnt]); | ||
1319 | return -EINVAL; | ||
1320 | } | ||
1321 | hc->codec = codec[l1oip_cnt]; | ||
1322 | if (debug & DEBUG_L1OIP_INIT) | ||
1323 | printk(KERN_DEBUG "%s: using codec %d\n", | ||
1324 | __func__, hc->codec); | ||
1325 | |||
1326 | if (id[l1oip_cnt] == 0) { | ||
1327 | printk(KERN_WARNING "Warning: No 'id' value given or " | ||
1328 | "0, this is highly unsecure. Please use 32 " | ||
1329 | "bit randmom number 0x...\n"); | ||
1330 | } | ||
1331 | hc->id = id[l1oip_cnt]; | ||
1332 | if (debug & DEBUG_L1OIP_INIT) | ||
1333 | printk(KERN_DEBUG "%s: using id 0x%x\n", __func__, hc->id); | ||
1334 | |||
1335 | hc->ondemand = ondemand[l1oip_cnt]; | ||
1336 | if (hc->ondemand && !hc->id) { | ||
1337 | printk(KERN_ERR "%s: ondemand option only allowed in " | ||
1338 | "conjunction with non 0 ID\n", __func__); | ||
1339 | return -EINVAL; | ||
1340 | } | ||
1341 | |||
1342 | if (limit[l1oip_cnt]) | ||
1343 | hc->b_num = limit[l1oip_cnt]; | ||
1344 | if (!pri && hc->b_num > 2) { | ||
1345 | printk(KERN_ERR "Maximum limit for BRI interface is 2 " | ||
1346 | "channels.\n"); | ||
1347 | return -EINVAL; | ||
1348 | } | ||
1349 | if (pri && hc->b_num > 126) { | ||
1350 | printk(KERN_ERR "Maximum limit for PRI interface is 126 " | ||
1351 | "channels.\n"); | ||
1352 | return -EINVAL; | ||
1353 | } | ||
1354 | if (pri && hc->b_num > 30) { | ||
1355 | printk(KERN_WARNING "Maximum limit for BRI interface is 30 " | ||
1356 | "channels.\n"); | ||
1357 | printk(KERN_WARNING "Your selection of %d channels must be " | ||
1358 | "supported by application.\n", hc->limit); | ||
1359 | } | ||
1360 | |||
1361 | hc->remoteip = ip[l1oip_cnt<<2] << 24 | ||
1362 | | ip[(l1oip_cnt<<2)+1] << 16 | ||
1363 | | ip[(l1oip_cnt<<2)+2] << 8 | ||
1364 | | ip[(l1oip_cnt<<2)+3]; | ||
1365 | hc->localport = port[l1oip_cnt]?:(L1OIP_DEFAULTPORT+l1oip_cnt); | ||
1366 | if (remoteport[l1oip_cnt]) | ||
1367 | hc->remoteport = remoteport[l1oip_cnt]; | ||
1368 | else | ||
1369 | hc->remoteport = hc->localport; | ||
1370 | if (debug & DEBUG_L1OIP_INIT) | ||
1371 | printk(KERN_DEBUG "%s: using local port %d remote ip " | ||
1372 | "%d.%d.%d.%d port %d ondemand %d\n", __func__, | ||
1373 | hc->localport, hc->remoteip >> 24, | ||
1374 | (hc->remoteip >> 16) & 0xff, | ||
1375 | (hc->remoteip >> 8) & 0xff, hc->remoteip & 0xff, | ||
1376 | hc->remoteport, hc->ondemand); | ||
1377 | |||
1378 | dch = kzalloc(sizeof(struct dchannel), GFP_KERNEL); | ||
1379 | if (!dch) | ||
1380 | return -ENOMEM; | ||
1381 | dch->debug = debug; | ||
1382 | mISDN_initdchannel(dch, MAX_DFRAME_LEN_L1, NULL); | ||
1383 | dch->hw = hc; | ||
1384 | if (pri) | ||
1385 | dch->dev.Dprotocols = (1 << ISDN_P_TE_E1) | (1 << ISDN_P_NT_E1); | ||
1386 | else | ||
1387 | dch->dev.Dprotocols = (1 << ISDN_P_TE_S0) | (1 << ISDN_P_NT_S0); | ||
1388 | dch->dev.Bprotocols = (1 << (ISDN_P_B_RAW & ISDN_P_B_MASK)) | | ||
1389 | (1 << (ISDN_P_B_HDLC & ISDN_P_B_MASK)); | ||
1390 | dch->dev.D.send = handle_dmsg; | ||
1391 | dch->dev.D.ctrl = l1oip_dctrl; | ||
1392 | dch->dev.nrbchan = hc->b_num; | ||
1393 | dch->slot = hc->d_idx; | ||
1394 | hc->chan[hc->d_idx].dch = dch; | ||
1395 | i = 1; | ||
1396 | for (ch = 0; ch < dch->dev.nrbchan; ch++) { | ||
1397 | if (ch == 15) | ||
1398 | i++; | ||
1399 | bch = kzalloc(sizeof(struct bchannel), GFP_KERNEL); | ||
1400 | if (!bch) { | ||
1401 | printk(KERN_ERR "%s: no memory for bchannel\n", | ||
1402 | __func__); | ||
1403 | return -ENOMEM; | ||
1404 | } | ||
1405 | bch->nr = i + ch; | ||
1406 | bch->slot = i + ch; | ||
1407 | bch->debug = debug; | ||
1408 | mISDN_initbchannel(bch, MAX_DATA_MEM); | ||
1409 | bch->hw = hc; | ||
1410 | bch->ch.send = handle_bmsg; | ||
1411 | bch->ch.ctrl = l1oip_bctrl; | ||
1412 | bch->ch.nr = i + ch; | ||
1413 | list_add(&bch->ch.list, &dch->dev.bchannels); | ||
1414 | hc->chan[i + ch].bch = bch; | ||
1415 | test_and_set_bit(bch->nr & 0x1f, | ||
1416 | &dch->dev.channelmap[bch->nr >> 5]); | ||
1417 | } | ||
1418 | ret = mISDN_register_device(&dch->dev, hc->name); | ||
1419 | if (ret) | ||
1420 | return ret; | ||
1421 | hc->registered = 1; | ||
1422 | |||
1423 | if (debug & DEBUG_L1OIP_INIT) | ||
1424 | printk(KERN_DEBUG "%s: Setting up network card(%d)\n", | ||
1425 | __func__, l1oip_cnt + 1); | ||
1426 | ret = l1oip_socket_open(hc); | ||
1427 | if (ret) | ||
1428 | return ret; | ||
1429 | |||
1430 | hc->keep_tl.function = (void *)l1oip_keepalive; | ||
1431 | hc->keep_tl.data = (ulong)hc; | ||
1432 | init_timer(&hc->keep_tl); | ||
1433 | hc->keep_tl.expires = jiffies + 2*HZ; /* two seconds first time */ | ||
1434 | add_timer(&hc->keep_tl); | ||
1435 | |||
1436 | hc->timeout_tl.function = (void *)l1oip_timeout; | ||
1437 | hc->timeout_tl.data = (ulong)hc; | ||
1438 | init_timer(&hc->timeout_tl); | ||
1439 | hc->timeout_on = 0; /* state that we have timer off */ | ||
1440 | |||
1441 | return 0; | ||
1442 | } | ||
1443 | |||
1444 | static int __init | ||
1445 | l1oip_init(void) | ||
1446 | { | ||
1447 | int pri, bundle; | ||
1448 | struct l1oip *hc; | ||
1449 | int ret; | ||
1450 | |||
1451 | printk(KERN_INFO "mISDN: Layer-1-over-IP driver Rev. %s\n", | ||
1452 | l1oip_revision); | ||
1453 | |||
1454 | INIT_LIST_HEAD(&l1oip_ilist); | ||
1455 | spin_lock_init(&l1oip_lock); | ||
1456 | |||
1457 | if (l1oip_4bit_alloc(ulaw)) | ||
1458 | return -ENOMEM; | ||
1459 | |||
1460 | l1oip_cnt = 0; | ||
1461 | while (type[l1oip_cnt] && l1oip_cnt < MAX_CARDS) { | ||
1462 | switch (type[l1oip_cnt] & 0xff) { | ||
1463 | case 1: | ||
1464 | pri = 0; | ||
1465 | bundle = 0; | ||
1466 | break; | ||
1467 | case 2: | ||
1468 | pri = 1; | ||
1469 | bundle = 0; | ||
1470 | break; | ||
1471 | case 3: | ||
1472 | pri = 0; | ||
1473 | bundle = 1; | ||
1474 | break; | ||
1475 | case 4: | ||
1476 | pri = 1; | ||
1477 | bundle = 1; | ||
1478 | break; | ||
1479 | default: | ||
1480 | printk(KERN_ERR "Card type(%d) not supported.\n", | ||
1481 | type[l1oip_cnt] & 0xff); | ||
1482 | l1oip_cleanup(); | ||
1483 | return -EINVAL; | ||
1484 | } | ||
1485 | |||
1486 | if (debug & DEBUG_L1OIP_INIT) | ||
1487 | printk(KERN_DEBUG "%s: interface %d is %s with %s.\n", | ||
1488 | __func__, l1oip_cnt, pri?"PRI":"BRI", | ||
1489 | bundle?"bundled IP packet for all B-channels" | ||
1490 | :"seperate IP packets for every B-channel"); | ||
1491 | |||
1492 | hc = kzalloc(sizeof(struct l1oip), GFP_ATOMIC); | ||
1493 | if (!hc) { | ||
1494 | printk(KERN_ERR "No kmem for L1-over-IP driver.\n"); | ||
1495 | l1oip_cleanup(); | ||
1496 | return -ENOMEM; | ||
1497 | } | ||
1498 | INIT_WORK(&hc->workq, (void *)l1oip_send_bh); | ||
1499 | |||
1500 | spin_lock(&l1oip_lock); | ||
1501 | list_add_tail(&hc->list, &l1oip_ilist); | ||
1502 | spin_unlock(&l1oip_lock); | ||
1503 | |||
1504 | ret = init_card(hc, pri, bundle); | ||
1505 | if (ret) { | ||
1506 | l1oip_cleanup(); | ||
1507 | return ret; | ||
1508 | } | ||
1509 | |||
1510 | l1oip_cnt++; | ||
1511 | } | ||
1512 | printk(KERN_INFO "%d virtual devices registered\n", l1oip_cnt); | ||
1513 | return 0; | ||
1514 | } | ||
1515 | |||
1516 | module_init(l1oip_init); | ||
1517 | module_exit(l1oip_cleanup); | ||
1518 | |||