aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/isdn/i4l
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/isdn/i4l
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'drivers/isdn/i4l')
-rw-r--r--drivers/isdn/i4l/Kconfig141
-rw-r--r--drivers/isdn/i4l/Makefile18
-rw-r--r--drivers/isdn/i4l/isdn_audio.c720
-rw-r--r--drivers/isdn/i4l/isdn_audio.h45
-rw-r--r--drivers/isdn/i4l/isdn_bsdcomp.c937
-rw-r--r--drivers/isdn/i4l/isdn_common.c2253
-rw-r--r--drivers/isdn/i4l/isdn_common.h47
-rw-r--r--drivers/isdn/i4l/isdn_concap.c108
-rw-r--r--drivers/isdn/i4l/isdn_concap.h14
-rw-r--r--drivers/isdn/i4l/isdn_net.c3222
-rw-r--r--drivers/isdn/i4l/isdn_net.h190
-rw-r--r--drivers/isdn/i4l/isdn_ppp.c3020
-rw-r--r--drivers/isdn/i4l/isdn_ppp.h43
-rw-r--r--drivers/isdn/i4l/isdn_tty.c3911
-rw-r--r--drivers/isdn/i4l/isdn_tty.h122
-rw-r--r--drivers/isdn/i4l/isdn_ttyfax.c1122
-rw-r--r--drivers/isdn/i4l/isdn_ttyfax.h18
-rw-r--r--drivers/isdn/i4l/isdn_v110.c617
-rw-r--r--drivers/isdn/i4l/isdn_v110.h29
-rw-r--r--drivers/isdn/i4l/isdn_x25iface.c328
-rw-r--r--drivers/isdn/i4l/isdn_x25iface.h39
21 files changed, 16944 insertions, 0 deletions
diff --git a/drivers/isdn/i4l/Kconfig b/drivers/isdn/i4l/Kconfig
new file mode 100644
index 000000000000..1789b607f090
--- /dev/null
+++ b/drivers/isdn/i4l/Kconfig
@@ -0,0 +1,141 @@
1#
2# Old ISDN4Linux config
3#
4
5config ISDN_PPP
6 bool "Support synchronous PPP"
7 depends on INET
8 help
9 Over digital connections such as ISDN, there is no need to
10 synchronize sender and recipient's clocks with start and stop bits
11 as is done over analog telephone lines. Instead, one can use
12 "synchronous PPP". Saying Y here will include this protocol. This
13 protocol is used by Cisco and Sun for example. So you want to say Y
14 here if the other end of your ISDN connection supports it. You will
15 need a special version of pppd (called ipppd) for using this
16 feature. See <file:Documentation/isdn/README.syncppp> and
17 <file:Documentation/isdn/syncPPP.FAQ> for more information.
18
19config ISDN_PPP_VJ
20 bool "Use VJ-compression with synchronous PPP"
21 depends on ISDN_PPP
22 help
23 This enables Van Jacobson header compression for synchronous PPP.
24 Say Y if the other end of the connection supports it.
25
26config ISDN_MPP
27 bool "Support generic MP (RFC 1717)"
28 depends on ISDN_PPP
29 help
30 With synchronous PPP enabled, it is possible to increase throughput
31 by bundling several ISDN-connections, using this protocol. See
32 <file:Documentation/isdn/README.syncppp> for more information.
33
34config IPPP_FILTER
35 bool "Filtering for synchronous PPP"
36 depends on ISDN_PPP
37 help
38 Say Y here if you want to be able to filter the packets passing over
39 IPPP interfaces. This allows you to control which packets count as
40 activity (i.e. which packets will reset the idle timer or bring up
41 a demand-dialled link) and which packets are to be dropped entirely.
42 You need to say Y here if you wish to use the pass-filter and
43 active-filter options to ipppd.
44
45config ISDN_PPP_BSDCOMP
46 tristate "Support BSD compression"
47 depends on ISDN_PPP
48 help
49 Support for the BSD-Compress compression method for PPP, which uses
50 the LZW compression method to compress each PPP packet before it is
51 sent over the wire. The machine at the other end of the PPP link
52 (usually your ISP) has to support the BSD-Compress compression
53 method as well for this to be useful. Even if they don't support it,
54 it is safe to say Y here.
55
56config ISDN_AUDIO
57 bool "Support audio via ISDN"
58 help
59 If you say Y here, the modem-emulator will support a subset of the
60 EIA Class 8 Voice commands. Using a getty with voice-support
61 (mgetty+sendfax by <gert@greenie.muc.de> with an extension, available
62 with the ISDN utility package for example), you will be able to use
63 your Linux box as an ISDN-answering machine. Of course, this must be
64 supported by the lowlevel driver also. Currently, the HiSax driver
65 is the only voice-supporting driver. See
66 <file:Documentation/isdn/README.audio> for more information.
67
68config ISDN_TTY_FAX
69 bool "Support AT-Fax Class 1 and 2 commands"
70 depends on ISDN_AUDIO
71 help
72 If you say Y here, the modem-emulator will support a subset of the
73 Fax Class 1 and 2 commands. Using a getty with fax-support
74 (mgetty+sendfax, hylafax), you will be able to use your Linux box as
75 an ISDN-fax-machine. This must be supported by the lowlevel driver
76 also. See <file:Documentation/isdn/README.fax> for more information.
77
78config ISDN_X25
79 bool "X.25 PLP on top of ISDN"
80 depends on X25
81 help
82 This feature provides the X.25 protocol over ISDN connections.
83 See <file:Documentation/isdn/README.x25> for more information
84 if you are thinking about using this.
85
86
87menu "ISDN feature submodules"
88 depends on ISDN
89
90config ISDN_DRV_LOOP
91 tristate "isdnloop support"
92 depends on BROKEN_ON_SMP
93 help
94 This driver provides a virtual ISDN card. Its primary purpose is
95 testing of linklevel features or configuration without getting
96 charged by your service-provider for lots of phone calls.
97 You need will need the loopctrl utility from the latest isdn4k-utils
98 package to set up this driver.
99
100config ISDN_DIVERSION
101 tristate "Support isdn diversion services"
102 depends on ISDN && ISDN_I4L
103 help
104 This option allows you to use some supplementary diversion
105 services in conjunction with the HiSax driver on an EURO/DSS1
106 line.
107
108 Supported options are CD (call deflection), CFU (Call forward
109 unconditional), CFB (Call forward when busy) and CFNR (call forward
110 not reachable). Additionally the actual CFU, CFB and CFNR state may
111 be interrogated.
112
113 The use of CFU, CFB, CFNR and interrogation may be limited to some
114 countries. The keypad protocol is still not implemented. CD should
115 work in all countries if the service has been subscribed to.
116
117 Please read the file <file:Documentation/isdn/README.diversion>.
118
119endmenu
120
121comment "ISDN4Linux hardware drivers"
122 depends on NET && ISDN && ISDN_I4L
123
124source "drivers/isdn/hisax/Kconfig"
125
126
127menu "Active cards"
128 depends on NET && ISDN && ISDN_I4L!=n
129
130source "drivers/isdn/icn/Kconfig"
131
132source "drivers/isdn/pcbit/Kconfig"
133
134source "drivers/isdn/sc/Kconfig"
135
136source "drivers/isdn/act2000/Kconfig"
137
138source "drivers/isdn/hysdn/Kconfig"
139
140endmenu
141
diff --git a/drivers/isdn/i4l/Makefile b/drivers/isdn/i4l/Makefile
new file mode 100644
index 000000000000..49a06c0005dd
--- /dev/null
+++ b/drivers/isdn/i4l/Makefile
@@ -0,0 +1,18 @@
1# Makefile for the kernel ISDN subsystem and device drivers.
2
3# Each configuration option enables a list of files.
4
5obj-$(CONFIG_ISDN_I4L) += isdn.o
6obj-$(CONFIG_ISDN_PPP_BSDCOMP) += isdn_bsdcomp.o
7
8# Multipart objects.
9
10isdn-y := isdn_net.o isdn_tty.o isdn_v110.o isdn_common.o
11
12# Optional parts of multipart objects.
13
14isdn-$(CONFIG_ISDN_PPP) += isdn_ppp.o
15isdn-$(CONFIG_ISDN_X25) += isdn_concap.o isdn_x25iface.o
16isdn-$(CONFIG_ISDN_AUDIO) += isdn_audio.o
17isdn-$(CONFIG_ISDN_TTY_FAX) += isdn_ttyfax.o
18
diff --git a/drivers/isdn/i4l/isdn_audio.c b/drivers/isdn/i4l/isdn_audio.c
new file mode 100644
index 000000000000..5350836a4f98
--- /dev/null
+++ b/drivers/isdn/i4l/isdn_audio.c
@@ -0,0 +1,720 @@
1/* $Id: isdn_audio.c,v 1.1.2.2 2004/01/12 22:37:18 keil Exp $
2 *
3 * Linux ISDN subsystem, audio conversion and compression (linklevel).
4 *
5 * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de)
6 * DTMF code (c) 1996 by Christian Mock (cm@kukuruz.ping.at)
7 * Silence detection (c) 1998 by Armin Schindler (mac@gismo.telekom.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.
11 *
12 */
13
14#include <linux/isdn.h>
15#include "isdn_audio.h"
16#include "isdn_common.h"
17
18char *isdn_audio_revision = "$Revision: 1.1.2.2 $";
19
20/*
21 * Misc. lookup-tables.
22 */
23
24/* ulaw -> signed 16-bit */
25static short isdn_audio_ulaw_to_s16[] =
26{
27 0x8284, 0x8684, 0x8a84, 0x8e84, 0x9284, 0x9684, 0x9a84, 0x9e84,
28 0xa284, 0xa684, 0xaa84, 0xae84, 0xb284, 0xb684, 0xba84, 0xbe84,
29 0xc184, 0xc384, 0xc584, 0xc784, 0xc984, 0xcb84, 0xcd84, 0xcf84,
30 0xd184, 0xd384, 0xd584, 0xd784, 0xd984, 0xdb84, 0xdd84, 0xdf84,
31 0xe104, 0xe204, 0xe304, 0xe404, 0xe504, 0xe604, 0xe704, 0xe804,
32 0xe904, 0xea04, 0xeb04, 0xec04, 0xed04, 0xee04, 0xef04, 0xf004,
33 0xf0c4, 0xf144, 0xf1c4, 0xf244, 0xf2c4, 0xf344, 0xf3c4, 0xf444,
34 0xf4c4, 0xf544, 0xf5c4, 0xf644, 0xf6c4, 0xf744, 0xf7c4, 0xf844,
35 0xf8a4, 0xf8e4, 0xf924, 0xf964, 0xf9a4, 0xf9e4, 0xfa24, 0xfa64,
36 0xfaa4, 0xfae4, 0xfb24, 0xfb64, 0xfba4, 0xfbe4, 0xfc24, 0xfc64,
37 0xfc94, 0xfcb4, 0xfcd4, 0xfcf4, 0xfd14, 0xfd34, 0xfd54, 0xfd74,
38 0xfd94, 0xfdb4, 0xfdd4, 0xfdf4, 0xfe14, 0xfe34, 0xfe54, 0xfe74,
39 0xfe8c, 0xfe9c, 0xfeac, 0xfebc, 0xfecc, 0xfedc, 0xfeec, 0xfefc,
40 0xff0c, 0xff1c, 0xff2c, 0xff3c, 0xff4c, 0xff5c, 0xff6c, 0xff7c,
41 0xff88, 0xff90, 0xff98, 0xffa0, 0xffa8, 0xffb0, 0xffb8, 0xffc0,
42 0xffc8, 0xffd0, 0xffd8, 0xffe0, 0xffe8, 0xfff0, 0xfff8, 0x0000,
43 0x7d7c, 0x797c, 0x757c, 0x717c, 0x6d7c, 0x697c, 0x657c, 0x617c,
44 0x5d7c, 0x597c, 0x557c, 0x517c, 0x4d7c, 0x497c, 0x457c, 0x417c,
45 0x3e7c, 0x3c7c, 0x3a7c, 0x387c, 0x367c, 0x347c, 0x327c, 0x307c,
46 0x2e7c, 0x2c7c, 0x2a7c, 0x287c, 0x267c, 0x247c, 0x227c, 0x207c,
47 0x1efc, 0x1dfc, 0x1cfc, 0x1bfc, 0x1afc, 0x19fc, 0x18fc, 0x17fc,
48 0x16fc, 0x15fc, 0x14fc, 0x13fc, 0x12fc, 0x11fc, 0x10fc, 0x0ffc,
49 0x0f3c, 0x0ebc, 0x0e3c, 0x0dbc, 0x0d3c, 0x0cbc, 0x0c3c, 0x0bbc,
50 0x0b3c, 0x0abc, 0x0a3c, 0x09bc, 0x093c, 0x08bc, 0x083c, 0x07bc,
51 0x075c, 0x071c, 0x06dc, 0x069c, 0x065c, 0x061c, 0x05dc, 0x059c,
52 0x055c, 0x051c, 0x04dc, 0x049c, 0x045c, 0x041c, 0x03dc, 0x039c,
53 0x036c, 0x034c, 0x032c, 0x030c, 0x02ec, 0x02cc, 0x02ac, 0x028c,
54 0x026c, 0x024c, 0x022c, 0x020c, 0x01ec, 0x01cc, 0x01ac, 0x018c,
55 0x0174, 0x0164, 0x0154, 0x0144, 0x0134, 0x0124, 0x0114, 0x0104,
56 0x00f4, 0x00e4, 0x00d4, 0x00c4, 0x00b4, 0x00a4, 0x0094, 0x0084,
57 0x0078, 0x0070, 0x0068, 0x0060, 0x0058, 0x0050, 0x0048, 0x0040,
58 0x0038, 0x0030, 0x0028, 0x0020, 0x0018, 0x0010, 0x0008, 0x0000
59};
60
61/* alaw -> signed 16-bit */
62static short isdn_audio_alaw_to_s16[] =
63{
64 0x13fc, 0xec04, 0x0144, 0xfebc, 0x517c, 0xae84, 0x051c, 0xfae4,
65 0x0a3c, 0xf5c4, 0x0048, 0xffb8, 0x287c, 0xd784, 0x028c, 0xfd74,
66 0x1bfc, 0xe404, 0x01cc, 0xfe34, 0x717c, 0x8e84, 0x071c, 0xf8e4,
67 0x0e3c, 0xf1c4, 0x00c4, 0xff3c, 0x387c, 0xc784, 0x039c, 0xfc64,
68 0x0ffc, 0xf004, 0x0104, 0xfefc, 0x417c, 0xbe84, 0x041c, 0xfbe4,
69 0x083c, 0xf7c4, 0x0008, 0xfff8, 0x207c, 0xdf84, 0x020c, 0xfdf4,
70 0x17fc, 0xe804, 0x018c, 0xfe74, 0x617c, 0x9e84, 0x061c, 0xf9e4,
71 0x0c3c, 0xf3c4, 0x0084, 0xff7c, 0x307c, 0xcf84, 0x030c, 0xfcf4,
72 0x15fc, 0xea04, 0x0164, 0xfe9c, 0x597c, 0xa684, 0x059c, 0xfa64,
73 0x0b3c, 0xf4c4, 0x0068, 0xff98, 0x2c7c, 0xd384, 0x02cc, 0xfd34,
74 0x1dfc, 0xe204, 0x01ec, 0xfe14, 0x797c, 0x8684, 0x07bc, 0xf844,
75 0x0f3c, 0xf0c4, 0x00e4, 0xff1c, 0x3c7c, 0xc384, 0x03dc, 0xfc24,
76 0x11fc, 0xee04, 0x0124, 0xfedc, 0x497c, 0xb684, 0x049c, 0xfb64,
77 0x093c, 0xf6c4, 0x0028, 0xffd8, 0x247c, 0xdb84, 0x024c, 0xfdb4,
78 0x19fc, 0xe604, 0x01ac, 0xfe54, 0x697c, 0x9684, 0x069c, 0xf964,
79 0x0d3c, 0xf2c4, 0x00a4, 0xff5c, 0x347c, 0xcb84, 0x034c, 0xfcb4,
80 0x12fc, 0xed04, 0x0134, 0xfecc, 0x4d7c, 0xb284, 0x04dc, 0xfb24,
81 0x09bc, 0xf644, 0x0038, 0xffc8, 0x267c, 0xd984, 0x026c, 0xfd94,
82 0x1afc, 0xe504, 0x01ac, 0xfe54, 0x6d7c, 0x9284, 0x06dc, 0xf924,
83 0x0dbc, 0xf244, 0x00b4, 0xff4c, 0x367c, 0xc984, 0x036c, 0xfc94,
84 0x0f3c, 0xf0c4, 0x00f4, 0xff0c, 0x3e7c, 0xc184, 0x03dc, 0xfc24,
85 0x07bc, 0xf844, 0x0008, 0xfff8, 0x1efc, 0xe104, 0x01ec, 0xfe14,
86 0x16fc, 0xe904, 0x0174, 0xfe8c, 0x5d7c, 0xa284, 0x05dc, 0xfa24,
87 0x0bbc, 0xf444, 0x0078, 0xff88, 0x2e7c, 0xd184, 0x02ec, 0xfd14,
88 0x14fc, 0xeb04, 0x0154, 0xfeac, 0x557c, 0xaa84, 0x055c, 0xfaa4,
89 0x0abc, 0xf544, 0x0058, 0xffa8, 0x2a7c, 0xd584, 0x02ac, 0xfd54,
90 0x1cfc, 0xe304, 0x01cc, 0xfe34, 0x757c, 0x8a84, 0x075c, 0xf8a4,
91 0x0ebc, 0xf144, 0x00d4, 0xff2c, 0x3a7c, 0xc584, 0x039c, 0xfc64,
92 0x10fc, 0xef04, 0x0114, 0xfeec, 0x457c, 0xba84, 0x045c, 0xfba4,
93 0x08bc, 0xf744, 0x0018, 0xffe8, 0x227c, 0xdd84, 0x022c, 0xfdd4,
94 0x18fc, 0xe704, 0x018c, 0xfe74, 0x657c, 0x9a84, 0x065c, 0xf9a4,
95 0x0cbc, 0xf344, 0x0094, 0xff6c, 0x327c, 0xcd84, 0x032c, 0xfcd4
96};
97
98/* alaw -> ulaw */
99static char isdn_audio_alaw_to_ulaw[] =
100{
101 0xab, 0x2b, 0xe3, 0x63, 0x8b, 0x0b, 0xc9, 0x49,
102 0xba, 0x3a, 0xf6, 0x76, 0x9b, 0x1b, 0xd7, 0x57,
103 0xa3, 0x23, 0xdd, 0x5d, 0x83, 0x03, 0xc1, 0x41,
104 0xb2, 0x32, 0xeb, 0x6b, 0x93, 0x13, 0xcf, 0x4f,
105 0xaf, 0x2f, 0xe7, 0x67, 0x8f, 0x0f, 0xcd, 0x4d,
106 0xbe, 0x3e, 0xfe, 0x7e, 0x9f, 0x1f, 0xdb, 0x5b,
107 0xa7, 0x27, 0xdf, 0x5f, 0x87, 0x07, 0xc5, 0x45,
108 0xb6, 0x36, 0xef, 0x6f, 0x97, 0x17, 0xd3, 0x53,
109 0xa9, 0x29, 0xe1, 0x61, 0x89, 0x09, 0xc7, 0x47,
110 0xb8, 0x38, 0xf2, 0x72, 0x99, 0x19, 0xd5, 0x55,
111 0xa1, 0x21, 0xdc, 0x5c, 0x81, 0x01, 0xbf, 0x3f,
112 0xb0, 0x30, 0xe9, 0x69, 0x91, 0x11, 0xce, 0x4e,
113 0xad, 0x2d, 0xe5, 0x65, 0x8d, 0x0d, 0xcb, 0x4b,
114 0xbc, 0x3c, 0xfa, 0x7a, 0x9d, 0x1d, 0xd9, 0x59,
115 0xa5, 0x25, 0xde, 0x5e, 0x85, 0x05, 0xc3, 0x43,
116 0xb4, 0x34, 0xed, 0x6d, 0x95, 0x15, 0xd1, 0x51,
117 0xac, 0x2c, 0xe4, 0x64, 0x8c, 0x0c, 0xca, 0x4a,
118 0xbb, 0x3b, 0xf8, 0x78, 0x9c, 0x1c, 0xd8, 0x58,
119 0xa4, 0x24, 0xde, 0x5e, 0x84, 0x04, 0xc2, 0x42,
120 0xb3, 0x33, 0xec, 0x6c, 0x94, 0x14, 0xd0, 0x50,
121 0xb0, 0x30, 0xe8, 0x68, 0x90, 0x10, 0xce, 0x4e,
122 0xbf, 0x3f, 0xfe, 0x7e, 0xa0, 0x20, 0xdc, 0x5c,
123 0xa8, 0x28, 0xe0, 0x60, 0x88, 0x08, 0xc6, 0x46,
124 0xb7, 0x37, 0xf0, 0x70, 0x98, 0x18, 0xd4, 0x54,
125 0xaa, 0x2a, 0xe2, 0x62, 0x8a, 0x0a, 0xc8, 0x48,
126 0xb9, 0x39, 0xf4, 0x74, 0x9a, 0x1a, 0xd6, 0x56,
127 0xa2, 0x22, 0xdd, 0x5d, 0x82, 0x02, 0xc0, 0x40,
128 0xb1, 0x31, 0xea, 0x6a, 0x92, 0x12, 0xcf, 0x4f,
129 0xae, 0x2e, 0xe6, 0x66, 0x8e, 0x0e, 0xcc, 0x4c,
130 0xbd, 0x3d, 0xfc, 0x7c, 0x9e, 0x1e, 0xda, 0x5a,
131 0xa6, 0x26, 0xdf, 0x5f, 0x86, 0x06, 0xc4, 0x44,
132 0xb5, 0x35, 0xee, 0x6e, 0x96, 0x16, 0xd2, 0x52
133};
134
135/* ulaw -> alaw */
136static char isdn_audio_ulaw_to_alaw[] =
137{
138 0xab, 0x55, 0xd5, 0x15, 0x95, 0x75, 0xf5, 0x35,
139 0xb5, 0x45, 0xc5, 0x05, 0x85, 0x65, 0xe5, 0x25,
140 0xa5, 0x5d, 0xdd, 0x1d, 0x9d, 0x7d, 0xfd, 0x3d,
141 0xbd, 0x4d, 0xcd, 0x0d, 0x8d, 0x6d, 0xed, 0x2d,
142 0xad, 0x51, 0xd1, 0x11, 0x91, 0x71, 0xf1, 0x31,
143 0xb1, 0x41, 0xc1, 0x01, 0x81, 0x61, 0xe1, 0x21,
144 0x59, 0xd9, 0x19, 0x99, 0x79, 0xf9, 0x39, 0xb9,
145 0x49, 0xc9, 0x09, 0x89, 0x69, 0xe9, 0x29, 0xa9,
146 0xd7, 0x17, 0x97, 0x77, 0xf7, 0x37, 0xb7, 0x47,
147 0xc7, 0x07, 0x87, 0x67, 0xe7, 0x27, 0xa7, 0xdf,
148 0x9f, 0x7f, 0xff, 0x3f, 0xbf, 0x4f, 0xcf, 0x0f,
149 0x8f, 0x6f, 0xef, 0x2f, 0x53, 0x13, 0x73, 0x33,
150 0xb3, 0x43, 0xc3, 0x03, 0x83, 0x63, 0xe3, 0x23,
151 0xa3, 0x5b, 0xdb, 0x1b, 0x9b, 0x7b, 0xfb, 0x3b,
152 0xbb, 0xbb, 0x4b, 0x4b, 0xcb, 0xcb, 0x0b, 0x0b,
153 0x8b, 0x8b, 0x6b, 0x6b, 0xeb, 0xeb, 0x2b, 0x2b,
154 0xab, 0x54, 0xd4, 0x14, 0x94, 0x74, 0xf4, 0x34,
155 0xb4, 0x44, 0xc4, 0x04, 0x84, 0x64, 0xe4, 0x24,
156 0xa4, 0x5c, 0xdc, 0x1c, 0x9c, 0x7c, 0xfc, 0x3c,
157 0xbc, 0x4c, 0xcc, 0x0c, 0x8c, 0x6c, 0xec, 0x2c,
158 0xac, 0x50, 0xd0, 0x10, 0x90, 0x70, 0xf0, 0x30,
159 0xb0, 0x40, 0xc0, 0x00, 0x80, 0x60, 0xe0, 0x20,
160 0x58, 0xd8, 0x18, 0x98, 0x78, 0xf8, 0x38, 0xb8,
161 0x48, 0xc8, 0x08, 0x88, 0x68, 0xe8, 0x28, 0xa8,
162 0xd6, 0x16, 0x96, 0x76, 0xf6, 0x36, 0xb6, 0x46,
163 0xc6, 0x06, 0x86, 0x66, 0xe6, 0x26, 0xa6, 0xde,
164 0x9e, 0x7e, 0xfe, 0x3e, 0xbe, 0x4e, 0xce, 0x0e,
165 0x8e, 0x6e, 0xee, 0x2e, 0x52, 0x12, 0x72, 0x32,
166 0xb2, 0x42, 0xc2, 0x02, 0x82, 0x62, 0xe2, 0x22,
167 0xa2, 0x5a, 0xda, 0x1a, 0x9a, 0x7a, 0xfa, 0x3a,
168 0xba, 0xba, 0x4a, 0x4a, 0xca, 0xca, 0x0a, 0x0a,
169 0x8a, 0x8a, 0x6a, 0x6a, 0xea, 0xea, 0x2a, 0x2a
170};
171
172#define NCOEFF 8 /* number of frequencies to be analyzed */
173#define DTMF_TRESH 4000 /* above this is dtmf */
174#define SILENCE_TRESH 200 /* below this is silence */
175#define AMP_BITS 9 /* bits per sample, reduced to avoid overflow */
176#define LOGRP 0
177#define HIGRP 1
178
179/* For DTMF recognition:
180 * 2 * cos(2 * PI * k / N) precalculated for all k
181 */
182static int cos2pik[NCOEFF] =
183{
184 55813, 53604, 51193, 48591, 38114, 33057, 25889, 18332
185};
186
187static char dtmf_matrix[4][4] =
188{
189 {'1', '2', '3', 'A'},
190 {'4', '5', '6', 'B'},
191 {'7', '8', '9', 'C'},
192 {'*', '0', '#', 'D'}
193};
194
195static inline void
196isdn_audio_tlookup(const u_char *table, u_char *buff, unsigned long n)
197{
198#ifdef __i386__
199 unsigned long d0, d1, d2, d3;
200 __asm__ __volatile__(
201 "cld\n"
202 "1:\tlodsb\n\t"
203 "xlatb\n\t"
204 "stosb\n\t"
205 "loop 1b\n\t"
206 : "=&b"(d0), "=&c"(d1), "=&D"(d2), "=&S"(d3)
207 : "0"((long) table), "1"(n), "2"((long) buff), "3"((long) buff)
208 : "memory", "ax");
209#else
210 while (n--)
211 *buff = table[*(unsigned char *)buff], buff++;
212#endif
213}
214
215void
216isdn_audio_ulaw2alaw(unsigned char *buff, unsigned long len)
217{
218 isdn_audio_tlookup(isdn_audio_ulaw_to_alaw, buff, len);
219}
220
221void
222isdn_audio_alaw2ulaw(unsigned char *buff, unsigned long len)
223{
224 isdn_audio_tlookup(isdn_audio_alaw_to_ulaw, buff, len);
225}
226
227/*
228 * linear <-> adpcm conversion stuff
229 * Most parts from the mgetty-package.
230 * (C) by Gert Doering and Klaus Weidner
231 * Used by permission of Gert Doering
232 */
233
234
235#define ZEROTRAP /* turn on the trap as per the MIL-STD */
236#undef ZEROTRAP
237#define BIAS 0x84 /* define the add-in bias for 16 bit samples */
238#define CLIP 32635
239
240static unsigned char
241isdn_audio_linear2ulaw(int sample)
242{
243 static int exp_lut[256] =
244 {
245 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
246 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
247 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
248 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
249 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
250 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
251 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
252 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
253 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
254 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
255 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
256 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
257 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
258 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
259 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
260 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
261 };
262 int sign,
263 exponent,
264 mantissa;
265 unsigned char ulawbyte;
266
267 /* Get the sample into sign-magnitude. */
268 sign = (sample >> 8) & 0x80; /* set aside the sign */
269 if (sign != 0)
270 sample = -sample; /* get magnitude */
271 if (sample > CLIP)
272 sample = CLIP; /* clip the magnitude */
273
274 /* Convert from 16 bit linear to ulaw. */
275 sample = sample + BIAS;
276 exponent = exp_lut[(sample >> 7) & 0xFF];
277 mantissa = (sample >> (exponent + 3)) & 0x0F;
278 ulawbyte = ~(sign | (exponent << 4) | mantissa);
279#ifdef ZEROTRAP
280 /* optional CCITT trap */
281 if (ulawbyte == 0)
282 ulawbyte = 0x02;
283#endif
284 return (ulawbyte);
285}
286
287
288static int Mx[3][8] =
289{
290 {0x3800, 0x5600, 0, 0, 0, 0, 0, 0},
291 {0x399a, 0x3a9f, 0x4d14, 0x6607, 0, 0, 0, 0},
292 {0x3556, 0x3556, 0x399A, 0x3A9F, 0x4200, 0x4D14, 0x6607, 0x6607},
293};
294
295static int bitmask[9] =
296{
297 0, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff
298};
299
300static int
301isdn_audio_get_bits(adpcm_state * s, unsigned char **in, int *len)
302{
303 while (s->nleft < s->nbits) {
304 int d = *((*in)++);
305 (*len)--;
306 s->word = (s->word << 8) | d;
307 s->nleft += 8;
308 }
309 s->nleft -= s->nbits;
310 return (s->word >> s->nleft) & bitmask[s->nbits];
311}
312
313static void
314isdn_audio_put_bits(int data, int nbits, adpcm_state * s,
315 unsigned char **out, int *len)
316{
317 s->word = (s->word << nbits) | (data & bitmask[nbits]);
318 s->nleft += nbits;
319 while (s->nleft >= 8) {
320 int d = (s->word >> (s->nleft - 8));
321 *(out[0]++) = d & 255;
322 (*len)++;
323 s->nleft -= 8;
324 }
325}
326
327adpcm_state *
328isdn_audio_adpcm_init(adpcm_state * s, int nbits)
329{
330 if (!s)
331 s = (adpcm_state *) kmalloc(sizeof(adpcm_state), GFP_ATOMIC);
332 if (s) {
333 s->a = 0;
334 s->d = 5;
335 s->word = 0;
336 s->nleft = 0;
337 s->nbits = nbits;
338 }
339 return s;
340}
341
342dtmf_state *
343isdn_audio_dtmf_init(dtmf_state * s)
344{
345 if (!s)
346 s = (dtmf_state *) kmalloc(sizeof(dtmf_state), GFP_ATOMIC);
347 if (s) {
348 s->idx = 0;
349 s->last = ' ';
350 }
351 return s;
352}
353
354/*
355 * Decompression of adpcm data to a/u-law
356 *
357 */
358
359int
360isdn_audio_adpcm2xlaw(adpcm_state * s, int fmt, unsigned char *in,
361 unsigned char *out, int len)
362{
363 int a = s->a;
364 int d = s->d;
365 int nbits = s->nbits;
366 int olen = 0;
367
368 while (len) {
369 int e = isdn_audio_get_bits(s, &in, &len);
370 int sign;
371
372 if (nbits == 4 && e == 0)
373 d = 4;
374 sign = (e >> (nbits - 1)) ? -1 : 1;
375 e &= bitmask[nbits - 1];
376 a += sign * ((e << 1) + 1) * d >> 1;
377 if (d & 1)
378 a++;
379 if (fmt)
380 *out++ = isdn_audio_ulaw_to_alaw[
381 isdn_audio_linear2ulaw(a << 2)];
382 else
383 *out++ = isdn_audio_linear2ulaw(a << 2);
384 olen++;
385 d = (d * Mx[nbits - 2][e] + 0x2000) >> 14;
386 if (d < 5)
387 d = 5;
388 }
389 s->a = a;
390 s->d = d;
391 return olen;
392}
393
394int
395isdn_audio_2adpcm_flush(adpcm_state * s, unsigned char *out)
396{
397 int olen = 0;
398
399 if (s->nleft)
400 isdn_audio_put_bits(0, 8 - s->nleft, s, &out, &olen);
401 return olen;
402}
403
404int
405isdn_audio_xlaw2adpcm(adpcm_state * s, int fmt, unsigned char *in,
406 unsigned char *out, int len)
407{
408 int a = s->a;
409 int d = s->d;
410 int nbits = s->nbits;
411 int olen = 0;
412
413 while (len--) {
414 int e = 0,
415 nmax = 1 << (nbits - 1);
416 int sign,
417 delta;
418
419 if (fmt)
420 delta = (isdn_audio_alaw_to_s16[*in++] >> 2) - a;
421 else
422 delta = (isdn_audio_ulaw_to_s16[*in++] >> 2) - a;
423 if (delta < 0) {
424 e = nmax;
425 delta = -delta;
426 }
427 while (--nmax && delta > d) {
428 delta -= d;
429 e++;
430 }
431 if (nbits == 4 && ((e & 0x0f) == 0))
432 e = 8;
433 isdn_audio_put_bits(e, nbits, s, &out, &olen);
434 sign = (e >> (nbits - 1)) ? -1 : 1;
435 e &= bitmask[nbits - 1];
436
437 a += sign * ((e << 1) + 1) * d >> 1;
438 if (d & 1)
439 a++;
440 d = (d * Mx[nbits - 2][e] + 0x2000) >> 14;
441 if (d < 5)
442 d = 5;
443 }
444 s->a = a;
445 s->d = d;
446 return olen;
447}
448
449/*
450 * Goertzel algorithm.
451 * See http://ptolemy.eecs.berkeley.edu/~pino/Ptolemy/papers/96/dtmf_ict/
452 * for more info.
453 * Result is stored into an sk_buff and queued up for later
454 * evaluation.
455 */
456static void
457isdn_audio_goertzel(int *sample, modem_info * info)
458{
459 int sk,
460 sk1,
461 sk2;
462 int k,
463 n;
464 struct sk_buff *skb;
465 int *result;
466
467 skb = dev_alloc_skb(sizeof(int) * NCOEFF);
468 if (!skb) {
469 printk(KERN_WARNING
470 "isdn_audio: Could not alloc DTMF result for ttyI%d\n",
471 info->line);
472 return;
473 }
474 result = (int *) skb_put(skb, sizeof(int) * NCOEFF);
475 for (k = 0; k < NCOEFF; k++) {
476 sk = sk1 = sk2 = 0;
477 for (n = 0; n < DTMF_NPOINTS; n++) {
478 sk = sample[n] + ((cos2pik[k] * sk1) >> 15) - sk2;
479 sk2 = sk1;
480 sk1 = sk;
481 }
482 /* Avoid overflows */
483 sk >>= 1;
484 sk2 >>= 1;
485 /* compute |X(k)|**2 */
486 /* report overflows. This should not happen. */
487 /* Comment this out if desired */
488 if (sk < -32768 || sk > 32767)
489 printk(KERN_DEBUG
490 "isdn_audio: dtmf goertzel overflow, sk=%d\n", sk);
491 if (sk2 < -32768 || sk2 > 32767)
492 printk(KERN_DEBUG
493 "isdn_audio: dtmf goertzel overflow, sk2=%d\n", sk2);
494 result[k] =
495 ((sk * sk) >> AMP_BITS) -
496 ((((cos2pik[k] * sk) >> 15) * sk2) >> AMP_BITS) +
497 ((sk2 * sk2) >> AMP_BITS);
498 }
499 skb_queue_tail(&info->dtmf_queue, skb);
500 isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
501}
502
503void
504isdn_audio_eval_dtmf(modem_info * info)
505{
506 struct sk_buff *skb;
507 int *result;
508 dtmf_state *s;
509 int silence;
510 int i;
511 int di;
512 int ch;
513 int grp[2];
514 char what;
515 char *p;
516 int thresh;
517
518 while ((skb = skb_dequeue(&info->dtmf_queue))) {
519 result = (int *) skb->data;
520 s = info->dtmf_state;
521 grp[LOGRP] = grp[HIGRP] = -1;
522 silence = 0;
523 thresh = 0;
524 for (i = 0; i < NCOEFF; i++) {
525 if (result[i] > DTMF_TRESH) {
526 if (result[i] > thresh)
527 thresh = result[i];
528 }
529 else if (result[i] < SILENCE_TRESH)
530 silence++;
531 }
532 if (silence == NCOEFF)
533 what = ' ';
534 else {
535 if (thresh > 0) {
536 thresh = thresh >> 4; /* touchtones must match within 12 dB */
537 for (i = 0; i < NCOEFF; i++) {
538 if (result[i] < thresh)
539 continue; /* ignore */
540 /* good level found. This is allowed only one time per group */
541 if (i < NCOEFF / 2) {
542 /* lowgroup*/
543 if (grp[LOGRP] >= 0) {
544 // Bad. Another tone found. */
545 grp[LOGRP] = -1;
546 break;
547 }
548 else
549 grp[LOGRP] = i;
550 }
551 else { /* higroup */
552 if (grp[HIGRP] >= 0) { // Bad. Another tone found. */
553 grp[HIGRP] = -1;
554 break;
555 }
556 else
557 grp[HIGRP] = i - NCOEFF/2;
558 }
559 }
560 if ((grp[LOGRP] >= 0) && (grp[HIGRP] >= 0)) {
561 what = dtmf_matrix[grp[LOGRP]][grp[HIGRP]];
562 if (s->last != ' ' && s->last != '.')
563 s->last = what; /* min. 1 non-DTMF between DTMF */
564 } else
565 what = '.';
566 }
567 else
568 what = '.';
569 }
570 if ((what != s->last) && (what != ' ') && (what != '.')) {
571 printk(KERN_DEBUG "dtmf: tt='%c'\n", what);
572 p = skb->data;
573 *p++ = 0x10;
574 *p = what;
575 skb_trim(skb, 2);
576 ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;
577 ISDN_AUDIO_SKB_LOCK(skb) = 0;
578 di = info->isdn_driver;
579 ch = info->isdn_channel;
580 __skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb);
581 dev->drv[di]->rcvcount[ch] += 2;
582 /* Schedule dequeuing */
583 if ((dev->modempoll) && (info->rcvsched))
584 isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
585 wake_up_interruptible(&dev->drv[di]->rcv_waitq[ch]);
586 } else
587 kfree_skb(skb);
588 s->last = what;
589 }
590}
591
592/*
593 * Decode DTMF tones, queue result in separate sk_buf for
594 * later examination.
595 * Parameters:
596 * s = pointer to state-struct.
597 * buf = input audio data
598 * len = size of audio data.
599 * fmt = audio data format (0 = ulaw, 1 = alaw)
600 */
601void
602isdn_audio_calc_dtmf(modem_info * info, unsigned char *buf, int len, int fmt)
603{
604 dtmf_state *s = info->dtmf_state;
605 int i;
606 int c;
607
608 while (len) {
609 c = DTMF_NPOINTS - s->idx;
610 if (c > len)
611 c = len;
612 if (c <= 0)
613 break;
614 for (i = 0; i < c; i++) {
615 if (fmt)
616 s->buf[s->idx++] =
617 isdn_audio_alaw_to_s16[*buf++] >> (15 - AMP_BITS);
618 else
619 s->buf[s->idx++] =
620 isdn_audio_ulaw_to_s16[*buf++] >> (15 - AMP_BITS);
621 }
622 if (s->idx == DTMF_NPOINTS) {
623 isdn_audio_goertzel(s->buf, info);
624 s->idx = 0;
625 }
626 len -= c;
627 }
628}
629
630silence_state *
631isdn_audio_silence_init(silence_state * s)
632{
633 if (!s)
634 s = (silence_state *) kmalloc(sizeof(silence_state), GFP_ATOMIC);
635 if (s) {
636 s->idx = 0;
637 s->state = 0;
638 }
639 return s;
640}
641
642void
643isdn_audio_calc_silence(modem_info * info, unsigned char *buf, int len, int fmt)
644{
645 silence_state *s = info->silence_state;
646 int i;
647 signed char c;
648
649 if (!info->emu.vpar[1]) return;
650
651 for (i = 0; i < len; i++) {
652 if (fmt)
653 c = isdn_audio_alaw_to_ulaw[*buf++];
654 else
655 c = *buf++;
656
657 if (c > 0) c -= 128;
658 c = abs(c);
659
660 if (c > (info->emu.vpar[1] * 4)) {
661 s->idx = 0;
662 s->state = 1;
663 } else {
664 if (s->idx < 210000) s->idx++;
665 }
666 }
667}
668
669void
670isdn_audio_put_dle_code(modem_info * info, u_char code)
671{
672 struct sk_buff *skb;
673 int di;
674 int ch;
675 char *p;
676
677 skb = dev_alloc_skb(2);
678 if (!skb) {
679 printk(KERN_WARNING
680 "isdn_audio: Could not alloc skb for ttyI%d\n",
681 info->line);
682 return;
683 }
684 p = (char *) skb_put(skb, 2);
685 p[0] = 0x10;
686 p[1] = code;
687 ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;
688 ISDN_AUDIO_SKB_LOCK(skb) = 0;
689 di = info->isdn_driver;
690 ch = info->isdn_channel;
691 __skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb);
692 dev->drv[di]->rcvcount[ch] += 2;
693 /* Schedule dequeuing */
694 if ((dev->modempoll) && (info->rcvsched))
695 isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
696 wake_up_interruptible(&dev->drv[di]->rcv_waitq[ch]);
697}
698
699void
700isdn_audio_eval_silence(modem_info * info)
701{
702 silence_state *s = info->silence_state;
703 char what;
704
705 what = ' ';
706
707 if (s->idx > (info->emu.vpar[2] * 800)) {
708 s->idx = 0;
709 if (!s->state) { /* silence from beginning of rec */
710 what = 's';
711 } else {
712 what = 'q';
713 }
714 }
715 if ((what == 's') || (what == 'q')) {
716 printk(KERN_DEBUG "ttyI%d: %s\n", info->line,
717 (what=='s') ? "silence":"quiet");
718 isdn_audio_put_dle_code(info, what);
719 }
720}
diff --git a/drivers/isdn/i4l/isdn_audio.h b/drivers/isdn/i4l/isdn_audio.h
new file mode 100644
index 000000000000..5a977b21dcfa
--- /dev/null
+++ b/drivers/isdn/i4l/isdn_audio.h
@@ -0,0 +1,45 @@
1/* $Id: isdn_audio.h,v 1.1.2.2 2004/01/12 22:37:18 keil Exp $
2 *
3 * Linux ISDN subsystem, audio conversion and compression (linklevel).
4 *
5 * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de)
6 *
7 * This software may be used and distributed according to the terms
8 * of the GNU General Public License, incorporated herein by reference.
9 *
10 */
11
12#define DTMF_NPOINTS 205 /* Number of samples for DTMF recognition */
13typedef struct adpcm_state {
14 int a;
15 int d;
16 int word;
17 int nleft;
18 int nbits;
19} adpcm_state;
20
21typedef struct dtmf_state {
22 char last;
23 char llast;
24 int idx;
25 int buf[DTMF_NPOINTS];
26} dtmf_state;
27
28typedef struct silence_state {
29 int state;
30 unsigned int idx;
31} silence_state;
32
33extern void isdn_audio_ulaw2alaw(unsigned char *, unsigned long);
34extern void isdn_audio_alaw2ulaw(unsigned char *, unsigned long);
35extern adpcm_state *isdn_audio_adpcm_init(adpcm_state *, int);
36extern int isdn_audio_adpcm2xlaw(adpcm_state *, int, unsigned char *, unsigned char *, int);
37extern int isdn_audio_xlaw2adpcm(adpcm_state *, int, unsigned char *, unsigned char *, int);
38extern int isdn_audio_2adpcm_flush(adpcm_state * s, unsigned char *out);
39extern void isdn_audio_calc_dtmf(modem_info *, unsigned char *, int, int);
40extern void isdn_audio_eval_dtmf(modem_info *);
41dtmf_state *isdn_audio_dtmf_init(dtmf_state *);
42extern void isdn_audio_calc_silence(modem_info *, unsigned char *, int, int);
43extern void isdn_audio_eval_silence(modem_info *);
44silence_state *isdn_audio_silence_init(silence_state *);
45extern void isdn_audio_put_dle_code(modem_info *, u_char);
diff --git a/drivers/isdn/i4l/isdn_bsdcomp.c b/drivers/isdn/i4l/isdn_bsdcomp.c
new file mode 100644
index 000000000000..baf4bcad9bf9
--- /dev/null
+++ b/drivers/isdn/i4l/isdn_bsdcomp.c
@@ -0,0 +1,937 @@
1/*
2 * BSD compression module
3 *
4 * Patched version for ISDN syncPPP written 1997/1998 by Michael Hipp
5 * The whole module is now SKB based.
6 *
7 */
8
9/*
10 * Update: The Berkeley copyright was changed, and the change
11 * is retroactive to all "true" BSD software (ie everything
12 * from UCB as opposed to other peoples code that just carried
13 * the same license). The new copyright doesn't clash with the
14 * GPL, so the module-only restriction has been removed..
15 */
16
17/*
18 * Original copyright notice:
19 *
20 * Copyright (c) 1985, 1986 The Regents of the University of California.
21 * All rights reserved.
22 *
23 * This code is derived from software contributed to Berkeley by
24 * James A. Woods, derived from original work by Spencer Thomas
25 * and Joseph Orost.
26 *
27 * Redistribution and use in source and binary forms, with or without
28 * modification, are permitted provided that the following conditions
29 * are met:
30 * 1. Redistributions of source code must retain the above copyright
31 * notice, this list of conditions and the following disclaimer.
32 * 2. Redistributions in binary form must reproduce the above copyright
33 * notice, this list of conditions and the following disclaimer in the
34 * documentation and/or other materials provided with the distribution.
35 * 3. All advertising materials mentioning features or use of this software
36 * must display the following acknowledgement:
37 * This product includes software developed by the University of
38 * California, Berkeley and its contributors.
39 * 4. Neither the name of the University nor the names of its contributors
40 * may be used to endorse or promote products derived from this software
41 * without specific prior written permission.
42 *
43 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
44 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
45 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
47 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
48 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
49 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
50 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
51 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
52 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
53 * SUCH DAMAGE.
54 */
55
56#include <linux/module.h>
57#include <linux/init.h>
58#include <linux/kernel.h>
59#include <linux/sched.h>
60#include <linux/types.h>
61#include <linux/fcntl.h>
62#include <linux/interrupt.h>
63#include <linux/ptrace.h>
64#include <linux/ioport.h>
65#include <linux/in.h>
66#include <linux/slab.h>
67#include <linux/tty.h>
68#include <linux/errno.h>
69#include <linux/string.h> /* used in new tty drivers */
70#include <linux/signal.h> /* used in new tty drivers */
71#include <linux/bitops.h>
72
73#include <asm/system.h>
74#include <asm/byteorder.h>
75#include <asm/types.h>
76
77#include <linux/if.h>
78
79#include <linux/if_ether.h>
80#include <linux/netdevice.h>
81#include <linux/skbuff.h>
82#include <linux/inet.h>
83#include <linux/ioctl.h>
84#include <linux/vmalloc.h>
85
86#include <linux/ppp_defs.h>
87
88#include <linux/isdn.h>
89#include <linux/isdn_ppp.h>
90#include <linux/ip.h>
91#include <linux/tcp.h>
92#include <linux/if_arp.h>
93#include <linux/ppp-comp.h>
94
95#include "isdn_ppp.h"
96
97MODULE_DESCRIPTION("ISDN4Linux: BSD Compression for PPP over ISDN");
98MODULE_LICENSE("Dual BSD/GPL");
99
100#define BSD_VERSION(x) ((x) >> 5)
101#define BSD_NBITS(x) ((x) & 0x1F)
102
103#define BSD_CURRENT_VERSION 1
104
105#define DEBUG 1
106
107/*
108 * A dictionary for doing BSD compress.
109 */
110
111struct bsd_dict {
112 u32 fcode;
113 u16 codem1; /* output of hash table -1 */
114 u16 cptr; /* map code to hash table entry */
115};
116
117struct bsd_db {
118 int totlen; /* length of this structure */
119 unsigned int hsize; /* size of the hash table */
120 unsigned char hshift; /* used in hash function */
121 unsigned char n_bits; /* current bits/code */
122 unsigned char maxbits; /* maximum bits/code */
123 unsigned char debug; /* non-zero if debug desired */
124 unsigned char unit; /* ppp unit number */
125 u16 seqno; /* sequence # of next packet */
126 unsigned int mru; /* size of receive (decompress) bufr */
127 unsigned int maxmaxcode; /* largest valid code */
128 unsigned int max_ent; /* largest code in use */
129 unsigned int in_count; /* uncompressed bytes, aged */
130 unsigned int bytes_out; /* compressed bytes, aged */
131 unsigned int ratio; /* recent compression ratio */
132 unsigned int checkpoint; /* when to next check the ratio */
133 unsigned int clear_count; /* times dictionary cleared */
134 unsigned int incomp_count; /* incompressible packets */
135 unsigned int incomp_bytes; /* incompressible bytes */
136 unsigned int uncomp_count; /* uncompressed packets */
137 unsigned int uncomp_bytes; /* uncompressed bytes */
138 unsigned int comp_count; /* compressed packets */
139 unsigned int comp_bytes; /* compressed bytes */
140 unsigned short *lens; /* array of lengths of codes */
141 struct bsd_dict *dict; /* dictionary */
142 int xmit;
143};
144
145#define BSD_OVHD 2 /* BSD compress overhead/packet */
146#define MIN_BSD_BITS 9
147#define BSD_INIT_BITS MIN_BSD_BITS
148#define MAX_BSD_BITS 15
149
150/*
151 * the next two codes should not be changed lightly, as they must not
152 * lie within the contiguous general code space.
153 */
154#define CLEAR 256 /* table clear output code */
155#define FIRST 257 /* first free entry */
156#define LAST 255
157
158#define MAXCODE(b) ((1 << (b)) - 1)
159#define BADCODEM1 MAXCODE(MAX_BSD_BITS);
160
161#define BSD_HASH(prefix,suffix,hshift) ((((unsigned long)(suffix))<<(hshift)) \
162 ^ (unsigned long)(prefix))
163#define BSD_KEY(prefix,suffix) ((((unsigned long)(suffix)) << 16) \
164 + (unsigned long)(prefix))
165
166#define CHECK_GAP 10000 /* Ratio check interval */
167
168#define RATIO_SCALE_LOG 8
169#define RATIO_SCALE (1<<RATIO_SCALE_LOG)
170#define RATIO_MAX (0x7fffffff>>RATIO_SCALE_LOG)
171
172/*
173 * clear the dictionary
174 */
175
176static void bsd_clear(struct bsd_db *db)
177{
178 db->clear_count++;
179 db->max_ent = FIRST-1;
180 db->n_bits = BSD_INIT_BITS;
181 db->bytes_out = 0;
182 db->in_count = 0;
183 db->incomp_count = 0;
184 db->ratio = 0;
185 db->checkpoint = CHECK_GAP;
186}
187
188/*
189 * If the dictionary is full, then see if it is time to reset it.
190 *
191 * Compute the compression ratio using fixed-point arithmetic
192 * with 8 fractional bits.
193 *
194 * Since we have an infinite stream instead of a single file,
195 * watch only the local compression ratio.
196 *
197 * Since both peers must reset the dictionary at the same time even in
198 * the absence of CLEAR codes (while packets are incompressible), they
199 * must compute the same ratio.
200 */
201static int bsd_check (struct bsd_db *db) /* 1=output CLEAR */
202{
203 unsigned int new_ratio;
204
205 if (db->in_count >= db->checkpoint)
206 {
207 /* age the ratio by limiting the size of the counts */
208 if (db->in_count >= RATIO_MAX || db->bytes_out >= RATIO_MAX)
209 {
210 db->in_count -= (db->in_count >> 2);
211 db->bytes_out -= (db->bytes_out >> 2);
212 }
213
214 db->checkpoint = db->in_count + CHECK_GAP;
215
216 if (db->max_ent >= db->maxmaxcode)
217 {
218 /* Reset the dictionary only if the ratio is worse,
219 * or if it looks as if it has been poisoned
220 * by incompressible data.
221 *
222 * This does not overflow, because
223 * db->in_count <= RATIO_MAX.
224 */
225
226 new_ratio = db->in_count << RATIO_SCALE_LOG;
227 if (db->bytes_out != 0)
228 {
229 new_ratio /= db->bytes_out;
230 }
231
232 if (new_ratio < db->ratio || new_ratio < 1 * RATIO_SCALE)
233 {
234 bsd_clear (db);
235 return 1;
236 }
237 db->ratio = new_ratio;
238 }
239 }
240 return 0;
241}
242
243/*
244 * Return statistics.
245 */
246
247static void bsd_stats (void *state, struct compstat *stats)
248{
249 struct bsd_db *db = (struct bsd_db *) state;
250
251 stats->unc_bytes = db->uncomp_bytes;
252 stats->unc_packets = db->uncomp_count;
253 stats->comp_bytes = db->comp_bytes;
254 stats->comp_packets = db->comp_count;
255 stats->inc_bytes = db->incomp_bytes;
256 stats->inc_packets = db->incomp_count;
257 stats->in_count = db->in_count;
258 stats->bytes_out = db->bytes_out;
259}
260
261/*
262 * Reset state, as on a CCP ResetReq.
263 */
264static void bsd_reset (void *state,unsigned char code, unsigned char id,
265 unsigned char *data, unsigned len,
266 struct isdn_ppp_resetparams *rsparm)
267{
268 struct bsd_db *db = (struct bsd_db *) state;
269
270 bsd_clear(db);
271 db->seqno = 0;
272 db->clear_count = 0;
273}
274
275/*
276 * Release the compression structure
277 */
278static void bsd_free (void *state)
279{
280 struct bsd_db *db = (struct bsd_db *) state;
281
282 if (db) {
283 /*
284 * Release the dictionary
285 */
286 if (db->dict) {
287 vfree (db->dict);
288 db->dict = NULL;
289 }
290
291 /*
292 * Release the string buffer
293 */
294 if (db->lens) {
295 vfree (db->lens);
296 db->lens = NULL;
297 }
298
299 /*
300 * Finally release the structure itself.
301 */
302 kfree (db);
303 }
304}
305
306
307/*
308 * Allocate space for a (de) compressor.
309 */
310static void *bsd_alloc (struct isdn_ppp_comp_data *data)
311{
312 int bits;
313 unsigned int hsize, hshift, maxmaxcode;
314 struct bsd_db *db;
315 int decomp;
316
317 static unsigned int htab[][2] = {
318 { 5003 , 4 } , { 5003 , 4 } , { 5003 , 4 } , { 5003 , 4 } ,
319 { 9001 , 5 } , { 18013 , 6 } , { 35023 , 7 } , { 69001 , 8 }
320 };
321
322 if (data->optlen != 1 || data->num != CI_BSD_COMPRESS
323 || BSD_VERSION(data->options[0]) != BSD_CURRENT_VERSION)
324 return NULL;
325
326 bits = BSD_NBITS(data->options[0]);
327
328 if(bits < 9 || bits > 15)
329 return NULL;
330
331 hsize = htab[bits-9][0];
332 hshift = htab[bits-9][1];
333
334 /*
335 * Allocate the main control structure for this instance.
336 */
337 maxmaxcode = MAXCODE(bits);
338 db = (struct bsd_db *) kmalloc (sizeof (struct bsd_db),GFP_KERNEL);
339 if (!db)
340 return NULL;
341
342 memset (db, 0, sizeof(struct bsd_db));
343
344 db->xmit = data->flags & IPPP_COMP_FLAG_XMIT;
345 decomp = db->xmit ? 0 : 1;
346
347 /*
348 * Allocate space for the dictionary. This may be more than one page in
349 * length.
350 */
351 db->dict = (struct bsd_dict *) vmalloc (hsize * sizeof (struct bsd_dict));
352 if (!db->dict) {
353 bsd_free (db);
354 return NULL;
355 }
356
357 /*
358 * If this is the compression buffer then there is no length data.
359 * For decompression, the length information is needed as well.
360 */
361 if (!decomp)
362 db->lens = NULL;
363 else {
364 db->lens = (unsigned short *) vmalloc ((maxmaxcode + 1) *
365 sizeof (db->lens[0]));
366 if (!db->lens) {
367 bsd_free (db);
368 return (NULL);
369 }
370 }
371
372 /*
373 * Initialize the data information for the compression code
374 */
375 db->totlen = sizeof (struct bsd_db) + (sizeof (struct bsd_dict) * hsize);
376 db->hsize = hsize;
377 db->hshift = hshift;
378 db->maxmaxcode = maxmaxcode;
379 db->maxbits = bits;
380
381 return (void *) db;
382}
383
384/*
385 * Initialize the database.
386 */
387static int bsd_init (void *state, struct isdn_ppp_comp_data *data, int unit, int debug)
388{
389 struct bsd_db *db = state;
390 int indx;
391 int decomp;
392
393 if(!state || !data) {
394 printk(KERN_ERR "isdn_bsd_init: [%d] ERR, state %lx data %lx\n",unit,(long)state,(long)data);
395 return 0;
396 }
397
398 decomp = db->xmit ? 0 : 1;
399
400 if (data->optlen != 1 || data->num != CI_BSD_COMPRESS
401 || (BSD_VERSION(data->options[0]) != BSD_CURRENT_VERSION)
402 || (BSD_NBITS(data->options[0]) != db->maxbits)
403 || (decomp && db->lens == NULL)) {
404 printk(KERN_ERR "isdn_bsd: %d %d %d %d %lx\n",data->optlen,data->num,data->options[0],decomp,(unsigned long)db->lens);
405 return 0;
406 }
407
408 if (decomp)
409 for(indx=LAST;indx>=0;indx--)
410 db->lens[indx] = 1;
411
412 indx = db->hsize;
413 while (indx-- != 0) {
414 db->dict[indx].codem1 = BADCODEM1;
415 db->dict[indx].cptr = 0;
416 }
417
418 db->unit = unit;
419 db->mru = 0;
420
421 db->debug = 1;
422
423 bsd_reset(db,0,0,NULL,0,NULL);
424
425 return 1;
426}
427
428/*
429 * Obtain pointers to the various structures in the compression tables
430 */
431
432#define dict_ptrx(p,idx) &(p->dict[idx])
433#define lens_ptrx(p,idx) &(p->lens[idx])
434
435#ifdef DEBUG
436static unsigned short *lens_ptr(struct bsd_db *db, int idx)
437{
438 if ((unsigned int) idx > (unsigned int) db->maxmaxcode) {
439 printk (KERN_DEBUG "<9>ppp: lens_ptr(%d) > max\n", idx);
440 idx = 0;
441 }
442 return lens_ptrx (db, idx);
443}
444
445static struct bsd_dict *dict_ptr(struct bsd_db *db, int idx)
446{
447 if ((unsigned int) idx >= (unsigned int) db->hsize) {
448 printk (KERN_DEBUG "<9>ppp: dict_ptr(%d) > max\n", idx);
449 idx = 0;
450 }
451 return dict_ptrx (db, idx);
452}
453
454#else
455#define lens_ptr(db,idx) lens_ptrx(db,idx)
456#define dict_ptr(db,idx) dict_ptrx(db,idx)
457#endif
458
459/*
460 * compress a packet
461 */
462static int bsd_compress (void *state, struct sk_buff *skb_in, struct sk_buff *skb_out,int proto)
463{
464 struct bsd_db *db;
465 int hshift;
466 unsigned int max_ent;
467 unsigned int n_bits;
468 unsigned int bitno;
469 unsigned long accm;
470 int ent;
471 unsigned long fcode;
472 struct bsd_dict *dictp;
473 unsigned char c;
474 int hval,disp,ilen,mxcode;
475 unsigned char *rptr = skb_in->data;
476 int isize = skb_in->len;
477
478#define OUTPUT(ent) \
479 { \
480 bitno -= n_bits; \
481 accm |= ((ent) << bitno); \
482 do { \
483 if(skb_out && skb_tailroom(skb_out) > 0) \
484 *(skb_put(skb_out,1)) = (unsigned char) (accm>>24); \
485 accm <<= 8; \
486 bitno += 8; \
487 } while (bitno <= 24); \
488 }
489
490 /*
491 * If the protocol is not in the range we're interested in,
492 * just return without compressing the packet. If it is,
493 * the protocol becomes the first byte to compress.
494 */
495 printk(KERN_DEBUG "bsd_compress called with %x\n",proto);
496
497 ent = proto;
498 if (proto < 0x21 || proto > 0xf9 || !(proto & 0x1) )
499 return 0;
500
501 db = (struct bsd_db *) state;
502 hshift = db->hshift;
503 max_ent = db->max_ent;
504 n_bits = db->n_bits;
505 bitno = 32;
506 accm = 0;
507 mxcode = MAXCODE (n_bits);
508
509 /* This is the PPP header information */
510 if(skb_out && skb_tailroom(skb_out) >= 2) {
511 char *v = skb_put(skb_out,2);
512 /* we only push our own data on the header,
513 AC,PC and protos is pushed by caller */
514 v[0] = db->seqno >> 8;
515 v[1] = db->seqno;
516 }
517
518 ilen = ++isize; /* This is off by one, but that is what is in draft! */
519
520 while (--ilen > 0) {
521 c = *rptr++;
522 fcode = BSD_KEY (ent, c);
523 hval = BSD_HASH (ent, c, hshift);
524 dictp = dict_ptr (db, hval);
525
526 /* Validate and then check the entry. */
527 if (dictp->codem1 >= max_ent)
528 goto nomatch;
529
530 if (dictp->fcode == fcode) {
531 ent = dictp->codem1 + 1;
532 continue; /* found (prefix,suffix) */
533 }
534
535 /* continue probing until a match or invalid entry */
536 disp = (hval == 0) ? 1 : hval;
537
538 do {
539 hval += disp;
540 if (hval >= db->hsize)
541 hval -= db->hsize;
542 dictp = dict_ptr (db, hval);
543 if (dictp->codem1 >= max_ent)
544 goto nomatch;
545 } while (dictp->fcode != fcode);
546
547 ent = dictp->codem1 + 1; /* finally found (prefix,suffix) */
548 continue;
549
550nomatch:
551 OUTPUT(ent); /* output the prefix */
552
553 /* code -> hashtable */
554 if (max_ent < db->maxmaxcode) {
555 struct bsd_dict *dictp2;
556 struct bsd_dict *dictp3;
557 int indx;
558
559 /* expand code size if needed */
560 if (max_ent >= mxcode) {
561 db->n_bits = ++n_bits;
562 mxcode = MAXCODE (n_bits);
563 }
564
565 /*
566 * Invalidate old hash table entry using
567 * this code, and then take it over.
568 */
569 dictp2 = dict_ptr (db, max_ent + 1);
570 indx = dictp2->cptr;
571 dictp3 = dict_ptr (db, indx);
572
573 if (dictp3->codem1 == max_ent)
574 dictp3->codem1 = BADCODEM1;
575
576 dictp2->cptr = hval;
577 dictp->codem1 = max_ent;
578 dictp->fcode = fcode;
579 db->max_ent = ++max_ent;
580
581 if (db->lens) {
582 unsigned short *len1 = lens_ptr (db, max_ent);
583 unsigned short *len2 = lens_ptr (db, ent);
584 *len1 = *len2 + 1;
585 }
586 }
587 ent = c;
588 }
589
590 OUTPUT(ent); /* output the last code */
591
592 if(skb_out)
593 db->bytes_out += skb_out->len; /* Do not count bytes from here */
594 db->uncomp_bytes += isize;
595 db->in_count += isize;
596 ++db->uncomp_count;
597 ++db->seqno;
598
599 if (bitno < 32)
600 ++db->bytes_out; /* must be set before calling bsd_check */
601
602 /*
603 * Generate the clear command if needed
604 */
605
606 if (bsd_check(db))
607 OUTPUT (CLEAR);
608
609 /*
610 * Pad dribble bits of last code with ones.
611 * Do not emit a completely useless byte of ones.
612 */
613 if (bitno < 32 && skb_out && skb_tailroom(skb_out) > 0)
614 *(skb_put(skb_out,1)) = (unsigned char) ((accm | (0xff << (bitno-8))) >> 24);
615
616 /*
617 * Increase code size if we would have without the packet
618 * boundary because the decompressor will do so.
619 */
620 if (max_ent >= mxcode && max_ent < db->maxmaxcode)
621 db->n_bits++;
622
623 /* If output length is too large then this is an incompressible frame. */
624 if (!skb_out || (skb_out && skb_out->len >= skb_in->len) ) {
625 ++db->incomp_count;
626 db->incomp_bytes += isize;
627 return 0;
628 }
629
630 /* Count the number of compressed frames */
631 ++db->comp_count;
632 db->comp_bytes += skb_out->len;
633 return skb_out->len;
634
635#undef OUTPUT
636}
637
638/*
639 * Update the "BSD Compress" dictionary on the receiver for
640 * incompressible data by pretending to compress the incoming data.
641 */
642static void bsd_incomp (void *state, struct sk_buff *skb_in,int proto)
643{
644 bsd_compress (state, skb_in, NULL, proto);
645}
646
647/*
648 * Decompress "BSD Compress".
649 */
650static int bsd_decompress (void *state, struct sk_buff *skb_in, struct sk_buff *skb_out,
651 struct isdn_ppp_resetparams *rsparm)
652{
653 struct bsd_db *db;
654 unsigned int max_ent;
655 unsigned long accm;
656 unsigned int bitno; /* 1st valid bit in accm */
657 unsigned int n_bits;
658 unsigned int tgtbitno; /* bitno when we have a code */
659 struct bsd_dict *dictp;
660 int seq;
661 unsigned int incode;
662 unsigned int oldcode;
663 unsigned int finchar;
664 unsigned char *p,*ibuf;
665 int ilen;
666 int codelen;
667 int extra;
668
669 db = (struct bsd_db *) state;
670 max_ent = db->max_ent;
671 accm = 0;
672 bitno = 32; /* 1st valid bit in accm */
673 n_bits = db->n_bits;
674 tgtbitno = 32 - n_bits; /* bitno when we have a code */
675
676 printk(KERN_DEBUG "bsd_decompress called\n");
677
678 if(!skb_in || !skb_out) {
679 printk(KERN_ERR "bsd_decompress called with NULL parameter\n");
680 return DECOMP_ERROR;
681 }
682
683 /*
684 * Get the sequence number.
685 */
686 if( (p = skb_pull(skb_in,2)) == NULL) {
687 return DECOMP_ERROR;
688 }
689 p-=2;
690 seq = (p[0] << 8) + p[1];
691 ilen = skb_in->len;
692 ibuf = skb_in->data;
693
694 /*
695 * Check the sequence number and give up if it differs from
696 * the value we're expecting.
697 */
698 if (seq != db->seqno) {
699 if (db->debug) {
700 printk(KERN_DEBUG "bsd_decomp%d: bad sequence # %d, expected %d\n",
701 db->unit, seq, db->seqno - 1);
702 }
703 return DECOMP_ERROR;
704 }
705
706 ++db->seqno;
707 db->bytes_out += ilen;
708
709 if(skb_tailroom(skb_out) > 0)
710 *(skb_put(skb_out,1)) = 0;
711 else
712 return DECOMP_ERR_NOMEM;
713
714 oldcode = CLEAR;
715
716 /*
717 * Keep the checkpoint correctly so that incompressible packets
718 * clear the dictionary at the proper times.
719 */
720
721 for (;;) {
722 if (ilen-- <= 0) {
723 db->in_count += (skb_out->len - 1); /* don't count the header */
724 break;
725 }
726
727 /*
728 * Accumulate bytes until we have a complete code.
729 * Then get the next code, relying on the 32-bit,
730 * unsigned accm to mask the result.
731 */
732
733 bitno -= 8;
734 accm |= *ibuf++ << bitno;
735 if (tgtbitno < bitno)
736 continue;
737
738 incode = accm >> tgtbitno;
739 accm <<= n_bits;
740 bitno += n_bits;
741
742 /*
743 * The dictionary must only be cleared at the end of a packet.
744 */
745
746 if (incode == CLEAR) {
747 if (ilen > 0) {
748 if (db->debug)
749 printk(KERN_DEBUG "bsd_decomp%d: bad CLEAR\n", db->unit);
750 return DECOMP_FATALERROR; /* probably a bug */
751 }
752 bsd_clear(db);
753 break;
754 }
755
756 if ((incode > max_ent + 2) || (incode > db->maxmaxcode)
757 || (incode > max_ent && oldcode == CLEAR)) {
758 if (db->debug) {
759 printk(KERN_DEBUG "bsd_decomp%d: bad code 0x%x oldcode=0x%x ",
760 db->unit, incode, oldcode);
761 printk(KERN_DEBUG "max_ent=0x%x skb->Len=%d seqno=%d\n",
762 max_ent, skb_out->len, db->seqno);
763 }
764 return DECOMP_FATALERROR; /* probably a bug */
765 }
766
767 /* Special case for KwKwK string. */
768 if (incode > max_ent) {
769 finchar = oldcode;
770 extra = 1;
771 } else {
772 finchar = incode;
773 extra = 0;
774 }
775
776 codelen = *(lens_ptr (db, finchar));
777 if( skb_tailroom(skb_out) < codelen + extra) {
778 if (db->debug) {
779 printk(KERN_DEBUG "bsd_decomp%d: ran out of mru\n", db->unit);
780#ifdef DEBUG
781 printk(KERN_DEBUG " len=%d, finchar=0x%x, codelen=%d,skblen=%d\n",
782 ilen, finchar, codelen, skb_out->len);
783#endif
784 }
785 return DECOMP_FATALERROR;
786 }
787
788 /*
789 * Decode this code and install it in the decompressed buffer.
790 */
791
792 p = skb_put(skb_out,codelen);
793 p += codelen;
794 while (finchar > LAST) {
795 struct bsd_dict *dictp2 = dict_ptr (db, finchar);
796
797 dictp = dict_ptr (db, dictp2->cptr);
798
799#ifdef DEBUG
800 if (--codelen <= 0 || dictp->codem1 != finchar-1) {
801 if (codelen <= 0) {
802 printk(KERN_ERR "bsd_decomp%d: fell off end of chain ", db->unit);
803 printk(KERN_ERR "0x%x at 0x%x by 0x%x, max_ent=0x%x\n", incode, finchar, dictp2->cptr, max_ent);
804 } else {
805 if (dictp->codem1 != finchar-1) {
806 printk(KERN_ERR "bsd_decomp%d: bad code chain 0x%x finchar=0x%x ",db->unit, incode, finchar);
807 printk(KERN_ERR "oldcode=0x%x cptr=0x%x codem1=0x%x\n", oldcode, dictp2->cptr, dictp->codem1);
808 }
809 }
810 return DECOMP_FATALERROR;
811 }
812#endif
813
814 {
815 u32 fcode = dictp->fcode;
816 *--p = (fcode >> 16) & 0xff;
817 finchar = fcode & 0xffff;
818 }
819 }
820 *--p = finchar;
821
822#ifdef DEBUG
823 if (--codelen != 0)
824 printk(KERN_ERR "bsd_decomp%d: short by %d after code 0x%x, max_ent=0x%x\n", db->unit, codelen, incode, max_ent);
825#endif
826
827 if (extra) /* the KwKwK case again */
828 *(skb_put(skb_out,1)) = finchar;
829
830 /*
831 * If not first code in a packet, and
832 * if not out of code space, then allocate a new code.
833 *
834 * Keep the hash table correct so it can be used
835 * with uncompressed packets.
836 */
837 if (oldcode != CLEAR && max_ent < db->maxmaxcode) {
838 struct bsd_dict *dictp2, *dictp3;
839 u16 *lens1, *lens2;
840 unsigned long fcode;
841 int hval, disp, indx;
842
843 fcode = BSD_KEY(oldcode,finchar);
844 hval = BSD_HASH(oldcode,finchar,db->hshift);
845 dictp = dict_ptr (db, hval);
846
847 /* look for a free hash table entry */
848 if (dictp->codem1 < max_ent) {
849 disp = (hval == 0) ? 1 : hval;
850 do {
851 hval += disp;
852 if (hval >= db->hsize)
853 hval -= db->hsize;
854 dictp = dict_ptr (db, hval);
855 } while (dictp->codem1 < max_ent);
856 }
857
858 /*
859 * Invalidate previous hash table entry
860 * assigned this code, and then take it over
861 */
862
863 dictp2 = dict_ptr (db, max_ent + 1);
864 indx = dictp2->cptr;
865 dictp3 = dict_ptr (db, indx);
866
867 if (dictp3->codem1 == max_ent)
868 dictp3->codem1 = BADCODEM1;
869
870 dictp2->cptr = hval;
871 dictp->codem1 = max_ent;
872 dictp->fcode = fcode;
873 db->max_ent = ++max_ent;
874
875 /* Update the length of this string. */
876 lens1 = lens_ptr (db, max_ent);
877 lens2 = lens_ptr (db, oldcode);
878 *lens1 = *lens2 + 1;
879
880 /* Expand code size if needed. */
881 if (max_ent >= MAXCODE(n_bits) && max_ent < db->maxmaxcode) {
882 db->n_bits = ++n_bits;
883 tgtbitno = 32-n_bits;
884 }
885 }
886 oldcode = incode;
887 }
888
889 ++db->comp_count;
890 ++db->uncomp_count;
891 db->comp_bytes += skb_in->len - BSD_OVHD;
892 db->uncomp_bytes += skb_out->len;
893
894 if (bsd_check(db)) {
895 if (db->debug)
896 printk(KERN_DEBUG "bsd_decomp%d: peer should have cleared dictionary on %d\n",
897 db->unit, db->seqno - 1);
898 }
899 return skb_out->len;
900}
901
902/*************************************************************
903 * Table of addresses for the BSD compression module
904 *************************************************************/
905
906static struct isdn_ppp_compressor ippp_bsd_compress = {
907 .owner = THIS_MODULE,
908 .num = CI_BSD_COMPRESS,
909 .alloc = bsd_alloc,
910 .free = bsd_free,
911 .init = bsd_init,
912 .reset = bsd_reset,
913 .compress = bsd_compress,
914 .decompress = bsd_decompress,
915 .incomp = bsd_incomp,
916 .stat = bsd_stats,
917};
918
919/*************************************************************
920 * Module support routines
921 *************************************************************/
922
923static int __init isdn_bsdcomp_init(void)
924{
925 int answer = isdn_ppp_register_compressor (&ippp_bsd_compress);
926 if (answer == 0)
927 printk (KERN_INFO "PPP BSD Compression module registered\n");
928 return answer;
929}
930
931static void __exit isdn_bsdcomp_exit(void)
932{
933 isdn_ppp_unregister_compressor (&ippp_bsd_compress);
934}
935
936module_init(isdn_bsdcomp_init);
937module_exit(isdn_bsdcomp_exit);
diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c
new file mode 100644
index 000000000000..c406df6f268a
--- /dev/null
+++ b/drivers/isdn/i4l/isdn_common.c
@@ -0,0 +1,2253 @@
1/* $Id: isdn_common.c,v 1.1.2.3 2004/02/10 01:07:13 keil Exp $
2 *
3 * Linux ISDN subsystem, common used functions (linklevel).
4 *
5 * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de)
6 * Copyright 1995,96 Thinking Objects Software GmbH Wuerzburg
7 * Copyright 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.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.
11 *
12 */
13
14#include <linux/config.h>
15#include <linux/module.h>
16#include <linux/init.h>
17#include <linux/version.h>
18#include <linux/poll.h>
19#include <linux/vmalloc.h>
20#include <linux/isdn.h>
21#include <linux/smp_lock.h>
22#include "isdn_common.h"
23#include "isdn_tty.h"
24#include "isdn_net.h"
25#include "isdn_ppp.h"
26#ifdef CONFIG_ISDN_AUDIO
27#include "isdn_audio.h"
28#endif
29#ifdef CONFIG_ISDN_DIVERSION_MODULE
30#define CONFIG_ISDN_DIVERSION
31#endif
32#ifdef CONFIG_ISDN_DIVERSION
33#include <linux/isdn_divertif.h>
34#endif /* CONFIG_ISDN_DIVERSION */
35#include "isdn_v110.h"
36
37/* Debugflags */
38#undef ISDN_DEBUG_STATCALLB
39
40MODULE_DESCRIPTION("ISDN4Linux: link layer");
41MODULE_AUTHOR("Fritz Elfert");
42MODULE_LICENSE("GPL");
43
44isdn_dev *dev;
45
46static char *isdn_revision = "$Revision: 1.1.2.3 $";
47
48extern char *isdn_net_revision;
49extern char *isdn_tty_revision;
50#ifdef CONFIG_ISDN_PPP
51extern char *isdn_ppp_revision;
52#else
53static char *isdn_ppp_revision = ": none $";
54#endif
55#ifdef CONFIG_ISDN_AUDIO
56extern char *isdn_audio_revision;
57#else
58static char *isdn_audio_revision = ": none $";
59#endif
60extern char *isdn_v110_revision;
61
62#ifdef CONFIG_ISDN_DIVERSION
63static isdn_divert_if *divert_if; /* = NULL */
64#endif /* CONFIG_ISDN_DIVERSION */
65
66
67static int isdn_writebuf_stub(int, int, const u_char __user *, int);
68static void set_global_features(void);
69static int isdn_wildmat(char *s, char *p);
70
71
72static inline void
73isdn_lock_driver(isdn_driver_t *drv)
74{
75 try_module_get(drv->interface->owner);
76 drv->locks++;
77}
78
79void
80isdn_lock_drivers(void)
81{
82 int i;
83
84 for (i = 0; i < ISDN_MAX_DRIVERS; i++) {
85 if (!dev->drv[i])
86 continue;
87 isdn_lock_driver(dev->drv[i]);
88 }
89}
90
91static inline void
92isdn_unlock_driver(isdn_driver_t *drv)
93{
94 if (drv->locks > 0) {
95 drv->locks--;
96 module_put(drv->interface->owner);
97 }
98}
99
100void
101isdn_unlock_drivers(void)
102{
103 int i;
104
105 for (i = 0; i < ISDN_MAX_DRIVERS; i++) {
106 if (!dev->drv[i])
107 continue;
108 isdn_unlock_driver(dev->drv[i]);
109 }
110}
111
112#if defined(ISDN_DEBUG_NET_DUMP) || defined(ISDN_DEBUG_MODEM_DUMP)
113void
114isdn_dumppkt(char *s, u_char * p, int len, int dumplen)
115{
116 int dumpc;
117
118 printk(KERN_DEBUG "%s(%d) ", s, len);
119 for (dumpc = 0; (dumpc < dumplen) && (len); len--, dumpc++)
120 printk(" %02x", *p++);
121 printk("\n");
122}
123#endif
124
125/*
126 * I picked the pattern-matching-functions from an old GNU-tar version (1.10)
127 * It was originally written and put to PD by rs@mirror.TMC.COM (Rich Salz)
128 */
129static int
130isdn_star(char *s, char *p)
131{
132 while (isdn_wildmat(s, p)) {
133 if (*++s == '\0')
134 return (2);
135 }
136 return (0);
137}
138
139/*
140 * Shell-type Pattern-matching for incoming caller-Ids
141 * This function gets a string in s and checks, if it matches the pattern
142 * given in p.
143 *
144 * Return:
145 * 0 = match.
146 * 1 = no match.
147 * 2 = no match. Would eventually match, if s would be longer.
148 *
149 * Possible Patterns:
150 *
151 * '?' matches one character
152 * '*' matches zero or more characters
153 * [xyz] matches the set of characters in brackets.
154 * [^xyz] matches any single character not in the set of characters
155 */
156
157static int
158isdn_wildmat(char *s, char *p)
159{
160 register int last;
161 register int matched;
162 register int reverse;
163 register int nostar = 1;
164
165 if (!(*s) && !(*p))
166 return(1);
167 for (; *p; s++, p++)
168 switch (*p) {
169 case '\\':
170 /*
171 * Literal match with following character,
172 * fall through.
173 */
174 p++;
175 default:
176 if (*s != *p)
177 return (*s == '\0')?2:1;
178 continue;
179 case '?':
180 /* Match anything. */
181 if (*s == '\0')
182 return (2);
183 continue;
184 case '*':
185 nostar = 0;
186 /* Trailing star matches everything. */
187 return (*++p ? isdn_star(s, p) : 0);
188 case '[':
189 /* [^....] means inverse character class. */
190 if ((reverse = (p[1] == '^')))
191 p++;
192 for (last = 0, matched = 0; *++p && (*p != ']'); last = *p)
193 /* This next line requires a good C compiler. */
194 if (*p == '-' ? *s <= *++p && *s >= last : *s == *p)
195 matched = 1;
196 if (matched == reverse)
197 return (1);
198 continue;
199 }
200 return (*s == '\0')?0:nostar;
201}
202
203int isdn_msncmp( const char * msn1, const char * msn2 )
204{
205 char TmpMsn1[ ISDN_MSNLEN ];
206 char TmpMsn2[ ISDN_MSNLEN ];
207 char *p;
208
209 for ( p = TmpMsn1; *msn1 && *msn1 != ':'; ) // Strip off a SPID
210 *p++ = *msn1++;
211 *p = '\0';
212
213 for ( p = TmpMsn2; *msn2 && *msn2 != ':'; ) // Strip off a SPID
214 *p++ = *msn2++;
215 *p = '\0';
216
217 return isdn_wildmat( TmpMsn1, TmpMsn2 );
218}
219
220int
221isdn_dc2minor(int di, int ch)
222{
223 int i;
224 for (i = 0; i < ISDN_MAX_CHANNELS; i++)
225 if (dev->chanmap[i] == ch && dev->drvmap[i] == di)
226 return i;
227 return -1;
228}
229
230static int isdn_timer_cnt1 = 0;
231static int isdn_timer_cnt2 = 0;
232static int isdn_timer_cnt3 = 0;
233
234static void
235isdn_timer_funct(ulong dummy)
236{
237 int tf = dev->tflags;
238 if (tf & ISDN_TIMER_FAST) {
239 if (tf & ISDN_TIMER_MODEMREAD)
240 isdn_tty_readmodem();
241 if (tf & ISDN_TIMER_MODEMPLUS)
242 isdn_tty_modem_escape();
243 if (tf & ISDN_TIMER_MODEMXMIT)
244 isdn_tty_modem_xmit();
245 }
246 if (tf & ISDN_TIMER_SLOW) {
247 if (++isdn_timer_cnt1 >= ISDN_TIMER_02SEC) {
248 isdn_timer_cnt1 = 0;
249 if (tf & ISDN_TIMER_NETDIAL)
250 isdn_net_dial();
251 }
252 if (++isdn_timer_cnt2 >= ISDN_TIMER_1SEC) {
253 isdn_timer_cnt2 = 0;
254 if (tf & ISDN_TIMER_NETHANGUP)
255 isdn_net_autohup();
256 if (++isdn_timer_cnt3 >= ISDN_TIMER_RINGING) {
257 isdn_timer_cnt3 = 0;
258 if (tf & ISDN_TIMER_MODEMRING)
259 isdn_tty_modem_ring();
260 }
261 if (tf & ISDN_TIMER_CARRIER)
262 isdn_tty_carrier_timeout();
263 }
264 }
265 if (tf)
266 mod_timer(&dev->timer, jiffies+ISDN_TIMER_RES);
267}
268
269void
270isdn_timer_ctrl(int tf, int onoff)
271{
272 unsigned long flags;
273 int old_tflags;
274
275 spin_lock_irqsave(&dev->timerlock, flags);
276 if ((tf & ISDN_TIMER_SLOW) && (!(dev->tflags & ISDN_TIMER_SLOW))) {
277 /* If the slow-timer wasn't activated until now */
278 isdn_timer_cnt1 = 0;
279 isdn_timer_cnt2 = 0;
280 }
281 old_tflags = dev->tflags;
282 if (onoff)
283 dev->tflags |= tf;
284 else
285 dev->tflags &= ~tf;
286 if (dev->tflags && !old_tflags)
287 mod_timer(&dev->timer, jiffies+ISDN_TIMER_RES);
288 spin_unlock_irqrestore(&dev->timerlock, flags);
289}
290
291/*
292 * Receive a packet from B-Channel. (Called from low-level-module)
293 */
294static void
295isdn_receive_skb_callback(int di, int channel, struct sk_buff *skb)
296{
297 int i;
298
299 if ((i = isdn_dc2minor(di, channel)) == -1) {
300 dev_kfree_skb(skb);
301 return;
302 }
303 /* Update statistics */
304 dev->ibytes[i] += skb->len;
305
306 /* First, try to deliver data to network-device */
307 if (isdn_net_rcv_skb(i, skb))
308 return;
309
310 /* V.110 handling
311 * makes sense for async streams only, so it is
312 * called after possible net-device delivery.
313 */
314 if (dev->v110[i]) {
315 atomic_inc(&dev->v110use[i]);
316 skb = isdn_v110_decode(dev->v110[i], skb);
317 atomic_dec(&dev->v110use[i]);
318 if (!skb)
319 return;
320 }
321
322 /* No network-device found, deliver to tty or raw-channel */
323 if (skb->len) {
324 if (isdn_tty_rcv_skb(i, di, channel, skb))
325 return;
326 wake_up_interruptible(&dev->drv[di]->rcv_waitq[channel]);
327 } else
328 dev_kfree_skb(skb);
329}
330
331/*
332 * Intercept command from Linklevel to Lowlevel.
333 * If layer 2 protocol is V.110 and this is not supported by current
334 * lowlevel-driver, use driver's transparent mode and handle V.110 in
335 * linklevel instead.
336 */
337int
338isdn_command(isdn_ctrl *cmd)
339{
340 if (cmd->driver == -1) {
341 printk(KERN_WARNING "isdn_command command(%x) driver -1\n", cmd->command);
342 return(1);
343 }
344 if (cmd->command == ISDN_CMD_SETL2) {
345 int idx = isdn_dc2minor(cmd->driver, cmd->arg & 255);
346 unsigned long l2prot = (cmd->arg >> 8) & 255;
347 unsigned long features = (dev->drv[cmd->driver]->interface->features
348 >> ISDN_FEATURE_L2_SHIFT) &
349 ISDN_FEATURE_L2_MASK;
350 unsigned long l2_feature = (1 << l2prot);
351
352 switch (l2prot) {
353 case ISDN_PROTO_L2_V11096:
354 case ISDN_PROTO_L2_V11019:
355 case ISDN_PROTO_L2_V11038:
356 /* If V.110 requested, but not supported by
357 * HL-driver, set emulator-flag and change
358 * Layer-2 to transparent
359 */
360 if (!(features & l2_feature)) {
361 dev->v110emu[idx] = l2prot;
362 cmd->arg = (cmd->arg & 255) |
363 (ISDN_PROTO_L2_TRANS << 8);
364 } else
365 dev->v110emu[idx] = 0;
366 }
367 }
368 return dev->drv[cmd->driver]->interface->command(cmd);
369}
370
371void
372isdn_all_eaz(int di, int ch)
373{
374 isdn_ctrl cmd;
375
376 if (di < 0)
377 return;
378 cmd.driver = di;
379 cmd.arg = ch;
380 cmd.command = ISDN_CMD_SETEAZ;
381 cmd.parm.num[0] = '\0';
382 isdn_command(&cmd);
383}
384
385/*
386 * Begin of a CAPI like LL<->HL interface, currently used only for
387 * supplementary service (CAPI 2.0 part III)
388 */
389#include <linux/isdn/capicmd.h>
390
391int
392isdn_capi_rec_hl_msg(capi_msg *cm) {
393
394 int di;
395 int ch;
396
397 di = (cm->adr.Controller & 0x7f) -1;
398 ch = isdn_dc2minor(di, (cm->adr.Controller>>8)& 0x7f);
399 switch(cm->Command) {
400 case CAPI_FACILITY:
401 /* in the moment only handled in tty */
402 return(isdn_tty_capi_facility(cm));
403 default:
404 return(-1);
405 }
406}
407
408static int
409isdn_status_callback(isdn_ctrl * c)
410{
411 int di;
412 u_long flags;
413 int i;
414 int r;
415 int retval = 0;
416 isdn_ctrl cmd;
417 isdn_net_dev *p;
418
419 di = c->driver;
420 i = isdn_dc2minor(di, c->arg);
421 switch (c->command) {
422 case ISDN_STAT_BSENT:
423 if (i < 0)
424 return -1;
425 if (dev->global_flags & ISDN_GLOBAL_STOPPED)
426 return 0;
427 if (isdn_net_stat_callback(i, c))
428 return 0;
429 if (isdn_v110_stat_callback(i, c))
430 return 0;
431 if (isdn_tty_stat_callback(i, c))
432 return 0;
433 wake_up_interruptible(&dev->drv[di]->snd_waitq[c->arg]);
434 break;
435 case ISDN_STAT_STAVAIL:
436 dev->drv[di]->stavail += c->arg;
437 wake_up_interruptible(&dev->drv[di]->st_waitq);
438 break;
439 case ISDN_STAT_RUN:
440 dev->drv[di]->flags |= DRV_FLAG_RUNNING;
441 for (i = 0; i < ISDN_MAX_CHANNELS; i++)
442 if (dev->drvmap[i] == di)
443 isdn_all_eaz(di, dev->chanmap[i]);
444 set_global_features();
445 break;
446 case ISDN_STAT_STOP:
447 dev->drv[di]->flags &= ~DRV_FLAG_RUNNING;
448 break;
449 case ISDN_STAT_ICALL:
450 if (i < 0)
451 return -1;
452#ifdef ISDN_DEBUG_STATCALLB
453 printk(KERN_DEBUG "ICALL (net): %d %ld %s\n", di, c->arg, c->parm.num);
454#endif
455 if (dev->global_flags & ISDN_GLOBAL_STOPPED) {
456 cmd.driver = di;
457 cmd.arg = c->arg;
458 cmd.command = ISDN_CMD_HANGUP;
459 isdn_command(&cmd);
460 return 0;
461 }
462 /* Try to find a network-interface which will accept incoming call */
463 r = ((c->command == ISDN_STAT_ICALLW) ? 0 : isdn_net_find_icall(di, c->arg, i, &c->parm.setup));
464 switch (r) {
465 case 0:
466 /* No network-device replies.
467 * Try ttyI's.
468 * These return 0 on no match, 1 on match and
469 * 3 on eventually match, if CID is longer.
470 */
471 if (c->command == ISDN_STAT_ICALL)
472 if ((retval = isdn_tty_find_icall(di, c->arg, &c->parm.setup))) return(retval);
473#ifdef CONFIG_ISDN_DIVERSION
474 if (divert_if)
475 if ((retval = divert_if->stat_callback(c)))
476 return(retval); /* processed */
477#endif /* CONFIG_ISDN_DIVERSION */
478 if ((!retval) && (dev->drv[di]->flags & DRV_FLAG_REJBUS)) {
479 /* No tty responding */
480 cmd.driver = di;
481 cmd.arg = c->arg;
482 cmd.command = ISDN_CMD_HANGUP;
483 isdn_command(&cmd);
484 retval = 2;
485 }
486 break;
487 case 1:
488 /* Schedule connection-setup */
489 isdn_net_dial();
490 cmd.driver = di;
491 cmd.arg = c->arg;
492 cmd.command = ISDN_CMD_ACCEPTD;
493 for ( p = dev->netdev; p; p = p->next )
494 if ( p->local->isdn_channel == cmd.arg )
495 {
496 strcpy( cmd.parm.setup.eazmsn, p->local->msn );
497 isdn_command(&cmd);
498 retval = 1;
499 break;
500 }
501 break;
502
503 case 2: /* For calling back, first reject incoming call ... */
504 case 3: /* Interface found, but down, reject call actively */
505 retval = 2;
506 printk(KERN_INFO "isdn: Rejecting Call\n");
507 cmd.driver = di;
508 cmd.arg = c->arg;
509 cmd.command = ISDN_CMD_HANGUP;
510 isdn_command(&cmd);
511 if (r == 3)
512 break;
513 /* Fall through */
514 case 4:
515 /* ... then start callback. */
516 isdn_net_dial();
517 break;
518 case 5:
519 /* Number would eventually match, if longer */
520 retval = 3;
521 break;
522 }
523#ifdef ISDN_DEBUG_STATCALLB
524 printk(KERN_DEBUG "ICALL: ret=%d\n", retval);
525#endif
526 return retval;
527 break;
528 case ISDN_STAT_CINF:
529 if (i < 0)
530 return -1;
531#ifdef ISDN_DEBUG_STATCALLB
532 printk(KERN_DEBUG "CINF: %ld %s\n", c->arg, c->parm.num);
533#endif
534 if (dev->global_flags & ISDN_GLOBAL_STOPPED)
535 return 0;
536 if (strcmp(c->parm.num, "0"))
537 isdn_net_stat_callback(i, c);
538 isdn_tty_stat_callback(i, c);
539 break;
540 case ISDN_STAT_CAUSE:
541#ifdef ISDN_DEBUG_STATCALLB
542 printk(KERN_DEBUG "CAUSE: %ld %s\n", c->arg, c->parm.num);
543#endif
544 printk(KERN_INFO "isdn: %s,ch%ld cause: %s\n",
545 dev->drvid[di], c->arg, c->parm.num);
546 isdn_tty_stat_callback(i, c);
547#ifdef CONFIG_ISDN_DIVERSION
548 if (divert_if)
549 divert_if->stat_callback(c);
550#endif /* CONFIG_ISDN_DIVERSION */
551 break;
552 case ISDN_STAT_DISPLAY:
553#ifdef ISDN_DEBUG_STATCALLB
554 printk(KERN_DEBUG "DISPLAY: %ld %s\n", c->arg, c->parm.display);
555#endif
556 isdn_tty_stat_callback(i, c);
557#ifdef CONFIG_ISDN_DIVERSION
558 if (divert_if)
559 divert_if->stat_callback(c);
560#endif /* CONFIG_ISDN_DIVERSION */
561 break;
562 case ISDN_STAT_DCONN:
563 if (i < 0)
564 return -1;
565#ifdef ISDN_DEBUG_STATCALLB
566 printk(KERN_DEBUG "DCONN: %ld\n", c->arg);
567#endif
568 if (dev->global_flags & ISDN_GLOBAL_STOPPED)
569 return 0;
570 /* Find any net-device, waiting for D-channel setup */
571 if (isdn_net_stat_callback(i, c))
572 break;
573 isdn_v110_stat_callback(i, c);
574 /* Find any ttyI, waiting for D-channel setup */
575 if (isdn_tty_stat_callback(i, c)) {
576 cmd.driver = di;
577 cmd.arg = c->arg;
578 cmd.command = ISDN_CMD_ACCEPTB;
579 isdn_command(&cmd);
580 break;
581 }
582 break;
583 case ISDN_STAT_DHUP:
584 if (i < 0)
585 return -1;
586#ifdef ISDN_DEBUG_STATCALLB
587 printk(KERN_DEBUG "DHUP: %ld\n", c->arg);
588#endif
589 if (dev->global_flags & ISDN_GLOBAL_STOPPED)
590 return 0;
591 dev->drv[di]->online &= ~(1 << (c->arg));
592 isdn_info_update();
593 /* Signal hangup to network-devices */
594 if (isdn_net_stat_callback(i, c))
595 break;
596 isdn_v110_stat_callback(i, c);
597 if (isdn_tty_stat_callback(i, c))
598 break;
599#ifdef CONFIG_ISDN_DIVERSION
600 if (divert_if)
601 divert_if->stat_callback(c);
602#endif /* CONFIG_ISDN_DIVERSION */
603 break;
604 break;
605 case ISDN_STAT_BCONN:
606 if (i < 0)
607 return -1;
608#ifdef ISDN_DEBUG_STATCALLB
609 printk(KERN_DEBUG "BCONN: %ld\n", c->arg);
610#endif
611 /* Signal B-channel-connect to network-devices */
612 if (dev->global_flags & ISDN_GLOBAL_STOPPED)
613 return 0;
614 dev->drv[di]->online |= (1 << (c->arg));
615 isdn_info_update();
616 if (isdn_net_stat_callback(i, c))
617 break;
618 isdn_v110_stat_callback(i, c);
619 if (isdn_tty_stat_callback(i, c))
620 break;
621 break;
622 case ISDN_STAT_BHUP:
623 if (i < 0)
624 return -1;
625#ifdef ISDN_DEBUG_STATCALLB
626 printk(KERN_DEBUG "BHUP: %ld\n", c->arg);
627#endif
628 if (dev->global_flags & ISDN_GLOBAL_STOPPED)
629 return 0;
630 dev->drv[di]->online &= ~(1 << (c->arg));
631 isdn_info_update();
632#ifdef CONFIG_ISDN_X25
633 /* Signal hangup to network-devices */
634 if (isdn_net_stat_callback(i, c))
635 break;
636#endif
637 isdn_v110_stat_callback(i, c);
638 if (isdn_tty_stat_callback(i, c))
639 break;
640 break;
641 case ISDN_STAT_NODCH:
642 if (i < 0)
643 return -1;
644#ifdef ISDN_DEBUG_STATCALLB
645 printk(KERN_DEBUG "NODCH: %ld\n", c->arg);
646#endif
647 if (dev->global_flags & ISDN_GLOBAL_STOPPED)
648 return 0;
649 if (isdn_net_stat_callback(i, c))
650 break;
651 if (isdn_tty_stat_callback(i, c))
652 break;
653 break;
654 case ISDN_STAT_ADDCH:
655 spin_lock_irqsave(&dev->lock, flags);
656 if (isdn_add_channels(dev->drv[di], di, c->arg, 1)) {
657 spin_unlock_irqrestore(&dev->lock, flags);
658 return -1;
659 }
660 spin_unlock_irqrestore(&dev->lock, flags);
661 isdn_info_update();
662 break;
663 case ISDN_STAT_DISCH:
664 spin_lock_irqsave(&dev->lock, flags);
665 for (i = 0; i < ISDN_MAX_CHANNELS; i++)
666 if ((dev->drvmap[i] == di) &&
667 (dev->chanmap[i] == c->arg)) {
668 if (c->parm.num[0])
669 dev->usage[i] &= ~ISDN_USAGE_DISABLED;
670 else
671 if (USG_NONE(dev->usage[i])) {
672 dev->usage[i] |= ISDN_USAGE_DISABLED;
673 }
674 else
675 retval = -1;
676 break;
677 }
678 spin_unlock_irqrestore(&dev->lock, flags);
679 isdn_info_update();
680 break;
681 case ISDN_STAT_UNLOAD:
682 while (dev->drv[di]->locks > 0) {
683 isdn_unlock_driver(dev->drv[di]);
684 }
685 spin_lock_irqsave(&dev->lock, flags);
686 isdn_tty_stat_callback(i, c);
687 for (i = 0; i < ISDN_MAX_CHANNELS; i++)
688 if (dev->drvmap[i] == di) {
689 dev->drvmap[i] = -1;
690 dev->chanmap[i] = -1;
691 dev->usage[i] &= ~ISDN_USAGE_DISABLED;
692 }
693 dev->drivers--;
694 dev->channels -= dev->drv[di]->channels;
695 kfree(dev->drv[di]->rcverr);
696 kfree(dev->drv[di]->rcvcount);
697 for (i = 0; i < dev->drv[di]->channels; i++)
698 skb_queue_purge(&dev->drv[di]->rpqueue[i]);
699 kfree(dev->drv[di]->rpqueue);
700 kfree(dev->drv[di]->rcv_waitq);
701 kfree(dev->drv[di]);
702 dev->drv[di] = NULL;
703 dev->drvid[di][0] = '\0';
704 isdn_info_update();
705 set_global_features();
706 spin_unlock_irqrestore(&dev->lock, flags);
707 return 0;
708 case ISDN_STAT_L1ERR:
709 break;
710 case CAPI_PUT_MESSAGE:
711 return(isdn_capi_rec_hl_msg(&c->parm.cmsg));
712#ifdef CONFIG_ISDN_TTY_FAX
713 case ISDN_STAT_FAXIND:
714 isdn_tty_stat_callback(i, c);
715 break;
716#endif
717#ifdef CONFIG_ISDN_AUDIO
718 case ISDN_STAT_AUDIO:
719 isdn_tty_stat_callback(i, c);
720 break;
721#endif
722#ifdef CONFIG_ISDN_DIVERSION
723 case ISDN_STAT_PROT:
724 case ISDN_STAT_REDIR:
725 if (divert_if)
726 return(divert_if->stat_callback(c));
727#endif /* CONFIG_ISDN_DIVERSION */
728 default:
729 return -1;
730 }
731 return 0;
732}
733
734/*
735 * Get integer from char-pointer, set pointer to end of number
736 */
737int
738isdn_getnum(char **p)
739{
740 int v = -1;
741
742 while (*p[0] >= '0' && *p[0] <= '9')
743 v = ((v < 0) ? 0 : (v * 10)) + (int) ((*p[0]++) - '0');
744 return v;
745}
746
747#define DLE 0x10
748
749/*
750 * isdn_readbchan() tries to get data from the read-queue.
751 * It MUST be called with interrupts off.
752 *
753 * Be aware that this is not an atomic operation when sleep != 0, even though
754 * interrupts are turned off! Well, like that we are currently only called
755 * on behalf of a read system call on raw device files (which are documented
756 * to be dangerous and for for debugging purpose only). The inode semaphore
757 * takes care that this is not called for the same minor device number while
758 * we are sleeping, but access is not serialized against simultaneous read()
759 * from the corresponding ttyI device. Can other ugly events, like changes
760 * of the mapping (di,ch)<->minor, happen during the sleep? --he
761 */
762int
763isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, wait_queue_head_t *sleep)
764{
765 int count;
766 int count_pull;
767 int count_put;
768 int dflag;
769 struct sk_buff *skb;
770 u_char *cp;
771
772 if (!dev->drv[di])
773 return 0;
774 if (skb_queue_empty(&dev->drv[di]->rpqueue[channel])) {
775 if (sleep)
776 interruptible_sleep_on(sleep);
777 else
778 return 0;
779 }
780 if (len > dev->drv[di]->rcvcount[channel])
781 len = dev->drv[di]->rcvcount[channel];
782 cp = buf;
783 count = 0;
784 while (len) {
785 if (!(skb = skb_peek(&dev->drv[di]->rpqueue[channel])))
786 break;
787#ifdef CONFIG_ISDN_AUDIO
788 if (ISDN_AUDIO_SKB_LOCK(skb))
789 break;
790 ISDN_AUDIO_SKB_LOCK(skb) = 1;
791 if ((ISDN_AUDIO_SKB_DLECOUNT(skb)) || (dev->drv[di]->DLEflag & (1 << channel))) {
792 char *p = skb->data;
793 unsigned long DLEmask = (1 << channel);
794
795 dflag = 0;
796 count_pull = count_put = 0;
797 while ((count_pull < skb->len) && (len > 0)) {
798 len--;
799 if (dev->drv[di]->DLEflag & DLEmask) {
800 *cp++ = DLE;
801 dev->drv[di]->DLEflag &= ~DLEmask;
802 } else {
803 *cp++ = *p;
804 if (*p == DLE) {
805 dev->drv[di]->DLEflag |= DLEmask;
806 (ISDN_AUDIO_SKB_DLECOUNT(skb))--;
807 }
808 p++;
809 count_pull++;
810 }
811 count_put++;
812 }
813 if (count_pull >= skb->len)
814 dflag = 1;
815 } else {
816#endif
817 /* No DLE's in buff, so simply copy it */
818 dflag = 1;
819 if ((count_pull = skb->len) > len) {
820 count_pull = len;
821 dflag = 0;
822 }
823 count_put = count_pull;
824 memcpy(cp, skb->data, count_put);
825 cp += count_put;
826 len -= count_put;
827#ifdef CONFIG_ISDN_AUDIO
828 }
829#endif
830 count += count_put;
831 if (fp) {
832 memset(fp, 0, count_put);
833 fp += count_put;
834 }
835 if (dflag) {
836 /* We got all the data in this buff.
837 * Now we can dequeue it.
838 */
839 if (fp)
840 *(fp - 1) = 0xff;
841#ifdef CONFIG_ISDN_AUDIO
842 ISDN_AUDIO_SKB_LOCK(skb) = 0;
843#endif
844 skb = skb_dequeue(&dev->drv[di]->rpqueue[channel]);
845 dev_kfree_skb(skb);
846 } else {
847 /* Not yet emptied this buff, so it
848 * must stay in the queue, for further calls
849 * but we pull off the data we got until now.
850 */
851 skb_pull(skb, count_pull);
852#ifdef CONFIG_ISDN_AUDIO
853 ISDN_AUDIO_SKB_LOCK(skb) = 0;
854#endif
855 }
856 dev->drv[di]->rcvcount[channel] -= count_put;
857 }
858 return count;
859}
860
861static __inline int
862isdn_minor2drv(int minor)
863{
864 return (dev->drvmap[minor]);
865}
866
867static __inline int
868isdn_minor2chan(int minor)
869{
870 return (dev->chanmap[minor]);
871}
872
873static char *
874isdn_statstr(void)
875{
876 static char istatbuf[2048];
877 char *p;
878 int i;
879
880 sprintf(istatbuf, "idmap:\t");
881 p = istatbuf + strlen(istatbuf);
882 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
883 sprintf(p, "%s ", (dev->drvmap[i] < 0) ? "-" : dev->drvid[dev->drvmap[i]]);
884 p = istatbuf + strlen(istatbuf);
885 }
886 sprintf(p, "\nchmap:\t");
887 p = istatbuf + strlen(istatbuf);
888 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
889 sprintf(p, "%d ", dev->chanmap[i]);
890 p = istatbuf + strlen(istatbuf);
891 }
892 sprintf(p, "\ndrmap:\t");
893 p = istatbuf + strlen(istatbuf);
894 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
895 sprintf(p, "%d ", dev->drvmap[i]);
896 p = istatbuf + strlen(istatbuf);
897 }
898 sprintf(p, "\nusage:\t");
899 p = istatbuf + strlen(istatbuf);
900 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
901 sprintf(p, "%d ", dev->usage[i]);
902 p = istatbuf + strlen(istatbuf);
903 }
904 sprintf(p, "\nflags:\t");
905 p = istatbuf + strlen(istatbuf);
906 for (i = 0; i < ISDN_MAX_DRIVERS; i++) {
907 if (dev->drv[i]) {
908 sprintf(p, "%ld ", dev->drv[i]->online);
909 p = istatbuf + strlen(istatbuf);
910 } else {
911 sprintf(p, "? ");
912 p = istatbuf + strlen(istatbuf);
913 }
914 }
915 sprintf(p, "\nphone:\t");
916 p = istatbuf + strlen(istatbuf);
917 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
918 sprintf(p, "%s ", dev->num[i]);
919 p = istatbuf + strlen(istatbuf);
920 }
921 sprintf(p, "\n");
922 return istatbuf;
923}
924
925/* Module interface-code */
926
927void
928isdn_info_update(void)
929{
930 infostruct *p = dev->infochain;
931
932 while (p) {
933 *(p->private) = 1;
934 p = (infostruct *) p->next;
935 }
936 wake_up_interruptible(&(dev->info_waitq));
937}
938
939static ssize_t
940isdn_read(struct file *file, char __user *buf, size_t count, loff_t * off)
941{
942 uint minor = MINOR(file->f_dentry->d_inode->i_rdev);
943 int len = 0;
944 int drvidx;
945 int chidx;
946 int retval;
947 char *p;
948
949 lock_kernel();
950 if (minor == ISDN_MINOR_STATUS) {
951 if (!file->private_data) {
952 if (file->f_flags & O_NONBLOCK) {
953 retval = -EAGAIN;
954 goto out;
955 }
956 interruptible_sleep_on(&(dev->info_waitq));
957 }
958 p = isdn_statstr();
959 file->private_data = NULL;
960 if ((len = strlen(p)) <= count) {
961 if (copy_to_user(buf, p, len)) {
962 retval = -EFAULT;
963 goto out;
964 }
965 *off += len;
966 retval = len;
967 goto out;
968 }
969 retval = 0;
970 goto out;
971 }
972 if (!dev->drivers) {
973 retval = -ENODEV;
974 goto out;
975 }
976 if (minor <= ISDN_MINOR_BMAX) {
977 printk(KERN_WARNING "isdn_read minor %d obsolete!\n", minor);
978 drvidx = isdn_minor2drv(minor);
979 if (drvidx < 0) {
980 retval = -ENODEV;
981 goto out;
982 }
983 if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING)) {
984 retval = -ENODEV;
985 goto out;
986 }
987 chidx = isdn_minor2chan(minor);
988 if (!(p = kmalloc(count, GFP_KERNEL))) {
989 retval = -ENOMEM;
990 goto out;
991 }
992 len = isdn_readbchan(drvidx, chidx, p, NULL, count,
993 &dev->drv[drvidx]->rcv_waitq[chidx]);
994 *off += len;
995 if (copy_to_user(buf,p,len))
996 len = -EFAULT;
997 kfree(p);
998 retval = len;
999 goto out;
1000 }
1001 if (minor <= ISDN_MINOR_CTRLMAX) {
1002 drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
1003 if (drvidx < 0) {
1004 retval = -ENODEV;
1005 goto out;
1006 }
1007 if (!dev->drv[drvidx]->stavail) {
1008 if (file->f_flags & O_NONBLOCK) {
1009 retval = -EAGAIN;
1010 goto out;
1011 }
1012 interruptible_sleep_on(&(dev->drv[drvidx]->st_waitq));
1013 }
1014 if (dev->drv[drvidx]->interface->readstat) {
1015 if (count > dev->drv[drvidx]->stavail)
1016 count = dev->drv[drvidx]->stavail;
1017 len = dev->drv[drvidx]->interface->
1018 readstat(buf, count, drvidx,
1019 isdn_minor2chan(minor));
1020 } else {
1021 len = 0;
1022 }
1023 if (len)
1024 dev->drv[drvidx]->stavail -= len;
1025 else
1026 dev->drv[drvidx]->stavail = 0;
1027 *off += len;
1028 retval = len;
1029 goto out;
1030 }
1031#ifdef CONFIG_ISDN_PPP
1032 if (minor <= ISDN_MINOR_PPPMAX) {
1033 retval = isdn_ppp_read(minor - ISDN_MINOR_PPP, file, buf, count);
1034 goto out;
1035 }
1036#endif
1037 retval = -ENODEV;
1038 out:
1039 unlock_kernel();
1040 return retval;
1041}
1042
1043static ssize_t
1044isdn_write(struct file *file, const char __user *buf, size_t count, loff_t * off)
1045{
1046 uint minor = MINOR(file->f_dentry->d_inode->i_rdev);
1047 int drvidx;
1048 int chidx;
1049 int retval;
1050
1051 if (minor == ISDN_MINOR_STATUS)
1052 return -EPERM;
1053 if (!dev->drivers)
1054 return -ENODEV;
1055
1056 lock_kernel();
1057 if (minor <= ISDN_MINOR_BMAX) {
1058 printk(KERN_WARNING "isdn_write minor %d obsolete!\n", minor);
1059 drvidx = isdn_minor2drv(minor);
1060 if (drvidx < 0) {
1061 retval = -ENODEV;
1062 goto out;
1063 }
1064 if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING)) {
1065 retval = -ENODEV;
1066 goto out;
1067 }
1068 chidx = isdn_minor2chan(minor);
1069 while (isdn_writebuf_stub(drvidx, chidx, buf, count) != count)
1070 interruptible_sleep_on(&dev->drv[drvidx]->snd_waitq[chidx]);
1071 retval = count;
1072 goto out;
1073 }
1074 if (minor <= ISDN_MINOR_CTRLMAX) {
1075 drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
1076 if (drvidx < 0) {
1077 retval = -ENODEV;
1078 goto out;
1079 }
1080 /*
1081 * We want to use the isdnctrl device to load the firmware
1082 *
1083 if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING))
1084 return -ENODEV;
1085 */
1086 if (dev->drv[drvidx]->interface->writecmd)
1087 retval = dev->drv[drvidx]->interface->
1088 writecmd(buf, count, drvidx, isdn_minor2chan(minor));
1089 else
1090 retval = count;
1091 goto out;
1092 }
1093#ifdef CONFIG_ISDN_PPP
1094 if (minor <= ISDN_MINOR_PPPMAX) {
1095 retval = isdn_ppp_write(minor - ISDN_MINOR_PPP, file, buf, count);
1096 goto out;
1097 }
1098#endif
1099 retval = -ENODEV;
1100 out:
1101 unlock_kernel();
1102 return retval;
1103}
1104
1105static unsigned int
1106isdn_poll(struct file *file, poll_table * wait)
1107{
1108 unsigned int mask = 0;
1109 unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
1110 int drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
1111
1112 lock_kernel();
1113 if (minor == ISDN_MINOR_STATUS) {
1114 poll_wait(file, &(dev->info_waitq), wait);
1115 /* mask = POLLOUT | POLLWRNORM; */
1116 if (file->private_data) {
1117 mask |= POLLIN | POLLRDNORM;
1118 }
1119 goto out;
1120 }
1121 if (minor >= ISDN_MINOR_CTRL && minor <= ISDN_MINOR_CTRLMAX) {
1122 if (drvidx < 0) {
1123 /* driver deregistered while file open */
1124 mask = POLLHUP;
1125 goto out;
1126 }
1127 poll_wait(file, &(dev->drv[drvidx]->st_waitq), wait);
1128 mask = POLLOUT | POLLWRNORM;
1129 if (dev->drv[drvidx]->stavail) {
1130 mask |= POLLIN | POLLRDNORM;
1131 }
1132 goto out;
1133 }
1134#ifdef CONFIG_ISDN_PPP
1135 if (minor <= ISDN_MINOR_PPPMAX) {
1136 mask = isdn_ppp_poll(file, wait);
1137 goto out;
1138 }
1139#endif
1140 mask = POLLERR;
1141 out:
1142 unlock_kernel();
1143 return mask;
1144}
1145
1146
1147static int
1148isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
1149{
1150 uint minor = MINOR(inode->i_rdev);
1151 isdn_ctrl c;
1152 int drvidx;
1153 int chidx;
1154 int ret;
1155 int i;
1156 char __user *p;
1157 char *s;
1158 union iocpar {
1159 char name[10];
1160 char bname[22];
1161 isdn_ioctl_struct iocts;
1162 isdn_net_ioctl_phone phone;
1163 isdn_net_ioctl_cfg cfg;
1164 } iocpar;
1165 void __user *argp = (void __user *)arg;
1166
1167#define name iocpar.name
1168#define bname iocpar.bname
1169#define iocts iocpar.iocts
1170#define phone iocpar.phone
1171#define cfg iocpar.cfg
1172
1173 if (minor == ISDN_MINOR_STATUS) {
1174 switch (cmd) {
1175 case IIOCGETDVR:
1176 return (TTY_DV +
1177 (NET_DV << 8) +
1178 (INF_DV << 16));
1179 case IIOCGETCPS:
1180 if (arg) {
1181 ulong __user *p = argp;
1182 int i;
1183 if (!access_ok(VERIFY_WRITE, p,
1184 sizeof(ulong) * ISDN_MAX_CHANNELS * 2))
1185 return -EFAULT;
1186 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
1187 put_user(dev->ibytes[i], p++);
1188 put_user(dev->obytes[i], p++);
1189 }
1190 return 0;
1191 } else
1192 return -EINVAL;
1193 break;
1194#ifdef CONFIG_NETDEVICES
1195 case IIOCNETGPN:
1196 /* Get peer phone number of a connected
1197 * isdn network interface */
1198 if (arg) {
1199 if (copy_from_user(&phone, argp, sizeof(phone)))
1200 return -EFAULT;
1201 return isdn_net_getpeer(&phone, argp);
1202 } else
1203 return -EINVAL;
1204#endif
1205 default:
1206 return -EINVAL;
1207 }
1208 }
1209 if (!dev->drivers)
1210 return -ENODEV;
1211 if (minor <= ISDN_MINOR_BMAX) {
1212 drvidx = isdn_minor2drv(minor);
1213 if (drvidx < 0)
1214 return -ENODEV;
1215 chidx = isdn_minor2chan(minor);
1216 if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING))
1217 return -ENODEV;
1218 return 0;
1219 }
1220 if (minor <= ISDN_MINOR_CTRLMAX) {
1221/*
1222 * isdn net devices manage lots of configuration variables as linked lists.
1223 * Those lists must only be manipulated from user space. Some of the ioctl's
1224 * service routines access user space and are not atomic. Therefor, ioctl's
1225 * manipulating the lists and ioctl's sleeping while accessing the lists
1226 * are serialized by means of a semaphore.
1227 */
1228 switch (cmd) {
1229 case IIOCNETDWRSET:
1230 printk(KERN_INFO "INFO: ISDN_DW_ABC_EXTENSION not enabled\n");
1231 return(-EINVAL);
1232 case IIOCNETLCR:
1233 printk(KERN_INFO "INFO: ISDN_ABC_LCR_SUPPORT not enabled\n");
1234 return -ENODEV;
1235#ifdef CONFIG_NETDEVICES
1236 case IIOCNETAIF:
1237 /* Add a network-interface */
1238 if (arg) {
1239 if (copy_from_user(name, argp, sizeof(name)))
1240 return -EFAULT;
1241 s = name;
1242 } else {
1243 s = NULL;
1244 }
1245 ret = down_interruptible(&dev->sem);
1246 if( ret ) return ret;
1247 if ((s = isdn_net_new(s, NULL))) {
1248 if (copy_to_user(argp, s, strlen(s) + 1)){
1249 ret = -EFAULT;
1250 } else {
1251 ret = 0;
1252 }
1253 } else
1254 ret = -ENODEV;
1255 up(&dev->sem);
1256 return ret;
1257 case IIOCNETASL:
1258 /* Add a slave to a network-interface */
1259 if (arg) {
1260 if (copy_from_user(bname, argp, sizeof(bname) - 1))
1261 return -EFAULT;
1262 } else
1263 return -EINVAL;
1264 ret = down_interruptible(&dev->sem);
1265 if( ret ) return ret;
1266 if ((s = isdn_net_newslave(bname))) {
1267 if (copy_to_user(argp, s, strlen(s) + 1)){
1268 ret = -EFAULT;
1269 } else {
1270 ret = 0;
1271 }
1272 } else
1273 ret = -ENODEV;
1274 up(&dev->sem);
1275 return ret;
1276 case IIOCNETDIF:
1277 /* Delete a network-interface */
1278 if (arg) {
1279 if (copy_from_user(name, argp, sizeof(name)))
1280 return -EFAULT;
1281 ret = down_interruptible(&dev->sem);
1282 if( ret ) return ret;
1283 ret = isdn_net_rm(name);
1284 up(&dev->sem);
1285 return ret;
1286 } else
1287 return -EINVAL;
1288 case IIOCNETSCF:
1289 /* Set configurable parameters of a network-interface */
1290 if (arg) {
1291 if (copy_from_user(&cfg, argp, sizeof(cfg)))
1292 return -EFAULT;
1293 return isdn_net_setcfg(&cfg);
1294 } else
1295 return -EINVAL;
1296 case IIOCNETGCF:
1297 /* Get configurable parameters of a network-interface */
1298 if (arg) {
1299 if (copy_from_user(&cfg, argp, sizeof(cfg)))
1300 return -EFAULT;
1301 if (!(ret = isdn_net_getcfg(&cfg))) {
1302 if (copy_to_user(argp, &cfg, sizeof(cfg)))
1303 return -EFAULT;
1304 }
1305 return ret;
1306 } else
1307 return -EINVAL;
1308 case IIOCNETANM:
1309 /* Add a phone-number to a network-interface */
1310 if (arg) {
1311 if (copy_from_user(&phone, argp, sizeof(phone)))
1312 return -EFAULT;
1313 ret = down_interruptible(&dev->sem);
1314 if( ret ) return ret;
1315 ret = isdn_net_addphone(&phone);
1316 up(&dev->sem);
1317 return ret;
1318 } else
1319 return -EINVAL;
1320 case IIOCNETGNM:
1321 /* Get list of phone-numbers of a network-interface */
1322 if (arg) {
1323 if (copy_from_user(&phone, argp, sizeof(phone)))
1324 return -EFAULT;
1325 ret = down_interruptible(&dev->sem);
1326 if( ret ) return ret;
1327 ret = isdn_net_getphones(&phone, argp);
1328 up(&dev->sem);
1329 return ret;
1330 } else
1331 return -EINVAL;
1332 case IIOCNETDNM:
1333 /* Delete a phone-number of a network-interface */
1334 if (arg) {
1335 if (copy_from_user(&phone, argp, sizeof(phone)))
1336 return -EFAULT;
1337 ret = down_interruptible(&dev->sem);
1338 if( ret ) return ret;
1339 ret = isdn_net_delphone(&phone);
1340 up(&dev->sem);
1341 return ret;
1342 } else
1343 return -EINVAL;
1344 case IIOCNETDIL:
1345 /* Force dialing of a network-interface */
1346 if (arg) {
1347 if (copy_from_user(name, argp, sizeof(name)))
1348 return -EFAULT;
1349 return isdn_net_force_dial(name);
1350 } else
1351 return -EINVAL;
1352#ifdef CONFIG_ISDN_PPP
1353 case IIOCNETALN:
1354 if (!arg)
1355 return -EINVAL;
1356 if (copy_from_user(name, argp, sizeof(name)))
1357 return -EFAULT;
1358 return isdn_ppp_dial_slave(name);
1359 case IIOCNETDLN:
1360 if (!arg)
1361 return -EINVAL;
1362 if (copy_from_user(name, argp, sizeof(name)))
1363 return -EFAULT;
1364 return isdn_ppp_hangup_slave(name);
1365#endif
1366 case IIOCNETHUP:
1367 /* Force hangup of a network-interface */
1368 if (!arg)
1369 return -EINVAL;
1370 if (copy_from_user(name, argp, sizeof(name)))
1371 return -EFAULT;
1372 return isdn_net_force_hangup(name);
1373 break;
1374#endif /* CONFIG_NETDEVICES */
1375 case IIOCSETVER:
1376 dev->net_verbose = arg;
1377 printk(KERN_INFO "isdn: Verbose-Level is %d\n", dev->net_verbose);
1378 return 0;
1379 case IIOCSETGST:
1380 if (arg)
1381 dev->global_flags |= ISDN_GLOBAL_STOPPED;
1382 else
1383 dev->global_flags &= ~ISDN_GLOBAL_STOPPED;
1384 printk(KERN_INFO "isdn: Global Mode %s\n",
1385 (dev->global_flags & ISDN_GLOBAL_STOPPED) ? "stopped" : "running");
1386 return 0;
1387 case IIOCSETBRJ:
1388 drvidx = -1;
1389 if (arg) {
1390 int i;
1391 char *p;
1392 if (copy_from_user(&iocts, argp,
1393 sizeof(isdn_ioctl_struct)))
1394 return -EFAULT;
1395 if (strlen(iocts.drvid)) {
1396 if ((p = strchr(iocts.drvid, ',')))
1397 *p = 0;
1398 drvidx = -1;
1399 for (i = 0; i < ISDN_MAX_DRIVERS; i++)
1400 if (!(strcmp(dev->drvid[i], iocts.drvid))) {
1401 drvidx = i;
1402 break;
1403 }
1404 }
1405 }
1406 if (drvidx == -1)
1407 return -ENODEV;
1408 if (iocts.arg)
1409 dev->drv[drvidx]->flags |= DRV_FLAG_REJBUS;
1410 else
1411 dev->drv[drvidx]->flags &= ~DRV_FLAG_REJBUS;
1412 return 0;
1413 case IIOCSIGPRF:
1414 dev->profd = current;
1415 return 0;
1416 break;
1417 case IIOCGETPRF:
1418 /* Get all Modem-Profiles */
1419 if (arg) {
1420 char __user *p = argp;
1421 int i;
1422
1423 if (!access_ok(VERIFY_WRITE, argp,
1424 (ISDN_MODEM_NUMREG + ISDN_MSNLEN + ISDN_LMSNLEN)
1425 * ISDN_MAX_CHANNELS))
1426 return -EFAULT;
1427
1428 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
1429 if (copy_to_user(p, dev->mdm.info[i].emu.profile,
1430 ISDN_MODEM_NUMREG))
1431 return -EFAULT;
1432 p += ISDN_MODEM_NUMREG;
1433 if (copy_to_user(p, dev->mdm.info[i].emu.pmsn, ISDN_MSNLEN))
1434 return -EFAULT;
1435 p += ISDN_MSNLEN;
1436 if (copy_to_user(p, dev->mdm.info[i].emu.plmsn, ISDN_LMSNLEN))
1437 return -EFAULT;
1438 p += ISDN_LMSNLEN;
1439 }
1440 return (ISDN_MODEM_NUMREG + ISDN_MSNLEN + ISDN_LMSNLEN) * ISDN_MAX_CHANNELS;
1441 } else
1442 return -EINVAL;
1443 break;
1444 case IIOCSETPRF:
1445 /* Set all Modem-Profiles */
1446 if (arg) {
1447 char __user *p = argp;
1448 int i;
1449
1450 if (!access_ok(VERIFY_READ, argp,
1451 (ISDN_MODEM_NUMREG + ISDN_MSNLEN + ISDN_LMSNLEN)
1452 * ISDN_MAX_CHANNELS))
1453 return -EFAULT;
1454
1455 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
1456 if (copy_from_user(dev->mdm.info[i].emu.profile, p,
1457 ISDN_MODEM_NUMREG))
1458 return -EFAULT;
1459 p += ISDN_MODEM_NUMREG;
1460 if (copy_from_user(dev->mdm.info[i].emu.plmsn, p, ISDN_LMSNLEN))
1461 return -EFAULT;
1462 p += ISDN_LMSNLEN;
1463 if (copy_from_user(dev->mdm.info[i].emu.pmsn, p, ISDN_MSNLEN))
1464 return -EFAULT;
1465 p += ISDN_MSNLEN;
1466 }
1467 return 0;
1468 } else
1469 return -EINVAL;
1470 break;
1471 case IIOCSETMAP:
1472 case IIOCGETMAP:
1473 /* Set/Get MSN->EAZ-Mapping for a driver */
1474 if (arg) {
1475
1476 if (copy_from_user(&iocts, argp,
1477 sizeof(isdn_ioctl_struct)))
1478 return -EFAULT;
1479 if (strlen(iocts.drvid)) {
1480 drvidx = -1;
1481 for (i = 0; i < ISDN_MAX_DRIVERS; i++)
1482 if (!(strcmp(dev->drvid[i], iocts.drvid))) {
1483 drvidx = i;
1484 break;
1485 }
1486 } else
1487 drvidx = 0;
1488 if (drvidx == -1)
1489 return -ENODEV;
1490 if (cmd == IIOCSETMAP) {
1491 int loop = 1;
1492
1493 p = (char __user *) iocts.arg;
1494 i = 0;
1495 while (loop) {
1496 int j = 0;
1497
1498 while (1) {
1499 if (!access_ok(VERIFY_READ, p, 1))
1500 return -EFAULT;
1501 get_user(bname[j], p++);
1502 switch (bname[j]) {
1503 case '\0':
1504 loop = 0;
1505 /* Fall through */
1506 case ',':
1507 bname[j] = '\0';
1508 strcpy(dev->drv[drvidx]->msn2eaz[i], bname);
1509 j = ISDN_MSNLEN;
1510 break;
1511 default:
1512 j++;
1513 }
1514 if (j >= ISDN_MSNLEN)
1515 break;
1516 }
1517 if (++i > 9)
1518 break;
1519 }
1520 } else {
1521 p = (char __user *) iocts.arg;
1522 for (i = 0; i < 10; i++) {
1523 sprintf(bname, "%s%s",
1524 strlen(dev->drv[drvidx]->msn2eaz[i]) ?
1525 dev->drv[drvidx]->msn2eaz[i] : "_",
1526 (i < 9) ? "," : "\0");
1527 if (copy_to_user(p, bname, strlen(bname) + 1))
1528 return -EFAULT;
1529 p += strlen(bname);
1530 }
1531 }
1532 return 0;
1533 } else
1534 return -EINVAL;
1535 case IIOCDBGVAR:
1536 if (arg) {
1537 if (copy_to_user(argp, &dev, sizeof(ulong)))
1538 return -EFAULT;
1539 return 0;
1540 } else
1541 return -EINVAL;
1542 break;
1543 default:
1544 if ((cmd & IIOCDRVCTL) == IIOCDRVCTL)
1545 cmd = ((cmd >> _IOC_NRSHIFT) & _IOC_NRMASK) & ISDN_DRVIOCTL_MASK;
1546 else
1547 return -EINVAL;
1548 if (arg) {
1549 int i;
1550 char *p;
1551 if (copy_from_user(&iocts, argp, sizeof(isdn_ioctl_struct)))
1552 return -EFAULT;
1553 if (strlen(iocts.drvid)) {
1554 if ((p = strchr(iocts.drvid, ',')))
1555 *p = 0;
1556 drvidx = -1;
1557 for (i = 0; i < ISDN_MAX_DRIVERS; i++)
1558 if (!(strcmp(dev->drvid[i], iocts.drvid))) {
1559 drvidx = i;
1560 break;
1561 }
1562 } else
1563 drvidx = 0;
1564 if (drvidx == -1)
1565 return -ENODEV;
1566 if (!access_ok(VERIFY_WRITE, argp,
1567 sizeof(isdn_ioctl_struct)))
1568 return -EFAULT;
1569 c.driver = drvidx;
1570 c.command = ISDN_CMD_IOCTL;
1571 c.arg = cmd;
1572 memcpy(c.parm.num, &iocts.arg, sizeof(ulong));
1573 ret = isdn_command(&c);
1574 memcpy(&iocts.arg, c.parm.num, sizeof(ulong));
1575 if (copy_to_user(argp, &iocts, sizeof(isdn_ioctl_struct)))
1576 return -EFAULT;
1577 return ret;
1578 } else
1579 return -EINVAL;
1580 }
1581 }
1582#ifdef CONFIG_ISDN_PPP
1583 if (minor <= ISDN_MINOR_PPPMAX)
1584 return (isdn_ppp_ioctl(minor - ISDN_MINOR_PPP, file, cmd, arg));
1585#endif
1586 return -ENODEV;
1587
1588#undef name
1589#undef bname
1590#undef iocts
1591#undef phone
1592#undef cfg
1593}
1594
1595/*
1596 * Open the device code.
1597 */
1598static int
1599isdn_open(struct inode *ino, struct file *filep)
1600{
1601 uint minor = MINOR(ino->i_rdev);
1602 int drvidx;
1603 int chidx;
1604 int retval = -ENODEV;
1605
1606
1607 if (minor == ISDN_MINOR_STATUS) {
1608 infostruct *p;
1609
1610 if ((p = kmalloc(sizeof(infostruct), GFP_KERNEL))) {
1611 p->next = (char *) dev->infochain;
1612 p->private = (char *) &(filep->private_data);
1613 dev->infochain = p;
1614 /* At opening we allow a single update */
1615 filep->private_data = (char *) 1;
1616 retval = 0;
1617 goto out;
1618 } else {
1619 retval = -ENOMEM;
1620 goto out;
1621 }
1622 }
1623 if (!dev->channels)
1624 goto out;
1625 if (minor <= ISDN_MINOR_BMAX) {
1626 printk(KERN_WARNING "isdn_open minor %d obsolete!\n", minor);
1627 drvidx = isdn_minor2drv(minor);
1628 if (drvidx < 0)
1629 goto out;
1630 chidx = isdn_minor2chan(minor);
1631 if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING))
1632 goto out;
1633 if (!(dev->drv[drvidx]->online & (1 << chidx)))
1634 goto out;
1635 isdn_lock_drivers();
1636 retval = 0;
1637 goto out;
1638 }
1639 if (minor <= ISDN_MINOR_CTRLMAX) {
1640 drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
1641 if (drvidx < 0)
1642 goto out;
1643 isdn_lock_drivers();
1644 retval = 0;
1645 goto out;
1646 }
1647#ifdef CONFIG_ISDN_PPP
1648 if (minor <= ISDN_MINOR_PPPMAX) {
1649 retval = isdn_ppp_open(minor - ISDN_MINOR_PPP, filep);
1650 if (retval == 0)
1651 isdn_lock_drivers();
1652 goto out;
1653 }
1654#endif
1655 out:
1656 nonseekable_open(ino, filep);
1657 return retval;
1658}
1659
1660static int
1661isdn_close(struct inode *ino, struct file *filep)
1662{
1663 uint minor = MINOR(ino->i_rdev);
1664
1665 lock_kernel();
1666 if (minor == ISDN_MINOR_STATUS) {
1667 infostruct *p = dev->infochain;
1668 infostruct *q = NULL;
1669
1670 while (p) {
1671 if (p->private == (char *) &(filep->private_data)) {
1672 if (q)
1673 q->next = p->next;
1674 else
1675 dev->infochain = (infostruct *) (p->next);
1676 kfree(p);
1677 goto out;
1678 }
1679 q = p;
1680 p = (infostruct *) (p->next);
1681 }
1682 printk(KERN_WARNING "isdn: No private data while closing isdnctrl\n");
1683 goto out;
1684 }
1685 isdn_unlock_drivers();
1686 if (minor <= ISDN_MINOR_BMAX)
1687 goto out;
1688 if (minor <= ISDN_MINOR_CTRLMAX) {
1689 if (dev->profd == current)
1690 dev->profd = NULL;
1691 goto out;
1692 }
1693#ifdef CONFIG_ISDN_PPP
1694 if (minor <= ISDN_MINOR_PPPMAX)
1695 isdn_ppp_release(minor - ISDN_MINOR_PPP, filep);
1696#endif
1697
1698 out:
1699 unlock_kernel();
1700 return 0;
1701}
1702
1703static struct file_operations isdn_fops =
1704{
1705 .owner = THIS_MODULE,
1706 .llseek = no_llseek,
1707 .read = isdn_read,
1708 .write = isdn_write,
1709 .poll = isdn_poll,
1710 .ioctl = isdn_ioctl,
1711 .open = isdn_open,
1712 .release = isdn_close,
1713};
1714
1715char *
1716isdn_map_eaz2msn(char *msn, int di)
1717{
1718 isdn_driver_t *this = dev->drv[di];
1719 int i;
1720
1721 if (strlen(msn) == 1) {
1722 i = msn[0] - '0';
1723 if ((i >= 0) && (i <= 9))
1724 if (strlen(this->msn2eaz[i]))
1725 return (this->msn2eaz[i]);
1726 }
1727 return (msn);
1728}
1729
1730/*
1731 * Find an unused ISDN-channel, whose feature-flags match the
1732 * given L2- and L3-protocols.
1733 */
1734#define L2V (~(ISDN_FEATURE_L2_V11096|ISDN_FEATURE_L2_V11019|ISDN_FEATURE_L2_V11038))
1735
1736/*
1737 * This function must be called with holding the dev->lock.
1738 */
1739int
1740isdn_get_free_channel(int usage, int l2_proto, int l3_proto, int pre_dev
1741 ,int pre_chan, char *msn)
1742{
1743 int i;
1744 ulong features;
1745 ulong vfeatures;
1746
1747 features = ((1 << l2_proto) | (0x10000 << l3_proto));
1748 vfeatures = (((1 << l2_proto) | (0x10000 << l3_proto)) &
1749 ~(ISDN_FEATURE_L2_V11096|ISDN_FEATURE_L2_V11019|ISDN_FEATURE_L2_V11038));
1750 /* If Layer-2 protocol is V.110, accept drivers with
1751 * transparent feature even if these don't support V.110
1752 * because we can emulate this in linklevel.
1753 */
1754 for (i = 0; i < ISDN_MAX_CHANNELS; i++)
1755 if (USG_NONE(dev->usage[i]) &&
1756 (dev->drvmap[i] != -1)) {
1757 int d = dev->drvmap[i];
1758 if ((dev->usage[i] & ISDN_USAGE_EXCLUSIVE) &&
1759 ((pre_dev != d) || (pre_chan != dev->chanmap[i])))
1760 continue;
1761 if (!strcmp(isdn_map_eaz2msn(msn, d), "-"))
1762 continue;
1763 if (dev->usage[i] & ISDN_USAGE_DISABLED)
1764 continue; /* usage not allowed */
1765 if (dev->drv[d]->flags & DRV_FLAG_RUNNING) {
1766 if (((dev->drv[d]->interface->features & features) == features) ||
1767 (((dev->drv[d]->interface->features & vfeatures) == vfeatures) &&
1768 (dev->drv[d]->interface->features & ISDN_FEATURE_L2_TRANS))) {
1769 if ((pre_dev < 0) || (pre_chan < 0)) {
1770 dev->usage[i] &= ISDN_USAGE_EXCLUSIVE;
1771 dev->usage[i] |= usage;
1772 isdn_info_update();
1773 return i;
1774 } else {
1775 if ((pre_dev == d) && (pre_chan == dev->chanmap[i])) {
1776 dev->usage[i] &= ISDN_USAGE_EXCLUSIVE;
1777 dev->usage[i] |= usage;
1778 isdn_info_update();
1779 return i;
1780 }
1781 }
1782 }
1783 }
1784 }
1785 return -1;
1786}
1787
1788/*
1789 * Set state of ISDN-channel to 'unused'
1790 */
1791void
1792isdn_free_channel(int di, int ch, int usage)
1793{
1794 int i;
1795
1796 for (i = 0; i < ISDN_MAX_CHANNELS; i++)
1797 if (((!usage) || ((dev->usage[i] & ISDN_USAGE_MASK) == usage)) &&
1798 (dev->drvmap[i] == di) &&
1799 (dev->chanmap[i] == ch)) {
1800 dev->usage[i] &= (ISDN_USAGE_NONE | ISDN_USAGE_EXCLUSIVE);
1801 strcpy(dev->num[i], "???");
1802 dev->ibytes[i] = 0;
1803 dev->obytes[i] = 0;
1804// 20.10.99 JIM, try to reinitialize v110 !
1805 dev->v110emu[i] = 0;
1806 atomic_set(&(dev->v110use[i]), 0);
1807 isdn_v110_close(dev->v110[i]);
1808 dev->v110[i] = NULL;
1809// 20.10.99 JIM, try to reinitialize v110 !
1810 isdn_info_update();
1811 skb_queue_purge(&dev->drv[di]->rpqueue[ch]);
1812 }
1813}
1814
1815/*
1816 * Cancel Exclusive-Flag for ISDN-channel
1817 */
1818void
1819isdn_unexclusive_channel(int di, int ch)
1820{
1821 int i;
1822
1823 for (i = 0; i < ISDN_MAX_CHANNELS; i++)
1824 if ((dev->drvmap[i] == di) &&
1825 (dev->chanmap[i] == ch)) {
1826 dev->usage[i] &= ~ISDN_USAGE_EXCLUSIVE;
1827 isdn_info_update();
1828 return;
1829 }
1830}
1831
1832/*
1833 * writebuf replacement for SKB_ABLE drivers
1834 */
1835static int
1836isdn_writebuf_stub(int drvidx, int chan, const u_char __user * buf, int len)
1837{
1838 int ret;
1839 int hl = dev->drv[drvidx]->interface->hl_hdrlen;
1840 struct sk_buff *skb = alloc_skb(hl + len, GFP_ATOMIC);
1841
1842 if (!skb)
1843 return 0;
1844 skb_reserve(skb, hl);
1845 copy_from_user(skb_put(skb, len), buf, len);
1846 ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, 1, skb);
1847 if (ret <= 0)
1848 dev_kfree_skb(skb);
1849 if (ret > 0)
1850 dev->obytes[isdn_dc2minor(drvidx, chan)] += ret;
1851 return ret;
1852}
1853
1854/*
1855 * Return: length of data on success, -ERRcode on failure.
1856 */
1857int
1858isdn_writebuf_skb_stub(int drvidx, int chan, int ack, struct sk_buff *skb)
1859{
1860 int ret;
1861 struct sk_buff *nskb = NULL;
1862 int v110_ret = skb->len;
1863 int idx = isdn_dc2minor(drvidx, chan);
1864
1865 if (dev->v110[idx]) {
1866 atomic_inc(&dev->v110use[idx]);
1867 nskb = isdn_v110_encode(dev->v110[idx], skb);
1868 atomic_dec(&dev->v110use[idx]);
1869 if (!nskb)
1870 return 0;
1871 v110_ret = *((int *)nskb->data);
1872 skb_pull(nskb, sizeof(int));
1873 if (!nskb->len) {
1874 dev_kfree_skb(nskb);
1875 return v110_ret;
1876 }
1877 /* V.110 must always be acknowledged */
1878 ack = 1;
1879 ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, ack, nskb);
1880 } else {
1881 int hl = dev->drv[drvidx]->interface->hl_hdrlen;
1882
1883 if( skb_headroom(skb) < hl ){
1884 /*
1885 * This should only occur when new HL driver with
1886 * increased hl_hdrlen was loaded after netdevice
1887 * was created and connected to the new driver.
1888 *
1889 * The V.110 branch (re-allocates on its own) does
1890 * not need this
1891 */
1892 struct sk_buff * skb_tmp;
1893
1894 skb_tmp = skb_realloc_headroom(skb, hl);
1895 printk(KERN_DEBUG "isdn_writebuf_skb_stub: reallocating headroom%s\n", skb_tmp ? "" : " failed");
1896 if (!skb_tmp) return -ENOMEM; /* 0 better? */
1897 ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, ack, skb_tmp);
1898 if( ret > 0 ){
1899 dev_kfree_skb(skb);
1900 } else {
1901 dev_kfree_skb(skb_tmp);
1902 }
1903 } else {
1904 ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, ack, skb);
1905 }
1906 }
1907 if (ret > 0) {
1908 dev->obytes[idx] += ret;
1909 if (dev->v110[idx]) {
1910 atomic_inc(&dev->v110use[idx]);
1911 dev->v110[idx]->skbuser++;
1912 atomic_dec(&dev->v110use[idx]);
1913 /* For V.110 return unencoded data length */
1914 ret = v110_ret;
1915 /* if the complete frame was send we free the skb;
1916 if not upper function will requeue the skb */
1917 if (ret == skb->len)
1918 dev_kfree_skb(skb);
1919 }
1920 } else
1921 if (dev->v110[idx])
1922 dev_kfree_skb(nskb);
1923 return ret;
1924}
1925
1926int
1927isdn_add_channels(isdn_driver_t *d, int drvidx, int n, int adding)
1928{
1929 int j, k, m;
1930
1931 init_waitqueue_head(&d->st_waitq);
1932 if (d->flags & DRV_FLAG_RUNNING)
1933 return -1;
1934 if (n < 1) return 0;
1935
1936 m = (adding) ? d->channels + n : n;
1937
1938 if (dev->channels + n > ISDN_MAX_CHANNELS) {
1939 printk(KERN_WARNING "register_isdn: Max. %d channels supported\n",
1940 ISDN_MAX_CHANNELS);
1941 return -1;
1942 }
1943
1944 if ((adding) && (d->rcverr))
1945 kfree(d->rcverr);
1946 if (!(d->rcverr = kmalloc(sizeof(int) * m, GFP_ATOMIC))) {
1947 printk(KERN_WARNING "register_isdn: Could not alloc rcverr\n");
1948 return -1;
1949 }
1950 memset((char *) d->rcverr, 0, sizeof(int) * m);
1951
1952 if ((adding) && (d->rcvcount))
1953 kfree(d->rcvcount);
1954 if (!(d->rcvcount = kmalloc(sizeof(int) * m, GFP_ATOMIC))) {
1955 printk(KERN_WARNING "register_isdn: Could not alloc rcvcount\n");
1956 if (!adding) kfree(d->rcverr);
1957 return -1;
1958 }
1959 memset((char *) d->rcvcount, 0, sizeof(int) * m);
1960
1961 if ((adding) && (d->rpqueue)) {
1962 for (j = 0; j < d->channels; j++)
1963 skb_queue_purge(&d->rpqueue[j]);
1964 kfree(d->rpqueue);
1965 }
1966 if (!(d->rpqueue = kmalloc(sizeof(struct sk_buff_head) * m, GFP_ATOMIC))) {
1967 printk(KERN_WARNING "register_isdn: Could not alloc rpqueue\n");
1968 if (!adding) {
1969 kfree(d->rcvcount);
1970 kfree(d->rcverr);
1971 }
1972 return -1;
1973 }
1974 for (j = 0; j < m; j++) {
1975 skb_queue_head_init(&d->rpqueue[j]);
1976 }
1977
1978 if ((adding) && (d->rcv_waitq))
1979 kfree(d->rcv_waitq);
1980 d->rcv_waitq = kmalloc(sizeof(wait_queue_head_t) * 2 * m, GFP_ATOMIC);
1981 if (!d->rcv_waitq) {
1982 printk(KERN_WARNING "register_isdn: Could not alloc rcv_waitq\n");
1983 if (!adding) {
1984 kfree(d->rpqueue);
1985 kfree(d->rcvcount);
1986 kfree(d->rcverr);
1987 }
1988 return -1;
1989 }
1990 d->snd_waitq = d->rcv_waitq + m;
1991 for (j = 0; j < m; j++) {
1992 init_waitqueue_head(&d->rcv_waitq[j]);
1993 init_waitqueue_head(&d->snd_waitq[j]);
1994 }
1995
1996 dev->channels += n;
1997 for (j = d->channels; j < m; j++)
1998 for (k = 0; k < ISDN_MAX_CHANNELS; k++)
1999 if (dev->chanmap[k] < 0) {
2000 dev->chanmap[k] = j;
2001 dev->drvmap[k] = drvidx;
2002 break;
2003 }
2004 d->channels = m;
2005 return 0;
2006}
2007
2008/*
2009 * Low-level-driver registration
2010 */
2011
2012static void
2013set_global_features(void)
2014{
2015 int drvidx;
2016
2017 dev->global_features = 0;
2018 for (drvidx = 0; drvidx < ISDN_MAX_DRIVERS; drvidx++) {
2019 if (!dev->drv[drvidx])
2020 continue;
2021 if (dev->drv[drvidx]->interface)
2022 dev->global_features |= dev->drv[drvidx]->interface->features;
2023 }
2024}
2025
2026#ifdef CONFIG_ISDN_DIVERSION
2027
2028static char *map_drvname(int di)
2029{
2030 if ((di < 0) || (di >= ISDN_MAX_DRIVERS))
2031 return(NULL);
2032 return(dev->drvid[di]); /* driver name */
2033} /* map_drvname */
2034
2035static int map_namedrv(char *id)
2036{ int i;
2037
2038 for (i = 0; i < ISDN_MAX_DRIVERS; i++)
2039 { if (!strcmp(dev->drvid[i],id))
2040 return(i);
2041 }
2042 return(-1);
2043} /* map_namedrv */
2044
2045int DIVERT_REG_NAME(isdn_divert_if *i_div)
2046{
2047 if (i_div->if_magic != DIVERT_IF_MAGIC)
2048 return(DIVERT_VER_ERR);
2049 switch (i_div->cmd)
2050 {
2051 case DIVERT_CMD_REL:
2052 if (divert_if != i_div)
2053 return(DIVERT_REL_ERR);
2054 divert_if = NULL; /* free interface */
2055 return(DIVERT_NO_ERR);
2056
2057 case DIVERT_CMD_REG:
2058 if (divert_if)
2059 return(DIVERT_REG_ERR);
2060 i_div->ll_cmd = isdn_command; /* set command function */
2061 i_div->drv_to_name = map_drvname;
2062 i_div->name_to_drv = map_namedrv;
2063 divert_if = i_div; /* remember interface */
2064 return(DIVERT_NO_ERR);
2065
2066 default:
2067 return(DIVERT_CMD_ERR);
2068 }
2069} /* DIVERT_REG_NAME */
2070
2071EXPORT_SYMBOL(DIVERT_REG_NAME);
2072
2073#endif /* CONFIG_ISDN_DIVERSION */
2074
2075
2076EXPORT_SYMBOL(register_isdn);
2077#ifdef CONFIG_ISDN_PPP
2078EXPORT_SYMBOL(isdn_ppp_register_compressor);
2079EXPORT_SYMBOL(isdn_ppp_unregister_compressor);
2080#endif
2081
2082int
2083register_isdn(isdn_if * i)
2084{
2085 isdn_driver_t *d;
2086 int j;
2087 ulong flags;
2088 int drvidx;
2089
2090 if (dev->drivers >= ISDN_MAX_DRIVERS) {
2091 printk(KERN_WARNING "register_isdn: Max. %d drivers supported\n",
2092 ISDN_MAX_DRIVERS);
2093 return 0;
2094 }
2095 if (!i->writebuf_skb) {
2096 printk(KERN_WARNING "register_isdn: No write routine given.\n");
2097 return 0;
2098 }
2099 if (!(d = kmalloc(sizeof(isdn_driver_t), GFP_KERNEL))) {
2100 printk(KERN_WARNING "register_isdn: Could not alloc driver-struct\n");
2101 return 0;
2102 }
2103 memset((char *) d, 0, sizeof(isdn_driver_t));
2104
2105 d->maxbufsize = i->maxbufsize;
2106 d->pktcount = 0;
2107 d->stavail = 0;
2108 d->flags = DRV_FLAG_LOADED;
2109 d->online = 0;
2110 d->interface = i;
2111 d->channels = 0;
2112 spin_lock_irqsave(&dev->lock, flags);
2113 for (drvidx = 0; drvidx < ISDN_MAX_DRIVERS; drvidx++)
2114 if (!dev->drv[drvidx])
2115 break;
2116 if (isdn_add_channels(d, drvidx, i->channels, 0)) {
2117 spin_unlock_irqrestore(&dev->lock, flags);
2118 kfree(d);
2119 return 0;
2120 }
2121 i->channels = drvidx;
2122 i->rcvcallb_skb = isdn_receive_skb_callback;
2123 i->statcallb = isdn_status_callback;
2124 if (!strlen(i->id))
2125 sprintf(i->id, "line%d", drvidx);
2126 for (j = 0; j < drvidx; j++)
2127 if (!strcmp(i->id, dev->drvid[j]))
2128 sprintf(i->id, "line%d", drvidx);
2129 dev->drv[drvidx] = d;
2130 strcpy(dev->drvid[drvidx], i->id);
2131 isdn_info_update();
2132 dev->drivers++;
2133 set_global_features();
2134 spin_unlock_irqrestore(&dev->lock, flags);
2135 return 1;
2136}
2137
2138/*
2139 *****************************************************************************
2140 * And now the modules code.
2141 *****************************************************************************
2142 */
2143
2144static char *
2145isdn_getrev(const char *revision)
2146{
2147 char *rev;
2148 char *p;
2149
2150 if ((p = strchr(revision, ':'))) {
2151 rev = p + 2;
2152 p = strchr(rev, '$');
2153 *--p = 0;
2154 } else
2155 rev = "???";
2156 return rev;
2157}
2158
2159/*
2160 * Allocate and initialize all data, register modem-devices
2161 */
2162static int __init isdn_init(void)
2163{
2164 int i;
2165 char tmprev[50];
2166
2167 if (!(dev = (isdn_dev *) vmalloc(sizeof(isdn_dev)))) {
2168 printk(KERN_WARNING "isdn: Could not allocate device-struct.\n");
2169 return -EIO;
2170 }
2171 memset((char *) dev, 0, sizeof(isdn_dev));
2172 init_timer(&dev->timer);
2173 dev->timer.function = isdn_timer_funct;
2174 spin_lock_init(&dev->lock);
2175 spin_lock_init(&dev->timerlock);
2176#ifdef MODULE
2177 dev->owner = THIS_MODULE;
2178#endif
2179 init_MUTEX(&dev->sem);
2180 init_waitqueue_head(&dev->info_waitq);
2181 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
2182 dev->drvmap[i] = -1;
2183 dev->chanmap[i] = -1;
2184 dev->m_idx[i] = -1;
2185 strcpy(dev->num[i], "???");
2186 init_waitqueue_head(&dev->mdm.info[i].open_wait);
2187 init_waitqueue_head(&dev->mdm.info[i].close_wait);
2188 }
2189 if (register_chrdev(ISDN_MAJOR, "isdn", &isdn_fops)) {
2190 printk(KERN_WARNING "isdn: Could not register control devices\n");
2191 vfree(dev);
2192 return -EIO;
2193 }
2194 if ((isdn_tty_modem_init()) < 0) {
2195 printk(KERN_WARNING "isdn: Could not register tty devices\n");
2196 vfree(dev);
2197 unregister_chrdev(ISDN_MAJOR, "isdn");
2198 return -EIO;
2199 }
2200#ifdef CONFIG_ISDN_PPP
2201 if (isdn_ppp_init() < 0) {
2202 printk(KERN_WARNING "isdn: Could not create PPP-device-structs\n");
2203 isdn_tty_exit();
2204 unregister_chrdev(ISDN_MAJOR, "isdn");
2205 vfree(dev);
2206 return -EIO;
2207 }
2208#endif /* CONFIG_ISDN_PPP */
2209
2210 strcpy(tmprev, isdn_revision);
2211 printk(KERN_NOTICE "ISDN subsystem Rev: %s/", isdn_getrev(tmprev));
2212 strcpy(tmprev, isdn_tty_revision);
2213 printk("%s/", isdn_getrev(tmprev));
2214 strcpy(tmprev, isdn_net_revision);
2215 printk("%s/", isdn_getrev(tmprev));
2216 strcpy(tmprev, isdn_ppp_revision);
2217 printk("%s/", isdn_getrev(tmprev));
2218 strcpy(tmprev, isdn_audio_revision);
2219 printk("%s/", isdn_getrev(tmprev));
2220 strcpy(tmprev, isdn_v110_revision);
2221 printk("%s", isdn_getrev(tmprev));
2222
2223#ifdef MODULE
2224 printk(" loaded\n");
2225#else
2226 printk("\n");
2227#endif
2228 isdn_info_update();
2229 return 0;
2230}
2231
2232/*
2233 * Unload module
2234 */
2235static void __exit isdn_exit(void)
2236{
2237#ifdef CONFIG_ISDN_PPP
2238 isdn_ppp_cleanup();
2239#endif
2240 if (isdn_net_rmall() < 0) {
2241 printk(KERN_WARNING "isdn: net-device busy, remove cancelled\n");
2242 return;
2243 }
2244 isdn_tty_exit();
2245 unregister_chrdev(ISDN_MAJOR, "isdn");
2246 del_timer(&dev->timer);
2247 /* call vfree with interrupts enabled, else it will hang */
2248 vfree(dev);
2249 printk(KERN_NOTICE "ISDN-subsystem unloaded\n");
2250}
2251
2252module_init(isdn_init);
2253module_exit(isdn_exit);
diff --git a/drivers/isdn/i4l/isdn_common.h b/drivers/isdn/i4l/isdn_common.h
new file mode 100644
index 000000000000..808135c427ad
--- /dev/null
+++ b/drivers/isdn/i4l/isdn_common.h
@@ -0,0 +1,47 @@
1/* $Id: isdn_common.h,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $
2 *
3 * header for Linux ISDN subsystem
4 * common used functions and debugging-switches (linklevel).
5 *
6 * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de)
7 * Copyright 1995,96 by Thinking Objects Software GmbH Wuerzburg
8 * Copyright 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
9 *
10 * This software may be used and distributed according to the terms
11 * of the GNU General Public License, incorporated herein by reference.
12 *
13 */
14
15#undef ISDN_DEBUG_MODEM_OPEN
16#undef ISDN_DEBUG_MODEM_IOCTL
17#undef ISDN_DEBUG_MODEM_WAITSENT
18#undef ISDN_DEBUG_MODEM_HUP
19#undef ISDN_DEBUG_MODEM_ICALL
20#undef ISDN_DEBUG_MODEM_DUMP
21#undef ISDN_DEBUG_MODEM_VOICE
22#undef ISDN_DEBUG_AT
23#undef ISDN_DEBUG_NET_DUMP
24#undef ISDN_DEBUG_NET_DIAL
25#undef ISDN_DEBUG_NET_ICALL
26
27/* Prototypes */
28extern void isdn_lock_drivers(void);
29extern void isdn_unlock_drivers(void);
30extern void isdn_free_channel(int di, int ch, int usage);
31extern void isdn_all_eaz(int di, int ch);
32extern int isdn_command(isdn_ctrl *);
33extern int isdn_dc2minor(int di, int ch);
34extern void isdn_info_update(void);
35extern char *isdn_map_eaz2msn(char *msn, int di);
36extern void isdn_timer_ctrl(int tf, int onoff);
37extern void isdn_unexclusive_channel(int di, int ch);
38extern int isdn_getnum(char **);
39extern int isdn_readbchan(int, int, u_char *, u_char *, int, wait_queue_head_t *);
40extern int isdn_get_free_channel(int, int, int, int, int, char *);
41extern int isdn_writebuf_skb_stub(int, int, int, struct sk_buff *);
42extern int register_isdn(isdn_if * i);
43extern int isdn_msncmp( const char *, const char *);
44extern int isdn_add_channels(isdn_driver_t *, int, int, int);
45#if defined(ISDN_DEBUG_NET_DUMP) || defined(ISDN_DEBUG_MODEM_DUMP)
46extern void isdn_dumppkt(char *, u_char *, int, int);
47#endif
diff --git a/drivers/isdn/i4l/isdn_concap.c b/drivers/isdn/i4l/isdn_concap.c
new file mode 100644
index 000000000000..83a4f5382bc2
--- /dev/null
+++ b/drivers/isdn/i4l/isdn_concap.c
@@ -0,0 +1,108 @@
1/* $Id: isdn_concap.c,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $
2 *
3 * Linux ISDN subsystem, protocol encapsulation
4 *
5 * This software may be used and distributed according to the terms
6 * of the GNU General Public License, incorporated herein by reference.
7 *
8 */
9
10/* Stuff to support the concap_proto by isdn4linux. isdn4linux - specific
11 * stuff goes here. Stuff that depends only on the concap protocol goes to
12 * another -- protocol specific -- source file.
13 *
14 */
15
16
17#include <linux/isdn.h>
18#include "isdn_x25iface.h"
19#include "isdn_net.h"
20#include <linux/concap.h>
21#include "isdn_concap.h"
22
23
24/* The following set of device service operations are for encapsulation
25 protocols that require for reliable datalink semantics. That means:
26
27 - before any data is to be submitted the connection must explicitly
28 be set up.
29 - after the successful set up of the connection is signalled the
30 connection is considered to be reliably up.
31
32 Auto-dialing ist not compatible with this requirements. Thus, auto-dialing
33 is completely bypassed.
34
35 It might be possible to implement a (non standardized) datalink protocol
36 that provides a reliable data link service while using some auto dialing
37 mechanism. Such a protocol would need an auxiliary channel (i.e. user-user-
38 signaling on the D-channel) while the B-channel is down.
39 */
40
41
42int isdn_concap_dl_data_req(struct concap_proto *concap, struct sk_buff *skb)
43{
44 struct net_device *ndev = concap -> net_dev;
45 isdn_net_dev *nd = ((isdn_net_local *) ndev->priv)->netdev;
46 isdn_net_local *lp = isdn_net_get_locked_lp(nd);
47
48 IX25DEBUG( "isdn_concap_dl_data_req: %s \n", concap->net_dev->name);
49 if (!lp) {
50 IX25DEBUG( "isdn_concap_dl_data_req: %s : isdn_net_send_skb returned %d\n", concap -> net_dev -> name, 1);
51 return 1;
52 }
53 lp->huptimer = 0;
54 isdn_net_writebuf_skb(lp, skb);
55 spin_unlock_bh(&lp->xmit_lock);
56 IX25DEBUG( "isdn_concap_dl_data_req: %s : isdn_net_send_skb returned %d\n", concap -> net_dev -> name, 0);
57 return 0;
58}
59
60
61int isdn_concap_dl_connect_req(struct concap_proto *concap)
62{
63 struct net_device *ndev = concap -> net_dev;
64 isdn_net_local *lp = (isdn_net_local *) ndev->priv;
65 int ret;
66 IX25DEBUG( "isdn_concap_dl_connect_req: %s \n", ndev -> name);
67
68 /* dial ... */
69 ret = isdn_net_dial_req( lp );
70 if ( ret ) IX25DEBUG("dialing failed\n");
71 return ret;
72}
73
74int isdn_concap_dl_disconn_req(struct concap_proto *concap)
75{
76 IX25DEBUG( "isdn_concap_dl_disconn_req: %s \n", concap -> net_dev -> name);
77
78 isdn_net_hangup( concap -> net_dev );
79 return 0;
80}
81
82struct concap_device_ops isdn_concap_reliable_dl_dops = {
83 &isdn_concap_dl_data_req,
84 &isdn_concap_dl_connect_req,
85 &isdn_concap_dl_disconn_req
86};
87
88struct concap_device_ops isdn_concap_demand_dial_dops = {
89 NULL, /* set this first entry to something like &isdn_net_start_xmit,
90 but the entry part of the current isdn_net_start_xmit must be
91 separated first. */
92 /* no connection control for demand dial semantics */
93 NULL,
94 NULL,
95};
96
97/* The following should better go into a dedicated source file such that
98 this sourcefile does not need to include any protocol specific header
99 files. For now:
100 */
101struct concap_proto * isdn_concap_new( int encap )
102{
103 switch ( encap ) {
104 case ISDN_NET_ENCAP_X25IFACE:
105 return isdn_x25iface_proto_new();
106 }
107 return NULL;
108}
diff --git a/drivers/isdn/i4l/isdn_concap.h b/drivers/isdn/i4l/isdn_concap.h
new file mode 100644
index 000000000000..306eb180438f
--- /dev/null
+++ b/drivers/isdn/i4l/isdn_concap.h
@@ -0,0 +1,14 @@
1/* $Id: isdn_concap.h,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $
2 *
3 * Linux ISDN subsystem, protocol encapsulation
4 *
5 * This software may be used and distributed according to the terms
6 * of the GNU General Public License, incorporated herein by reference.
7 *
8 */
9
10extern struct concap_device_ops isdn_concap_reliable_dl_dops;
11extern struct concap_device_ops isdn_concap_demand_dial_dops;
12extern struct concap_proto * isdn_concap_new( int );
13
14
diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c
new file mode 100644
index 000000000000..e2b790e34510
--- /dev/null
+++ b/drivers/isdn/i4l/isdn_net.c
@@ -0,0 +1,3222 @@
1/* $Id: isdn_net.c,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $
2 *
3 * Linux ISDN subsystem, network interfaces and related functions (linklevel).
4 *
5 * Copyright 1994-1998 by Fritz Elfert (fritz@isdn4linux.de)
6 * Copyright 1995,96 by Thinking Objects Software GmbH Wuerzburg
7 * Copyright 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.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.
11 *
12 * Data Over Voice (DOV) support added - Guy Ellis 23-Mar-02
13 * guy@traverse.com.au
14 * Outgoing calls - looks for a 'V' in first char of dialed number
15 * Incoming calls - checks first character of eaz as follows:
16 * Numeric - accept DATA only - original functionality
17 * 'V' - accept VOICE (DOV) only
18 * 'B' - accept BOTH DATA and DOV types
19 *
20 * Jan 2001: fix CISCO HDLC Bjoern A. Zeeb <i4l@zabbadoz.net>
21 * for info on the protocol, see
22 * http://i4l.zabbadoz.net/i4l/cisco-hdlc.txt
23 */
24
25#include <linux/config.h>
26#include <linux/isdn.h>
27#include <net/arp.h>
28#include <net/dst.h>
29#include <net/pkt_sched.h>
30#include <linux/inetdevice.h>
31#include "isdn_common.h"
32#include "isdn_net.h"
33#ifdef CONFIG_ISDN_PPP
34#include "isdn_ppp.h"
35#endif
36#ifdef CONFIG_ISDN_X25
37#include <linux/concap.h>
38#include "isdn_concap.h"
39#endif
40
41
42/*
43 * Outline of new tbusy handling:
44 *
45 * Old method, roughly spoken, consisted of setting tbusy when entering
46 * isdn_net_start_xmit() and at several other locations and clearing
47 * it from isdn_net_start_xmit() thread when sending was successful.
48 *
49 * With 2.3.x multithreaded network core, to prevent problems, tbusy should
50 * only be set by the isdn_net_start_xmit() thread and only when a tx-busy
51 * condition is detected. Other threads (in particular isdn_net_stat_callb())
52 * are only allowed to clear tbusy.
53 *
54 * -HE
55 */
56
57/*
58 * About SOFTNET:
59 * Most of the changes were pretty obvious and basically done by HE already.
60 *
61 * One problem of the isdn net device code is that is uses struct net_device
62 * for masters and slaves. However, only master interface are registered to
63 * the network layer, and therefore, it only makes sense to call netif_*
64 * functions on them.
65 *
66 * --KG
67 */
68
69/*
70 * Find out if the netdevice has been ifup-ed yet.
71 * For slaves, look at the corresponding master.
72 */
73static __inline__ int isdn_net_device_started(isdn_net_dev *n)
74{
75 isdn_net_local *lp = n->local;
76 struct net_device *dev;
77
78 if (lp->master)
79 dev = lp->master;
80 else
81 dev = &n->dev;
82 return netif_running(dev);
83}
84
85/*
86 * wake up the network -> net_device queue.
87 * For slaves, wake the corresponding master interface.
88 */
89static __inline__ void isdn_net_device_wake_queue(isdn_net_local *lp)
90{
91 if (lp->master)
92 netif_wake_queue(lp->master);
93 else
94 netif_wake_queue(&lp->netdev->dev);
95}
96
97/*
98 * stop the network -> net_device queue.
99 * For slaves, stop the corresponding master interface.
100 */
101static __inline__ void isdn_net_device_stop_queue(isdn_net_local *lp)
102{
103 if (lp->master)
104 netif_stop_queue(lp->master);
105 else
106 netif_stop_queue(&lp->netdev->dev);
107}
108
109/*
110 * find out if the net_device which this lp belongs to (lp can be
111 * master or slave) is busy. It's busy iff all (master and slave)
112 * queues are busy
113 */
114static __inline__ int isdn_net_device_busy(isdn_net_local *lp)
115{
116 isdn_net_local *nlp;
117 isdn_net_dev *nd;
118 unsigned long flags;
119
120 if (!isdn_net_lp_busy(lp))
121 return 0;
122
123 if (lp->master)
124 nd = ((isdn_net_local *) lp->master->priv)->netdev;
125 else
126 nd = lp->netdev;
127
128 spin_lock_irqsave(&nd->queue_lock, flags);
129 nlp = lp->next;
130 while (nlp != lp) {
131 if (!isdn_net_lp_busy(nlp)) {
132 spin_unlock_irqrestore(&nd->queue_lock, flags);
133 return 0;
134 }
135 nlp = nlp->next;
136 }
137 spin_unlock_irqrestore(&nd->queue_lock, flags);
138 return 1;
139}
140
141static __inline__ void isdn_net_inc_frame_cnt(isdn_net_local *lp)
142{
143 atomic_inc(&lp->frame_cnt);
144 if (isdn_net_device_busy(lp))
145 isdn_net_device_stop_queue(lp);
146}
147
148static __inline__ void isdn_net_dec_frame_cnt(isdn_net_local *lp)
149{
150 atomic_dec(&lp->frame_cnt);
151
152 if (!(isdn_net_device_busy(lp))) {
153 if (!skb_queue_empty(&lp->super_tx_queue)) {
154 schedule_work(&lp->tqueue);
155 } else {
156 isdn_net_device_wake_queue(lp);
157 }
158 }
159}
160
161static __inline__ void isdn_net_zero_frame_cnt(isdn_net_local *lp)
162{
163 atomic_set(&lp->frame_cnt, 0);
164}
165
166/* For 2.2.x we leave the transmitter busy timeout at 2 secs, just
167 * to be safe.
168 * For 2.3.x we push it up to 20 secs, because call establishment
169 * (in particular callback) may take such a long time, and we
170 * don't want confusing messages in the log. However, there is a slight
171 * possibility that this large timeout will break other things like MPPP,
172 * which might rely on the tx timeout. If so, we'll find out this way...
173 */
174
175#define ISDN_NET_TX_TIMEOUT (20*HZ)
176
177/* Prototypes */
178
179int isdn_net_force_dial_lp(isdn_net_local *);
180static int isdn_net_start_xmit(struct sk_buff *, struct net_device *);
181
182static void isdn_net_ciscohdlck_connected(isdn_net_local *lp);
183static void isdn_net_ciscohdlck_disconnected(isdn_net_local *lp);
184
185char *isdn_net_revision = "$Revision: 1.1.2.2 $";
186
187 /*
188 * Code for raw-networking over ISDN
189 */
190
191static void
192isdn_net_unreachable(struct net_device *dev, struct sk_buff *skb, char *reason)
193{
194 if(skb) {
195
196 u_short proto = ntohs(skb->protocol);
197
198 printk(KERN_DEBUG "isdn_net: %s: %s, signalling dst_link_failure %s\n",
199 dev->name,
200 (reason != NULL) ? reason : "unknown",
201 (proto != ETH_P_IP) ? "Protocol != ETH_P_IP" : "");
202
203 dst_link_failure(skb);
204 }
205 else { /* dial not triggered by rawIP packet */
206 printk(KERN_DEBUG "isdn_net: %s: %s\n",
207 dev->name,
208 (reason != NULL) ? reason : "reason unknown");
209 }
210}
211
212static void
213isdn_net_reset(struct net_device *dev)
214{
215#ifdef CONFIG_ISDN_X25
216 struct concap_device_ops * dops =
217 ( (isdn_net_local *) dev->priv ) -> dops;
218 struct concap_proto * cprot =
219 ( (isdn_net_local *) dev->priv ) -> netdev -> cprot;
220#endif
221#ifdef CONFIG_ISDN_X25
222 if( cprot && cprot -> pops && dops )
223 cprot -> pops -> restart ( cprot, dev, dops );
224#endif
225}
226
227/* Open/initialize the board. */
228static int
229isdn_net_open(struct net_device *dev)
230{
231 int i;
232 struct net_device *p;
233 struct in_device *in_dev;
234
235 /* moved here from isdn_net_reset, because only the master has an
236 interface associated which is supposed to be started. BTW:
237 we need to call netif_start_queue, not netif_wake_queue here */
238 netif_start_queue(dev);
239
240 isdn_net_reset(dev);
241 /* Fill in the MAC-level header (not needed, but for compatibility... */
242 for (i = 0; i < ETH_ALEN - sizeof(u32); i++)
243 dev->dev_addr[i] = 0xfc;
244 if ((in_dev = dev->ip_ptr) != NULL) {
245 /*
246 * Any address will do - we take the first
247 */
248 struct in_ifaddr *ifa = in_dev->ifa_list;
249 if (ifa != NULL)
250 memcpy(dev->dev_addr+2, &ifa->ifa_local, 4);
251 }
252
253 /* If this interface has slaves, start them also */
254
255 if ((p = (((isdn_net_local *) dev->priv)->slave))) {
256 while (p) {
257 isdn_net_reset(p);
258 p = (((isdn_net_local *) p->priv)->slave);
259 }
260 }
261 isdn_lock_drivers();
262 return 0;
263}
264
265/*
266 * Assign an ISDN-channel to a net-interface
267 */
268static void
269isdn_net_bind_channel(isdn_net_local * lp, int idx)
270{
271 lp->flags |= ISDN_NET_CONNECTED;
272 lp->isdn_device = dev->drvmap[idx];
273 lp->isdn_channel = dev->chanmap[idx];
274 dev->rx_netdev[idx] = lp->netdev;
275 dev->st_netdev[idx] = lp->netdev;
276}
277
278/*
279 * unbind a net-interface (resets interface after an error)
280 */
281static void
282isdn_net_unbind_channel(isdn_net_local * lp)
283{
284 skb_queue_purge(&lp->super_tx_queue);
285
286 if (!lp->master) { /* reset only master device */
287 /* Moral equivalent of dev_purge_queues():
288 BEWARE! This chunk of code cannot be called from hardware
289 interrupt handler. I hope it is true. --ANK
290 */
291 qdisc_reset(lp->netdev->dev.qdisc);
292 }
293 lp->dialstate = 0;
294 dev->rx_netdev[isdn_dc2minor(lp->isdn_device, lp->isdn_channel)] = NULL;
295 dev->st_netdev[isdn_dc2minor(lp->isdn_device, lp->isdn_channel)] = NULL;
296 isdn_free_channel(lp->isdn_device, lp->isdn_channel, ISDN_USAGE_NET);
297 lp->flags &= ~ISDN_NET_CONNECTED;
298 lp->isdn_device = -1;
299 lp->isdn_channel = -1;
300}
301
302/*
303 * Perform auto-hangup and cps-calculation for net-interfaces.
304 *
305 * auto-hangup:
306 * Increment idle-counter (this counter is reset on any incoming or
307 * outgoing packet), if counter exceeds configured limit either do a
308 * hangup immediately or - if configured - wait until just before the next
309 * charge-info.
310 *
311 * cps-calculation (needed for dynamic channel-bundling):
312 * Since this function is called every second, simply reset the
313 * byte-counter of the interface after copying it to the cps-variable.
314 */
315unsigned long last_jiffies = -HZ;
316
317void
318isdn_net_autohup(void)
319{
320 isdn_net_dev *p = dev->netdev;
321 int anymore;
322
323 anymore = 0;
324 while (p) {
325 isdn_net_local *l = p->local;
326 if (jiffies == last_jiffies)
327 l->cps = l->transcount;
328 else
329 l->cps = (l->transcount * HZ) / (jiffies - last_jiffies);
330 l->transcount = 0;
331 if (dev->net_verbose > 3)
332 printk(KERN_DEBUG "%s: %d bogocps\n", l->name, l->cps);
333 if ((l->flags & ISDN_NET_CONNECTED) && (!l->dialstate)) {
334 anymore = 1;
335 l->huptimer++;
336 /*
337 * if there is some dialmode where timeout-hangup
338 * should _not_ be done, check for that here
339 */
340 if ((l->onhtime) &&
341 (l->huptimer > l->onhtime))
342 {
343 if (l->hupflags & ISDN_MANCHARGE &&
344 l->hupflags & ISDN_CHARGEHUP) {
345 while (time_after(jiffies, l->chargetime + l->chargeint))
346 l->chargetime += l->chargeint;
347 if (time_after(jiffies, l->chargetime + l->chargeint - 2 * HZ))
348 if (l->outgoing || l->hupflags & ISDN_INHUP)
349 isdn_net_hangup(&p->dev);
350 } else if (l->outgoing) {
351 if (l->hupflags & ISDN_CHARGEHUP) {
352 if (l->hupflags & ISDN_WAITCHARGE) {
353 printk(KERN_DEBUG "isdn_net: Hupflags of %s are %X\n",
354 l->name, l->hupflags);
355 isdn_net_hangup(&p->dev);
356 } else if (time_after(jiffies, l->chargetime + l->chargeint)) {
357 printk(KERN_DEBUG
358 "isdn_net: %s: chtime = %lu, chint = %d\n",
359 l->name, l->chargetime, l->chargeint);
360 isdn_net_hangup(&p->dev);
361 }
362 } else
363 isdn_net_hangup(&p->dev);
364 } else if (l->hupflags & ISDN_INHUP)
365 isdn_net_hangup(&p->dev);
366 }
367
368 if(dev->global_flags & ISDN_GLOBAL_STOPPED || (ISDN_NET_DIALMODE(*l) == ISDN_NET_DM_OFF)) {
369 isdn_net_hangup(&p->dev);
370 break;
371 }
372 }
373 p = (isdn_net_dev *) p->next;
374 }
375 last_jiffies = jiffies;
376 isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, anymore);
377}
378
379static void isdn_net_lp_disconnected(isdn_net_local *lp)
380{
381 isdn_net_rm_from_bundle(lp);
382}
383
384/*
385 * Handle status-messages from ISDN-interfacecard.
386 * This function is called from within the main-status-dispatcher
387 * isdn_status_callback, which itself is called from the low-level driver.
388 * Return: 1 = Event handled, 0 = not for us or unknown Event.
389 */
390int
391isdn_net_stat_callback(int idx, isdn_ctrl *c)
392{
393 isdn_net_dev *p = dev->st_netdev[idx];
394 int cmd = c->command;
395
396 if (p) {
397 isdn_net_local *lp = p->local;
398#ifdef CONFIG_ISDN_X25
399 struct concap_proto *cprot = lp->netdev->cprot;
400 struct concap_proto_ops *pops = cprot ? cprot->pops : NULL;
401#endif
402 switch (cmd) {
403 case ISDN_STAT_BSENT:
404 /* A packet has successfully been sent out */
405 if ((lp->flags & ISDN_NET_CONNECTED) &&
406 (!lp->dialstate)) {
407 isdn_net_dec_frame_cnt(lp);
408 lp->stats.tx_packets++;
409 lp->stats.tx_bytes += c->parm.length;
410 }
411 return 1;
412 case ISDN_STAT_DCONN:
413 /* D-Channel is up */
414 switch (lp->dialstate) {
415 case 4:
416 case 7:
417 case 8:
418 lp->dialstate++;
419 return 1;
420 case 12:
421 lp->dialstate = 5;
422 return 1;
423 }
424 break;
425 case ISDN_STAT_DHUP:
426 /* Either D-Channel-hangup or error during dialout */
427#ifdef CONFIG_ISDN_X25
428 /* If we are not connencted then dialing had
429 failed. If there are generic encap protocol
430 receiver routines signal the closure of
431 the link*/
432
433 if( !(lp->flags & ISDN_NET_CONNECTED)
434 && pops && pops -> disconn_ind )
435 pops -> disconn_ind(cprot);
436#endif /* CONFIG_ISDN_X25 */
437 if ((!lp->dialstate) && (lp->flags & ISDN_NET_CONNECTED)) {
438 if (lp->p_encap == ISDN_NET_ENCAP_CISCOHDLCK)
439 isdn_net_ciscohdlck_disconnected(lp);
440#ifdef CONFIG_ISDN_PPP
441 if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
442 isdn_ppp_free(lp);
443#endif
444 isdn_net_lp_disconnected(lp);
445 isdn_all_eaz(lp->isdn_device, lp->isdn_channel);
446 printk(KERN_INFO "%s: remote hangup\n", lp->name);
447 printk(KERN_INFO "%s: Chargesum is %d\n", lp->name,
448 lp->charge);
449 isdn_net_unbind_channel(lp);
450 return 1;
451 }
452 break;
453#ifdef CONFIG_ISDN_X25
454 case ISDN_STAT_BHUP:
455 /* B-Channel-hangup */
456 /* try if there are generic encap protocol
457 receiver routines and signal the closure of
458 the link */
459 if( pops && pops -> disconn_ind ){
460 pops -> disconn_ind(cprot);
461 return 1;
462 }
463 break;
464#endif /* CONFIG_ISDN_X25 */
465 case ISDN_STAT_BCONN:
466 /* B-Channel is up */
467 isdn_net_zero_frame_cnt(lp);
468 switch (lp->dialstate) {
469 case 5:
470 case 6:
471 case 7:
472 case 8:
473 case 9:
474 case 10:
475 case 12:
476 if (lp->dialstate <= 6) {
477 dev->usage[idx] |= ISDN_USAGE_OUTGOING;
478 isdn_info_update();
479 } else
480 dev->rx_netdev[idx] = p;
481 lp->dialstate = 0;
482 isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, 1);
483 if (lp->p_encap == ISDN_NET_ENCAP_CISCOHDLCK)
484 isdn_net_ciscohdlck_connected(lp);
485 if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP) {
486 if (lp->master) { /* is lp a slave? */
487 isdn_net_dev *nd = ((isdn_net_local *)lp->master->priv)->netdev;
488 isdn_net_add_to_bundle(nd, lp);
489 }
490 }
491 printk(KERN_INFO "isdn_net: %s connected\n", lp->name);
492 /* If first Chargeinfo comes before B-Channel connect,
493 * we correct the timestamp here.
494 */
495 lp->chargetime = jiffies;
496
497 /* reset dial-timeout */
498 lp->dialstarted = 0;
499 lp->dialwait_timer = 0;
500
501#ifdef CONFIG_ISDN_PPP
502 if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
503 isdn_ppp_wakeup_daemon(lp);
504#endif
505#ifdef CONFIG_ISDN_X25
506 /* try if there are generic concap receiver routines */
507 if( pops )
508 if( pops->connect_ind)
509 pops->connect_ind(cprot);
510#endif /* CONFIG_ISDN_X25 */
511 /* ppp needs to do negotiations first */
512 if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP)
513 isdn_net_device_wake_queue(lp);
514 return 1;
515 }
516 break;
517 case ISDN_STAT_NODCH:
518 /* No D-Channel avail. */
519 if (lp->dialstate == 4) {
520 lp->dialstate--;
521 return 1;
522 }
523 break;
524 case ISDN_STAT_CINF:
525 /* Charge-info from TelCo. Calculate interval between
526 * charge-infos and set timestamp for last info for
527 * usage by isdn_net_autohup()
528 */
529 lp->charge++;
530 if (lp->hupflags & ISDN_HAVECHARGE) {
531 lp->hupflags &= ~ISDN_WAITCHARGE;
532 lp->chargeint = jiffies - lp->chargetime - (2 * HZ);
533 }
534 if (lp->hupflags & ISDN_WAITCHARGE)
535 lp->hupflags |= ISDN_HAVECHARGE;
536 lp->chargetime = jiffies;
537 printk(KERN_DEBUG "isdn_net: Got CINF chargetime of %s now %lu\n",
538 lp->name, lp->chargetime);
539 return 1;
540 }
541 }
542 return 0;
543}
544
545/*
546 * Perform dialout for net-interfaces and timeout-handling for
547 * D-Channel-up and B-Channel-up Messages.
548 * This function is initially called from within isdn_net_start_xmit() or
549 * or isdn_net_find_icall() after initializing the dialstate for an
550 * interface. If further calls are needed, the function schedules itself
551 * for a timer-callback via isdn_timer_function().
552 * The dialstate is also affected by incoming status-messages from
553 * the ISDN-Channel which are handled in isdn_net_stat_callback() above.
554 */
555void
556isdn_net_dial(void)
557{
558 isdn_net_dev *p = dev->netdev;
559 int anymore = 0;
560 int i;
561 isdn_ctrl cmd;
562 u_char *phone_number;
563
564 while (p) {
565 isdn_net_local *lp = p->local;
566
567#ifdef ISDN_DEBUG_NET_DIAL
568 if (lp->dialstate)
569 printk(KERN_DEBUG "%s: dialstate=%d\n", lp->name, lp->dialstate);
570#endif
571 switch (lp->dialstate) {
572 case 0:
573 /* Nothing to do for this interface */
574 break;
575 case 1:
576 /* Initiate dialout. Set phone-number-pointer to first number
577 * of interface.
578 */
579 lp->dial = lp->phone[1];
580 if (!lp->dial) {
581 printk(KERN_WARNING "%s: phone number deleted?\n",
582 lp->name);
583 isdn_net_hangup(&p->dev);
584 break;
585 }
586 anymore = 1;
587
588 if(lp->dialtimeout > 0)
589 if(lp->dialstarted == 0 || time_after(jiffies, lp->dialstarted + lp->dialtimeout + lp->dialwait)) {
590 lp->dialstarted = jiffies;
591 lp->dialwait_timer = 0;
592 }
593
594 lp->dialstate++;
595 /* Fall through */
596 case 2:
597 /* Prepare dialing. Clear EAZ, then set EAZ. */
598 cmd.driver = lp->isdn_device;
599 cmd.arg = lp->isdn_channel;
600 cmd.command = ISDN_CMD_CLREAZ;
601 isdn_command(&cmd);
602 sprintf(cmd.parm.num, "%s", isdn_map_eaz2msn(lp->msn, cmd.driver));
603 cmd.command = ISDN_CMD_SETEAZ;
604 isdn_command(&cmd);
605 lp->dialretry = 0;
606 anymore = 1;
607 lp->dialstate++;
608 /* Fall through */
609 case 3:
610 /* Setup interface, dial current phone-number, switch to next number.
611 * If list of phone-numbers is exhausted, increment
612 * retry-counter.
613 */
614 if(dev->global_flags & ISDN_GLOBAL_STOPPED || (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF)) {
615 char *s;
616 if (dev->global_flags & ISDN_GLOBAL_STOPPED)
617 s = "dial suppressed: isdn system stopped";
618 else
619 s = "dial suppressed: dialmode `off'";
620 isdn_net_unreachable(&p->dev, NULL, s);
621 isdn_net_hangup(&p->dev);
622 break;
623 }
624 cmd.driver = lp->isdn_device;
625 cmd.command = ISDN_CMD_SETL2;
626 cmd.arg = lp->isdn_channel + (lp->l2_proto << 8);
627 isdn_command(&cmd);
628 cmd.driver = lp->isdn_device;
629 cmd.command = ISDN_CMD_SETL3;
630 cmd.arg = lp->isdn_channel + (lp->l3_proto << 8);
631 isdn_command(&cmd);
632 cmd.driver = lp->isdn_device;
633 cmd.arg = lp->isdn_channel;
634 if (!lp->dial) {
635 printk(KERN_WARNING "%s: phone number deleted?\n",
636 lp->name);
637 isdn_net_hangup(&p->dev);
638 break;
639 }
640 if (!strncmp(lp->dial->num, "LEASED", strlen("LEASED"))) {
641 lp->dialstate = 4;
642 printk(KERN_INFO "%s: Open leased line ...\n", lp->name);
643 } else {
644 if(lp->dialtimeout > 0)
645 if (time_after(jiffies, lp->dialstarted + lp->dialtimeout)) {
646 lp->dialwait_timer = jiffies + lp->dialwait;
647 lp->dialstarted = 0;
648 isdn_net_unreachable(&p->dev, NULL, "dial: timed out");
649 isdn_net_hangup(&p->dev);
650 break;
651 }
652
653 cmd.driver = lp->isdn_device;
654 cmd.command = ISDN_CMD_DIAL;
655 cmd.parm.setup.si2 = 0;
656
657 /* check for DOV */
658 phone_number = lp->dial->num;
659 if ((*phone_number == 'v') ||
660 (*phone_number == 'V')) { /* DOV call */
661 cmd.parm.setup.si1 = 1;
662 } else { /* DATA call */
663 cmd.parm.setup.si1 = 7;
664 }
665
666 strcpy(cmd.parm.setup.phone, phone_number);
667 /*
668 * Switch to next number or back to start if at end of list.
669 */
670 if (!(lp->dial = (isdn_net_phone *) lp->dial->next)) {
671 lp->dial = lp->phone[1];
672 lp->dialretry++;
673
674 if (lp->dialretry > lp->dialmax) {
675 if (lp->dialtimeout == 0) {
676 lp->dialwait_timer = jiffies + lp->dialwait;
677 lp->dialstarted = 0;
678 isdn_net_unreachable(&p->dev, NULL, "dial: tried all numbers dialmax times");
679 }
680 isdn_net_hangup(&p->dev);
681 break;
682 }
683 }
684 sprintf(cmd.parm.setup.eazmsn, "%s",
685 isdn_map_eaz2msn(lp->msn, cmd.driver));
686 i = isdn_dc2minor(lp->isdn_device, lp->isdn_channel);
687 if (i >= 0) {
688 strcpy(dev->num[i], cmd.parm.setup.phone);
689 dev->usage[i] |= ISDN_USAGE_OUTGOING;
690 isdn_info_update();
691 }
692 printk(KERN_INFO "%s: dialing %d %s... %s\n", lp->name,
693 lp->dialretry, cmd.parm.setup.phone,
694 (cmd.parm.setup.si1 == 1) ? "DOV" : "");
695 lp->dtimer = 0;
696#ifdef ISDN_DEBUG_NET_DIAL
697 printk(KERN_DEBUG "dial: d=%d c=%d\n", lp->isdn_device,
698 lp->isdn_channel);
699#endif
700 isdn_command(&cmd);
701 }
702 lp->huptimer = 0;
703 lp->outgoing = 1;
704 if (lp->chargeint) {
705 lp->hupflags |= ISDN_HAVECHARGE;
706 lp->hupflags &= ~ISDN_WAITCHARGE;
707 } else {
708 lp->hupflags |= ISDN_WAITCHARGE;
709 lp->hupflags &= ~ISDN_HAVECHARGE;
710 }
711 anymore = 1;
712 lp->dialstate =
713 (lp->cbdelay &&
714 (lp->flags & ISDN_NET_CBOUT)) ? 12 : 4;
715 break;
716 case 4:
717 /* Wait for D-Channel-connect.
718 * If timeout, switch back to state 3.
719 * Dialmax-handling moved to state 3.
720 */
721 if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT10)
722 lp->dialstate = 3;
723 anymore = 1;
724 break;
725 case 5:
726 /* Got D-Channel-Connect, send B-Channel-request */
727 cmd.driver = lp->isdn_device;
728 cmd.arg = lp->isdn_channel;
729 cmd.command = ISDN_CMD_ACCEPTB;
730 anymore = 1;
731 lp->dtimer = 0;
732 lp->dialstate++;
733 isdn_command(&cmd);
734 break;
735 case 6:
736 /* Wait for B- or D-Channel-connect. If timeout,
737 * switch back to state 3.
738 */
739#ifdef ISDN_DEBUG_NET_DIAL
740 printk(KERN_DEBUG "dialtimer2: %d\n", lp->dtimer);
741#endif
742 if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT10)
743 lp->dialstate = 3;
744 anymore = 1;
745 break;
746 case 7:
747 /* Got incoming Call, setup L2 and L3 protocols,
748 * then wait for D-Channel-connect
749 */
750#ifdef ISDN_DEBUG_NET_DIAL
751 printk(KERN_DEBUG "dialtimer4: %d\n", lp->dtimer);
752#endif
753 cmd.driver = lp->isdn_device;
754 cmd.command = ISDN_CMD_SETL2;
755 cmd.arg = lp->isdn_channel + (lp->l2_proto << 8);
756 isdn_command(&cmd);
757 cmd.driver = lp->isdn_device;
758 cmd.command = ISDN_CMD_SETL3;
759 cmd.arg = lp->isdn_channel + (lp->l3_proto << 8);
760 isdn_command(&cmd);
761 if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT15)
762 isdn_net_hangup(&p->dev);
763 else {
764 anymore = 1;
765 lp->dialstate++;
766 }
767 break;
768 case 9:
769 /* Got incoming D-Channel-Connect, send B-Channel-request */
770 cmd.driver = lp->isdn_device;
771 cmd.arg = lp->isdn_channel;
772 cmd.command = ISDN_CMD_ACCEPTB;
773 isdn_command(&cmd);
774 anymore = 1;
775 lp->dtimer = 0;
776 lp->dialstate++;
777 break;
778 case 8:
779 case 10:
780 /* Wait for B- or D-channel-connect */
781#ifdef ISDN_DEBUG_NET_DIAL
782 printk(KERN_DEBUG "dialtimer4: %d\n", lp->dtimer);
783#endif
784 if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT10)
785 isdn_net_hangup(&p->dev);
786 else
787 anymore = 1;
788 break;
789 case 11:
790 /* Callback Delay */
791 if (lp->dtimer++ > lp->cbdelay)
792 lp->dialstate = 1;
793 anymore = 1;
794 break;
795 case 12:
796 /* Remote does callback. Hangup after cbdelay, then wait for incoming
797 * call (in state 4).
798 */
799 if (lp->dtimer++ > lp->cbdelay)
800 {
801 printk(KERN_INFO "%s: hangup waiting for callback ...\n", lp->name);
802 lp->dtimer = 0;
803 lp->dialstate = 4;
804 cmd.driver = lp->isdn_device;
805 cmd.command = ISDN_CMD_HANGUP;
806 cmd.arg = lp->isdn_channel;
807 isdn_command(&cmd);
808 isdn_all_eaz(lp->isdn_device, lp->isdn_channel);
809 }
810 anymore = 1;
811 break;
812 default:
813 printk(KERN_WARNING "isdn_net: Illegal dialstate %d for device %s\n",
814 lp->dialstate, lp->name);
815 }
816 p = (isdn_net_dev *) p->next;
817 }
818 isdn_timer_ctrl(ISDN_TIMER_NETDIAL, anymore);
819}
820
821/*
822 * Perform hangup for a net-interface.
823 */
824void
825isdn_net_hangup(struct net_device *d)
826{
827 isdn_net_local *lp = (isdn_net_local *) d->priv;
828 isdn_ctrl cmd;
829#ifdef CONFIG_ISDN_X25
830 struct concap_proto *cprot = lp->netdev->cprot;
831 struct concap_proto_ops *pops = cprot ? cprot->pops : NULL;
832#endif
833
834 if (lp->flags & ISDN_NET_CONNECTED) {
835 if (lp->slave != NULL) {
836 isdn_net_local *slp = (isdn_net_local *)lp->slave->priv;
837 if (slp->flags & ISDN_NET_CONNECTED) {
838 printk(KERN_INFO
839 "isdn_net: hang up slave %s before %s\n",
840 slp->name, lp->name);
841 isdn_net_hangup(lp->slave);
842 }
843 }
844 printk(KERN_INFO "isdn_net: local hangup %s\n", lp->name);
845#ifdef CONFIG_ISDN_PPP
846 if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
847 isdn_ppp_free(lp);
848#endif
849 isdn_net_lp_disconnected(lp);
850#ifdef CONFIG_ISDN_X25
851 /* try if there are generic encap protocol
852 receiver routines and signal the closure of
853 the link */
854 if( pops && pops -> disconn_ind )
855 pops -> disconn_ind(cprot);
856#endif /* CONFIG_ISDN_X25 */
857
858 cmd.driver = lp->isdn_device;
859 cmd.command = ISDN_CMD_HANGUP;
860 cmd.arg = lp->isdn_channel;
861 isdn_command(&cmd);
862 printk(KERN_INFO "%s: Chargesum is %d\n", lp->name, lp->charge);
863 isdn_all_eaz(lp->isdn_device, lp->isdn_channel);
864 }
865 isdn_net_unbind_channel(lp);
866}
867
868typedef struct {
869 unsigned short source;
870 unsigned short dest;
871} ip_ports;
872
873static void
874isdn_net_log_skb(struct sk_buff * skb, isdn_net_local * lp)
875{
876 u_char *p = skb->nh.raw; /* hopefully, this was set correctly */
877 unsigned short proto = ntohs(skb->protocol);
878 int data_ofs;
879 ip_ports *ipp;
880 char addinfo[100];
881
882 addinfo[0] = '\0';
883 /* This check stolen from 2.1.72 dev_queue_xmit_nit() */
884 if (skb->nh.raw < skb->data || skb->nh.raw >= skb->tail) {
885 /* fall back to old isdn_net_log_packet method() */
886 char * buf = skb->data;
887
888 printk(KERN_DEBUG "isdn_net: protocol %04x is buggy, dev %s\n", skb->protocol, lp->name);
889 p = buf;
890 proto = ETH_P_IP;
891 switch (lp->p_encap) {
892 case ISDN_NET_ENCAP_IPTYP:
893 proto = ntohs(*(unsigned short *) &buf[0]);
894 p = &buf[2];
895 break;
896 case ISDN_NET_ENCAP_ETHER:
897 proto = ntohs(*(unsigned short *) &buf[12]);
898 p = &buf[14];
899 break;
900 case ISDN_NET_ENCAP_CISCOHDLC:
901 proto = ntohs(*(unsigned short *) &buf[2]);
902 p = &buf[4];
903 break;
904#ifdef CONFIG_ISDN_PPP
905 case ISDN_NET_ENCAP_SYNCPPP:
906 proto = ntohs(skb->protocol);
907 p = &buf[IPPP_MAX_HEADER];
908 break;
909#endif
910 }
911 }
912 data_ofs = ((p[0] & 15) * 4);
913 switch (proto) {
914 case ETH_P_IP:
915 switch (p[9]) {
916 case 1:
917 strcpy(addinfo, " ICMP");
918 break;
919 case 2:
920 strcpy(addinfo, " IGMP");
921 break;
922 case 4:
923 strcpy(addinfo, " IPIP");
924 break;
925 case 6:
926 ipp = (ip_ports *) (&p[data_ofs]);
927 sprintf(addinfo, " TCP, port: %d -> %d", ntohs(ipp->source),
928 ntohs(ipp->dest));
929 break;
930 case 8:
931 strcpy(addinfo, " EGP");
932 break;
933 case 12:
934 strcpy(addinfo, " PUP");
935 break;
936 case 17:
937 ipp = (ip_ports *) (&p[data_ofs]);
938 sprintf(addinfo, " UDP, port: %d -> %d", ntohs(ipp->source),
939 ntohs(ipp->dest));
940 break;
941 case 22:
942 strcpy(addinfo, " IDP");
943 break;
944 }
945 printk(KERN_INFO
946 "OPEN: %d.%d.%d.%d -> %d.%d.%d.%d%s\n",
947
948 p[12], p[13], p[14], p[15],
949 p[16], p[17], p[18], p[19],
950 addinfo);
951 break;
952 case ETH_P_ARP:
953 printk(KERN_INFO
954 "OPEN: ARP %d.%d.%d.%d -> *.*.*.* ?%d.%d.%d.%d\n",
955 p[14], p[15], p[16], p[17],
956 p[24], p[25], p[26], p[27]);
957 break;
958 }
959}
960
961/*
962 * this function is used to send supervisory data, i.e. data which was
963 * not received from the network layer, but e.g. frames from ipppd, CCP
964 * reset frames etc.
965 */
966void isdn_net_write_super(isdn_net_local *lp, struct sk_buff *skb)
967{
968 if (in_irq()) {
969 // we can't grab the lock from irq context,
970 // so we just queue the packet
971 skb_queue_tail(&lp->super_tx_queue, skb);
972 schedule_work(&lp->tqueue);
973 return;
974 }
975
976 spin_lock_bh(&lp->xmit_lock);
977 if (!isdn_net_lp_busy(lp)) {
978 isdn_net_writebuf_skb(lp, skb);
979 } else {
980 skb_queue_tail(&lp->super_tx_queue, skb);
981 }
982 spin_unlock_bh(&lp->xmit_lock);
983}
984
985/*
986 * called from tq_immediate
987 */
988static void isdn_net_softint(void *private)
989{
990 isdn_net_local *lp = private;
991 struct sk_buff *skb;
992
993 spin_lock_bh(&lp->xmit_lock);
994 while (!isdn_net_lp_busy(lp)) {
995 skb = skb_dequeue(&lp->super_tx_queue);
996 if (!skb)
997 break;
998 isdn_net_writebuf_skb(lp, skb);
999 }
1000 spin_unlock_bh(&lp->xmit_lock);
1001}
1002
1003/*
1004 * all frames sent from the (net) LL to a HL driver should go via this function
1005 * it's serialized by the caller holding the lp->xmit_lock spinlock
1006 */
1007void isdn_net_writebuf_skb(isdn_net_local *lp, struct sk_buff *skb)
1008{
1009 int ret;
1010 int len = skb->len; /* save len */
1011
1012 /* before obtaining the lock the caller should have checked that
1013 the lp isn't busy */
1014 if (isdn_net_lp_busy(lp)) {
1015 printk("isdn BUG at %s:%d!\n", __FILE__, __LINE__);
1016 goto error;
1017 }
1018
1019 if (!(lp->flags & ISDN_NET_CONNECTED)) {
1020 printk("isdn BUG at %s:%d!\n", __FILE__, __LINE__);
1021 goto error;
1022 }
1023 ret = isdn_writebuf_skb_stub(lp->isdn_device, lp->isdn_channel, 1, skb);
1024 if (ret != len) {
1025 /* we should never get here */
1026 printk(KERN_WARNING "%s: HL driver queue full\n", lp->name);
1027 goto error;
1028 }
1029
1030 lp->transcount += len;
1031 isdn_net_inc_frame_cnt(lp);
1032 return;
1033
1034 error:
1035 dev_kfree_skb(skb);
1036 lp->stats.tx_errors++;
1037
1038}
1039
1040
1041/*
1042 * Helper function for isdn_net_start_xmit.
1043 * When called, the connection is already established.
1044 * Based on cps-calculation, check if device is overloaded.
1045 * If so, and if a slave exists, trigger dialing for it.
1046 * If any slave is online, deliver packets using a simple round robin
1047 * scheme.
1048 *
1049 * Return: 0 on success, !0 on failure.
1050 */
1051
1052static int
1053isdn_net_xmit(struct net_device *ndev, struct sk_buff *skb)
1054{
1055 isdn_net_dev *nd;
1056 isdn_net_local *slp;
1057 isdn_net_local *lp = (isdn_net_local *) ndev->priv;
1058 int retv = 0;
1059
1060 if (((isdn_net_local *) (ndev->priv))->master) {
1061 printk("isdn BUG at %s:%d!\n", __FILE__, __LINE__);
1062 dev_kfree_skb(skb);
1063 return 0;
1064 }
1065
1066 /* For the other encaps the header has already been built */
1067#ifdef CONFIG_ISDN_PPP
1068 if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) {
1069 return isdn_ppp_xmit(skb, ndev);
1070 }
1071#endif
1072 nd = ((isdn_net_local *) ndev->priv)->netdev;
1073 lp = isdn_net_get_locked_lp(nd);
1074 if (!lp) {
1075 printk(KERN_WARNING "%s: all channels busy - requeuing!\n", ndev->name);
1076 return 1;
1077 }
1078 /* we have our lp locked from now on */
1079
1080 /* Reset hangup-timeout */
1081 lp->huptimer = 0; // FIXME?
1082 isdn_net_writebuf_skb(lp, skb);
1083 spin_unlock_bh(&lp->xmit_lock);
1084
1085 /* the following stuff is here for backwards compatibility.
1086 * in future, start-up and hangup of slaves (based on current load)
1087 * should move to userspace and get based on an overall cps
1088 * calculation
1089 */
1090 if (lp->cps > lp->triggercps) {
1091 if (lp->slave) {
1092 if (!lp->sqfull) {
1093 /* First time overload: set timestamp only */
1094 lp->sqfull = 1;
1095 lp->sqfull_stamp = jiffies;
1096 } else {
1097 /* subsequent overload: if slavedelay exceeded, start dialing */
1098 if (time_after(jiffies, lp->sqfull_stamp + lp->slavedelay)) {
1099 slp = lp->slave->priv;
1100 if (!(slp->flags & ISDN_NET_CONNECTED)) {
1101 isdn_net_force_dial_lp((isdn_net_local *) lp->slave->priv);
1102 }
1103 }
1104 }
1105 }
1106 } else {
1107 if (lp->sqfull && time_after(jiffies, lp->sqfull_stamp + lp->slavedelay + (10 * HZ))) {
1108 lp->sqfull = 0;
1109 }
1110 /* this is a hack to allow auto-hangup for slaves on moderate loads */
1111 nd->queue = nd->local;
1112 }
1113
1114 return retv;
1115
1116}
1117
1118static void
1119isdn_net_adjust_hdr(struct sk_buff *skb, struct net_device *dev)
1120{
1121 isdn_net_local *lp = (isdn_net_local *) dev->priv;
1122 if (!skb)
1123 return;
1124 if (lp->p_encap == ISDN_NET_ENCAP_ETHER) {
1125 int pullsize = (ulong)skb->nh.raw - (ulong)skb->data - ETH_HLEN;
1126 if (pullsize > 0) {
1127 printk(KERN_DEBUG "isdn_net: Pull junk %d\n", pullsize);
1128 skb_pull(skb, pullsize);
1129 }
1130 }
1131}
1132
1133
1134void isdn_net_tx_timeout(struct net_device * ndev)
1135{
1136 isdn_net_local *lp = (isdn_net_local *) ndev->priv;
1137
1138 printk(KERN_WARNING "isdn_tx_timeout dev %s dialstate %d\n", ndev->name, lp->dialstate);
1139 if (!lp->dialstate){
1140 lp->stats.tx_errors++;
1141 /*
1142 * There is a certain probability that this currently
1143 * works at all because if we always wake up the interface,
1144 * then upper layer will try to send the next packet
1145 * immediately. And then, the old clean_up logic in the
1146 * driver will hopefully continue to work as it used to do.
1147 *
1148 * This is rather primitive right know, we better should
1149 * clean internal queues here, in particular for multilink and
1150 * ppp, and reset HL driver's channel, too. --HE
1151 *
1152 * actually, this may not matter at all, because ISDN hardware
1153 * should not see transmitter hangs at all IMO
1154 * changed KERN_DEBUG to KERN_WARNING to find out if this is
1155 * ever called --KG
1156 */
1157 }
1158 ndev->trans_start = jiffies;
1159 netif_wake_queue(ndev);
1160}
1161
1162/*
1163 * Try sending a packet.
1164 * If this interface isn't connected to a ISDN-Channel, find a free channel,
1165 * and start dialing.
1166 */
1167static int
1168isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
1169{
1170 isdn_net_local *lp = (isdn_net_local *) ndev->priv;
1171#ifdef CONFIG_ISDN_X25
1172 struct concap_proto * cprot = lp -> netdev -> cprot;
1173/* At this point hard_start_xmit() passes control to the encapsulation
1174 protocol (if present).
1175 For X.25 auto-dialing is completly bypassed because:
1176 - It does not conform with the semantics of a reliable datalink
1177 service as needed by X.25 PLP.
1178 - I don't want that the interface starts dialing when the network layer
1179 sends a message which requests to disconnect the lapb link (or if it
1180 sends any other message not resulting in data transmission).
1181 Instead, dialing will be initiated by the encapsulation protocol entity
1182 when a dl_establish request is received from the upper layer.
1183*/
1184 if (cprot && cprot -> pops) {
1185 int ret = cprot -> pops -> encap_and_xmit ( cprot , skb);
1186
1187 if (ret)
1188 netif_stop_queue(ndev);
1189 return ret;
1190 } else
1191#endif
1192 /* auto-dialing xmit function */
1193 {
1194#ifdef ISDN_DEBUG_NET_DUMP
1195 u_char *buf;
1196#endif
1197 isdn_net_adjust_hdr(skb, ndev);
1198#ifdef ISDN_DEBUG_NET_DUMP
1199 buf = skb->data;
1200 isdn_dumppkt("S:", buf, skb->len, 40);
1201#endif
1202
1203 if (!(lp->flags & ISDN_NET_CONNECTED)) {
1204 int chi;
1205 /* only do autodial if allowed by config */
1206 if (!(ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_AUTO)) {
1207 isdn_net_unreachable(ndev, skb, "dial rejected: interface not in dialmode `auto'");
1208 dev_kfree_skb(skb);
1209 return 0;
1210 }
1211 if (lp->phone[1]) {
1212 ulong flags;
1213
1214 if(lp->dialwait_timer <= 0)
1215 if(lp->dialstarted > 0 && lp->dialtimeout > 0 && time_before(jiffies, lp->dialstarted + lp->dialtimeout + lp->dialwait))
1216 lp->dialwait_timer = lp->dialstarted + lp->dialtimeout + lp->dialwait;
1217
1218 if(lp->dialwait_timer > 0) {
1219 if(time_before(jiffies, lp->dialwait_timer)) {
1220 isdn_net_unreachable(ndev, skb, "dial rejected: retry-time not reached");
1221 dev_kfree_skb(skb);
1222 return 0;
1223 } else
1224 lp->dialwait_timer = 0;
1225 }
1226 /* Grab a free ISDN-Channel */
1227 spin_lock_irqsave(&dev->lock, flags);
1228 if (((chi =
1229 isdn_get_free_channel(
1230 ISDN_USAGE_NET,
1231 lp->l2_proto,
1232 lp->l3_proto,
1233 lp->pre_device,
1234 lp->pre_channel,
1235 lp->msn)
1236 ) < 0) &&
1237 ((chi =
1238 isdn_get_free_channel(
1239 ISDN_USAGE_NET,
1240 lp->l2_proto,
1241 lp->l3_proto,
1242 lp->pre_device,
1243 lp->pre_channel^1,
1244 lp->msn)
1245 ) < 0)) {
1246 spin_unlock_irqrestore(&dev->lock, flags);
1247 isdn_net_unreachable(ndev, skb,
1248 "No channel");
1249 dev_kfree_skb(skb);
1250 return 0;
1251 }
1252 /* Log packet, which triggered dialing */
1253 if (dev->net_verbose)
1254 isdn_net_log_skb(skb, lp);
1255 lp->dialstate = 1;
1256 /* Connect interface with channel */
1257 isdn_net_bind_channel(lp, chi);
1258#ifdef CONFIG_ISDN_PPP
1259 if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) {
1260 /* no 'first_skb' handling for syncPPP */
1261 if (isdn_ppp_bind(lp) < 0) {
1262 dev_kfree_skb(skb);
1263 isdn_net_unbind_channel(lp);
1264 spin_unlock_irqrestore(&dev->lock, flags);
1265 return 0; /* STN (skb to nirvana) ;) */
1266 }
1267#ifdef CONFIG_IPPP_FILTER
1268 if (isdn_ppp_autodial_filter(skb, lp)) {
1269 isdn_ppp_free(lp);
1270 isdn_net_unbind_channel(lp);
1271 spin_unlock_irqrestore(&dev->lock, flags);
1272 isdn_net_unreachable(ndev, skb, "dial rejected: packet filtered");
1273 dev_kfree_skb(skb);
1274 return 0;
1275 }
1276#endif
1277 spin_unlock_irqrestore(&dev->lock, flags);
1278 isdn_net_dial(); /* Initiate dialing */
1279 netif_stop_queue(ndev);
1280 return 1; /* let upper layer requeue skb packet */
1281 }
1282#endif
1283 /* Initiate dialing */
1284 spin_unlock_irqrestore(&dev->lock, flags);
1285 isdn_net_dial();
1286 isdn_net_device_stop_queue(lp);
1287 return 1;
1288 } else {
1289 isdn_net_unreachable(ndev, skb,
1290 "No phone number");
1291 dev_kfree_skb(skb);
1292 return 0;
1293 }
1294 } else {
1295 /* Device is connected to an ISDN channel */
1296 ndev->trans_start = jiffies;
1297 if (!lp->dialstate) {
1298 /* ISDN connection is established, try sending */
1299 int ret;
1300 ret = (isdn_net_xmit(ndev, skb));
1301 if(ret) netif_stop_queue(ndev);
1302 return ret;
1303 } else
1304 netif_stop_queue(ndev);
1305 }
1306 }
1307 return 1;
1308}
1309
1310/*
1311 * Shutdown a net-interface.
1312 */
1313static int
1314isdn_net_close(struct net_device *dev)
1315{
1316 struct net_device *p;
1317#ifdef CONFIG_ISDN_X25
1318 struct concap_proto * cprot =
1319 ( (isdn_net_local *) dev->priv ) -> netdev -> cprot;
1320 /* printk(KERN_DEBUG "isdn_net_close %s\n" , dev-> name ); */
1321#endif
1322
1323#ifdef CONFIG_ISDN_X25
1324 if( cprot && cprot -> pops ) cprot -> pops -> close( cprot );
1325#endif
1326 netif_stop_queue(dev);
1327 if ((p = (((isdn_net_local *) dev->priv)->slave))) {
1328 /* If this interface has slaves, stop them also */
1329 while (p) {
1330#ifdef CONFIG_ISDN_X25
1331 cprot = ( (isdn_net_local *) p->priv )
1332 -> netdev -> cprot;
1333 if( cprot && cprot -> pops )
1334 cprot -> pops -> close( cprot );
1335#endif
1336 isdn_net_hangup(p);
1337 p = (((isdn_net_local *) p->priv)->slave);
1338 }
1339 }
1340 isdn_net_hangup(dev);
1341 isdn_unlock_drivers();
1342 return 0;
1343}
1344
1345/*
1346 * Get statistics
1347 */
1348static struct net_device_stats *
1349isdn_net_get_stats(struct net_device *dev)
1350{
1351 isdn_net_local *lp = (isdn_net_local *) dev->priv;
1352 return &lp->stats;
1353}
1354
1355/* This is simply a copy from std. eth.c EXCEPT we pull ETH_HLEN
1356 * instead of dev->hard_header_len off. This is done because the
1357 * lowlevel-driver has already pulled off its stuff when we get
1358 * here and this routine only gets called with p_encap == ETHER.
1359 * Determine the packet's protocol ID. The rule here is that we
1360 * assume 802.3 if the type field is short enough to be a length.
1361 * This is normal practice and works for any 'now in use' protocol.
1362 */
1363
1364static unsigned short
1365isdn_net_type_trans(struct sk_buff *skb, struct net_device *dev)
1366{
1367 struct ethhdr *eth;
1368 unsigned char *rawp;
1369
1370 skb->mac.raw = skb->data;
1371 skb_pull(skb, ETH_HLEN);
1372 eth = eth_hdr(skb);
1373
1374 if (*eth->h_dest & 1) {
1375 if (memcmp(eth->h_dest, dev->broadcast, ETH_ALEN) == 0)
1376 skb->pkt_type = PACKET_BROADCAST;
1377 else
1378 skb->pkt_type = PACKET_MULTICAST;
1379 }
1380 /*
1381 * This ALLMULTI check should be redundant by 1.4
1382 * so don't forget to remove it.
1383 */
1384
1385 else if (dev->flags & (IFF_PROMISC /*| IFF_ALLMULTI*/)) {
1386 if (memcmp(eth->h_dest, dev->dev_addr, ETH_ALEN))
1387 skb->pkt_type = PACKET_OTHERHOST;
1388 }
1389 if (ntohs(eth->h_proto) >= 1536)
1390 return eth->h_proto;
1391
1392 rawp = skb->data;
1393
1394 /*
1395 * This is a magic hack to spot IPX packets. Older Novell breaks
1396 * the protocol design and runs IPX over 802.3 without an 802.2 LLC
1397 * layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This
1398 * won't work for fault tolerant netware but does for the rest.
1399 */
1400 if (*(unsigned short *) rawp == 0xFFFF)
1401 return htons(ETH_P_802_3);
1402 /*
1403 * Real 802.2 LLC
1404 */
1405 return htons(ETH_P_802_2);
1406}
1407
1408
1409/*
1410 * CISCO HDLC keepalive specific stuff
1411 */
1412static struct sk_buff*
1413isdn_net_ciscohdlck_alloc_skb(isdn_net_local *lp, int len)
1414{
1415 unsigned short hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen;
1416 struct sk_buff *skb;
1417
1418 skb = alloc_skb(hl + len, GFP_ATOMIC);
1419 if (skb)
1420 skb_reserve(skb, hl);
1421 else
1422 printk("isdn out of mem at %s:%d!\n", __FILE__, __LINE__);
1423 return skb;
1424}
1425
1426/* cisco hdlck device private ioctls */
1427int
1428isdn_ciscohdlck_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1429{
1430 isdn_net_local *lp = (isdn_net_local *) dev->priv;
1431 unsigned long len = 0;
1432 unsigned long expires = 0;
1433 int tmp = 0;
1434 int period = lp->cisco_keepalive_period;
1435 s8 debserint = lp->cisco_debserint;
1436 int rc = 0;
1437
1438 if (lp->p_encap != ISDN_NET_ENCAP_CISCOHDLCK)
1439 return -EINVAL;
1440
1441 switch (cmd) {
1442 /* get/set keepalive period */
1443 case SIOCGKEEPPERIOD:
1444 len = (unsigned long)sizeof(lp->cisco_keepalive_period);
1445 if (copy_to_user(ifr->ifr_data,
1446 &lp->cisco_keepalive_period, len))
1447 rc = -EFAULT;
1448 break;
1449 case SIOCSKEEPPERIOD:
1450 tmp = lp->cisco_keepalive_period;
1451 len = (unsigned long)sizeof(lp->cisco_keepalive_period);
1452 if (copy_from_user(&period, ifr->ifr_data, len))
1453 rc = -EFAULT;
1454 if ((period > 0) && (period <= 32767))
1455 lp->cisco_keepalive_period = period;
1456 else
1457 rc = -EINVAL;
1458 if (!rc && (tmp != lp->cisco_keepalive_period)) {
1459 expires = (unsigned long)(jiffies +
1460 lp->cisco_keepalive_period * HZ);
1461 mod_timer(&lp->cisco_timer, expires);
1462 printk(KERN_INFO "%s: Keepalive period set "
1463 "to %d seconds.\n",
1464 lp->name, lp->cisco_keepalive_period);
1465 }
1466 break;
1467
1468 /* get/set debugging */
1469 case SIOCGDEBSERINT:
1470 len = (unsigned long)sizeof(lp->cisco_debserint);
1471 if (copy_to_user(ifr->ifr_data,
1472 &lp->cisco_debserint, len))
1473 rc = -EFAULT;
1474 break;
1475 case SIOCSDEBSERINT:
1476 len = (unsigned long)sizeof(lp->cisco_debserint);
1477 if (copy_from_user(&debserint,
1478 ifr->ifr_data, len))
1479 rc = -EFAULT;
1480 if ((debserint >= 0) && (debserint <= 64))
1481 lp->cisco_debserint = debserint;
1482 else
1483 rc = -EINVAL;
1484 break;
1485
1486 default:
1487 rc = -EINVAL;
1488 break;
1489 }
1490 return (rc);
1491}
1492
1493/* called via cisco_timer.function */
1494static void
1495isdn_net_ciscohdlck_slarp_send_keepalive(unsigned long data)
1496{
1497 isdn_net_local *lp = (isdn_net_local *) data;
1498 struct sk_buff *skb;
1499 unsigned char *p;
1500 unsigned long last_cisco_myseq = lp->cisco_myseq;
1501 int myseq_diff = 0;
1502
1503 if (!(lp->flags & ISDN_NET_CONNECTED) || lp->dialstate) {
1504 printk("isdn BUG at %s:%d!\n", __FILE__, __LINE__);
1505 return;
1506 }
1507 lp->cisco_myseq++;
1508
1509 myseq_diff = (lp->cisco_myseq - lp->cisco_mineseen);
1510 if ((lp->cisco_line_state) && ((myseq_diff >= 3)||(myseq_diff <= -3))) {
1511 /* line up -> down */
1512 lp->cisco_line_state = 0;
1513 printk (KERN_WARNING
1514 "UPDOWN: Line protocol on Interface %s,"
1515 " changed state to down\n", lp->name);
1516 /* should stop routing higher-level data accross */
1517 } else if ((!lp->cisco_line_state) &&
1518 (myseq_diff >= 0) && (myseq_diff <= 2)) {
1519 /* line down -> up */
1520 lp->cisco_line_state = 1;
1521 printk (KERN_WARNING
1522 "UPDOWN: Line protocol on Interface %s,"
1523 " changed state to up\n", lp->name);
1524 /* restart routing higher-level data accross */
1525 }
1526
1527 if (lp->cisco_debserint)
1528 printk (KERN_DEBUG "%s: HDLC "
1529 "myseq %lu, mineseen %lu%c, yourseen %lu, %s\n",
1530 lp->name, last_cisco_myseq, lp->cisco_mineseen,
1531 ((last_cisco_myseq == lp->cisco_mineseen) ? '*' : 040),
1532 lp->cisco_yourseq,
1533 ((lp->cisco_line_state) ? "line up" : "line down"));
1534
1535 skb = isdn_net_ciscohdlck_alloc_skb(lp, 4 + 14);
1536 if (!skb)
1537 return;
1538
1539 p = skb_put(skb, 4 + 14);
1540
1541 /* cisco header */
1542 p += put_u8 (p, CISCO_ADDR_UNICAST);
1543 p += put_u8 (p, CISCO_CTRL);
1544 p += put_u16(p, CISCO_TYPE_SLARP);
1545
1546 /* slarp keepalive */
1547 p += put_u32(p, CISCO_SLARP_KEEPALIVE);
1548 p += put_u32(p, lp->cisco_myseq);
1549 p += put_u32(p, lp->cisco_yourseq);
1550 p += put_u16(p, 0xffff); // reliablity, always 0xffff
1551
1552 isdn_net_write_super(lp, skb);
1553
1554 lp->cisco_timer.expires = jiffies + lp->cisco_keepalive_period * HZ;
1555
1556 add_timer(&lp->cisco_timer);
1557}
1558
1559static void
1560isdn_net_ciscohdlck_slarp_send_request(isdn_net_local *lp)
1561{
1562 struct sk_buff *skb;
1563 unsigned char *p;
1564
1565 skb = isdn_net_ciscohdlck_alloc_skb(lp, 4 + 14);
1566 if (!skb)
1567 return;
1568
1569 p = skb_put(skb, 4 + 14);
1570
1571 /* cisco header */
1572 p += put_u8 (p, CISCO_ADDR_UNICAST);
1573 p += put_u8 (p, CISCO_CTRL);
1574 p += put_u16(p, CISCO_TYPE_SLARP);
1575
1576 /* slarp request */
1577 p += put_u32(p, CISCO_SLARP_REQUEST);
1578 p += put_u32(p, 0); // address
1579 p += put_u32(p, 0); // netmask
1580 p += put_u16(p, 0); // unused
1581
1582 isdn_net_write_super(lp, skb);
1583}
1584
1585static void
1586isdn_net_ciscohdlck_connected(isdn_net_local *lp)
1587{
1588 lp->cisco_myseq = 0;
1589 lp->cisco_mineseen = 0;
1590 lp->cisco_yourseq = 0;
1591 lp->cisco_keepalive_period = ISDN_TIMER_KEEPINT;
1592 lp->cisco_last_slarp_in = 0;
1593 lp->cisco_line_state = 0;
1594 lp->cisco_debserint = 0;
1595
1596 /* send slarp request because interface/seq.no.s reset */
1597 isdn_net_ciscohdlck_slarp_send_request(lp);
1598
1599 init_timer(&lp->cisco_timer);
1600 lp->cisco_timer.data = (unsigned long) lp;
1601 lp->cisco_timer.function = isdn_net_ciscohdlck_slarp_send_keepalive;
1602 lp->cisco_timer.expires = jiffies + lp->cisco_keepalive_period * HZ;
1603 add_timer(&lp->cisco_timer);
1604}
1605
1606static void
1607isdn_net_ciscohdlck_disconnected(isdn_net_local *lp)
1608{
1609 del_timer(&lp->cisco_timer);
1610}
1611
1612static void
1613isdn_net_ciscohdlck_slarp_send_reply(isdn_net_local *lp)
1614{
1615 struct sk_buff *skb;
1616 unsigned char *p;
1617 struct in_device *in_dev = NULL;
1618 u32 addr = 0; /* local ipv4 address */
1619 u32 mask = 0; /* local netmask */
1620
1621 if ((in_dev = lp->netdev->dev.ip_ptr) != NULL) {
1622 /* take primary(first) address of interface */
1623 struct in_ifaddr *ifa = in_dev->ifa_list;
1624 if (ifa != NULL) {
1625 addr = ifa->ifa_local;
1626 mask = ifa->ifa_mask;
1627 }
1628 }
1629
1630 skb = isdn_net_ciscohdlck_alloc_skb(lp, 4 + 14);
1631 if (!skb)
1632 return;
1633
1634 p = skb_put(skb, 4 + 14);
1635
1636 /* cisco header */
1637 p += put_u8 (p, CISCO_ADDR_UNICAST);
1638 p += put_u8 (p, CISCO_CTRL);
1639 p += put_u16(p, CISCO_TYPE_SLARP);
1640
1641 /* slarp reply, send own ip/netmask; if values are nonsense remote
1642 * should think we are unable to provide it with an address via SLARP */
1643 p += put_u32(p, CISCO_SLARP_REPLY);
1644 p += put_u32(p, addr); // address
1645 p += put_u32(p, mask); // netmask
1646 p += put_u16(p, 0); // unused
1647
1648 isdn_net_write_super(lp, skb);
1649}
1650
1651static void
1652isdn_net_ciscohdlck_slarp_in(isdn_net_local *lp, struct sk_buff *skb)
1653{
1654 unsigned char *p;
1655 int period;
1656 u32 code;
1657 u32 my_seq, addr;
1658 u32 your_seq, mask;
1659 u32 local;
1660 u16 unused;
1661
1662 if (skb->len < 14)
1663 return;
1664
1665 p = skb->data;
1666 p += get_u32(p, &code);
1667
1668 switch (code) {
1669 case CISCO_SLARP_REQUEST:
1670 lp->cisco_yourseq = 0;
1671 isdn_net_ciscohdlck_slarp_send_reply(lp);
1672 break;
1673 case CISCO_SLARP_REPLY:
1674 addr = ntohl(*(u32 *)p);
1675 mask = ntohl(*(u32 *)(p+4));
1676 if (mask != 0xfffffffc)
1677 goto slarp_reply_out;
1678 if ((addr & 3) == 0 || (addr & 3) == 3)
1679 goto slarp_reply_out;
1680 local = addr ^ 3;
1681 printk(KERN_INFO "%s: got slarp reply: "
1682 "remote ip: %d.%d.%d.%d, "
1683 "local ip: %d.%d.%d.%d "
1684 "mask: %d.%d.%d.%d\n",
1685 lp->name,
1686 HIPQUAD(addr),
1687 HIPQUAD(local),
1688 HIPQUAD(mask));
1689 break;
1690 slarp_reply_out:
1691 printk(KERN_INFO "%s: got invalid slarp "
1692 "reply (%d.%d.%d.%d/%d.%d.%d.%d) "
1693 "- ignored\n", lp->name,
1694 HIPQUAD(addr), HIPQUAD(mask));
1695 break;
1696 case CISCO_SLARP_KEEPALIVE:
1697 period = (int)((jiffies - lp->cisco_last_slarp_in
1698 + HZ/2 - 1) / HZ);
1699 if (lp->cisco_debserint &&
1700 (period != lp->cisco_keepalive_period) &&
1701 lp->cisco_last_slarp_in) {
1702 printk(KERN_DEBUG "%s: Keepalive period mismatch - "
1703 "is %d but should be %d.\n",
1704 lp->name, period, lp->cisco_keepalive_period);
1705 }
1706 lp->cisco_last_slarp_in = jiffies;
1707 p += get_u32(p, &my_seq);
1708 p += get_u32(p, &your_seq);
1709 p += get_u16(p, &unused);
1710 lp->cisco_yourseq = my_seq;
1711 lp->cisco_mineseen = your_seq;
1712 break;
1713 }
1714}
1715
1716static void
1717isdn_net_ciscohdlck_receive(isdn_net_local *lp, struct sk_buff *skb)
1718{
1719 unsigned char *p;
1720 u8 addr;
1721 u8 ctrl;
1722 u16 type;
1723
1724 if (skb->len < 4)
1725 goto out_free;
1726
1727 p = skb->data;
1728 p += get_u8 (p, &addr);
1729 p += get_u8 (p, &ctrl);
1730 p += get_u16(p, &type);
1731 skb_pull(skb, 4);
1732
1733 if (addr != CISCO_ADDR_UNICAST && addr != CISCO_ADDR_BROADCAST) {
1734 printk(KERN_WARNING "%s: Unknown Cisco addr 0x%02x\n",
1735 lp->name, addr);
1736 goto out_free;
1737 }
1738 if (ctrl != CISCO_CTRL) {
1739 printk(KERN_WARNING "%s: Unknown Cisco ctrl 0x%02x\n",
1740 lp->name, ctrl);
1741 goto out_free;
1742 }
1743
1744 switch (type) {
1745 case CISCO_TYPE_SLARP:
1746 isdn_net_ciscohdlck_slarp_in(lp, skb);
1747 goto out_free;
1748 case CISCO_TYPE_CDP:
1749 if (lp->cisco_debserint)
1750 printk(KERN_DEBUG "%s: Received CDP packet. use "
1751 "\"no cdp enable\" on cisco.\n", lp->name);
1752 goto out_free;
1753 default:
1754 /* no special cisco protocol */
1755 skb->protocol = htons(type);
1756 netif_rx(skb);
1757 return;
1758 }
1759
1760 out_free:
1761 kfree_skb(skb);
1762}
1763
1764/*
1765 * Got a packet from ISDN-Channel.
1766 */
1767static void
1768isdn_net_receive(struct net_device *ndev, struct sk_buff *skb)
1769{
1770 isdn_net_local *lp = (isdn_net_local *) ndev->priv;
1771 isdn_net_local *olp = lp; /* original 'lp' */
1772#ifdef CONFIG_ISDN_X25
1773 struct concap_proto *cprot = lp -> netdev -> cprot;
1774#endif
1775 lp->transcount += skb->len;
1776
1777 lp->stats.rx_packets++;
1778 lp->stats.rx_bytes += skb->len;
1779 if (lp->master) {
1780 /* Bundling: If device is a slave-device, deliver to master, also
1781 * handle master's statistics and hangup-timeout
1782 */
1783 ndev = lp->master;
1784 lp = (isdn_net_local *) ndev->priv;
1785 lp->stats.rx_packets++;
1786 lp->stats.rx_bytes += skb->len;
1787 }
1788 skb->dev = ndev;
1789 skb->input_dev = ndev;
1790 skb->pkt_type = PACKET_HOST;
1791 skb->mac.raw = skb->data;
1792#ifdef ISDN_DEBUG_NET_DUMP
1793 isdn_dumppkt("R:", skb->data, skb->len, 40);
1794#endif
1795 switch (lp->p_encap) {
1796 case ISDN_NET_ENCAP_ETHER:
1797 /* Ethernet over ISDN */
1798 olp->huptimer = 0;
1799 lp->huptimer = 0;
1800 skb->protocol = isdn_net_type_trans(skb, ndev);
1801 break;
1802 case ISDN_NET_ENCAP_UIHDLC:
1803 /* HDLC with UI-frame (for ispa with -h1 option) */
1804 olp->huptimer = 0;
1805 lp->huptimer = 0;
1806 skb_pull(skb, 2);
1807 /* Fall through */
1808 case ISDN_NET_ENCAP_RAWIP:
1809 /* RAW-IP without MAC-Header */
1810 olp->huptimer = 0;
1811 lp->huptimer = 0;
1812 skb->protocol = htons(ETH_P_IP);
1813 break;
1814 case ISDN_NET_ENCAP_CISCOHDLCK:
1815 isdn_net_ciscohdlck_receive(lp, skb);
1816 return;
1817 case ISDN_NET_ENCAP_CISCOHDLC:
1818 /* CISCO-HDLC IP with type field and fake I-frame-header */
1819 skb_pull(skb, 2);
1820 /* Fall through */
1821 case ISDN_NET_ENCAP_IPTYP:
1822 /* IP with type field */
1823 olp->huptimer = 0;
1824 lp->huptimer = 0;
1825 skb->protocol = *(unsigned short *) &(skb->data[0]);
1826 skb_pull(skb, 2);
1827 if (*(unsigned short *) skb->data == 0xFFFF)
1828 skb->protocol = htons(ETH_P_802_3);
1829 break;
1830#ifdef CONFIG_ISDN_PPP
1831 case ISDN_NET_ENCAP_SYNCPPP:
1832 /* huptimer is done in isdn_ppp_push_higher */
1833 isdn_ppp_receive(lp->netdev, olp, skb);
1834 return;
1835#endif
1836
1837 default:
1838#ifdef CONFIG_ISDN_X25
1839 /* try if there are generic sync_device receiver routines */
1840 if(cprot) if(cprot -> pops)
1841 if( cprot -> pops -> data_ind){
1842 cprot -> pops -> data_ind(cprot,skb);
1843 return;
1844 };
1845#endif /* CONFIG_ISDN_X25 */
1846 printk(KERN_WARNING "%s: unknown encapsulation, dropping\n",
1847 lp->name);
1848 kfree_skb(skb);
1849 return;
1850 }
1851
1852 netif_rx(skb);
1853 return;
1854}
1855
1856/*
1857 * A packet arrived via ISDN. Search interface-chain for a corresponding
1858 * interface. If found, deliver packet to receiver-function and return 1,
1859 * else return 0.
1860 */
1861int
1862isdn_net_rcv_skb(int idx, struct sk_buff *skb)
1863{
1864 isdn_net_dev *p = dev->rx_netdev[idx];
1865
1866 if (p) {
1867 isdn_net_local *lp = p->local;
1868 if ((lp->flags & ISDN_NET_CONNECTED) &&
1869 (!lp->dialstate)) {
1870 isdn_net_receive(&p->dev, skb);
1871 return 1;
1872 }
1873 }
1874 return 0;
1875}
1876
1877static int
1878my_eth_header(struct sk_buff *skb, struct net_device *dev, unsigned short type,
1879 void *daddr, void *saddr, unsigned len)
1880{
1881 struct ethhdr *eth = (struct ethhdr *) skb_push(skb, ETH_HLEN);
1882
1883 /*
1884 * Set the protocol type. For a packet of type ETH_P_802_3 we
1885 * put the length here instead. It is up to the 802.2 layer to
1886 * carry protocol information.
1887 */
1888
1889 if (type != ETH_P_802_3)
1890 eth->h_proto = htons(type);
1891 else
1892 eth->h_proto = htons(len);
1893
1894 /*
1895 * Set the source hardware address.
1896 */
1897 if (saddr)
1898 memcpy(eth->h_source, saddr, dev->addr_len);
1899 else
1900 memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
1901
1902 /*
1903 * Anyway, the loopback-device should never use this function...
1904 */
1905
1906 if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) {
1907 memset(eth->h_dest, 0, dev->addr_len);
1908 return ETH_HLEN /*(dev->hard_header_len)*/;
1909 }
1910 if (daddr) {
1911 memcpy(eth->h_dest, daddr, dev->addr_len);
1912 return ETH_HLEN /*dev->hard_header_len*/;
1913 }
1914 return -ETH_HLEN /*dev->hard_header_len*/;
1915}
1916
1917/*
1918 * build an header
1919 * depends on encaps that is being used.
1920 */
1921
1922static int
1923isdn_net_header(struct sk_buff *skb, struct net_device *dev, unsigned short type,
1924 void *daddr, void *saddr, unsigned plen)
1925{
1926 isdn_net_local *lp = dev->priv;
1927 unsigned char *p;
1928 ushort len = 0;
1929
1930 switch (lp->p_encap) {
1931 case ISDN_NET_ENCAP_ETHER:
1932 len = my_eth_header(skb, dev, type, daddr, saddr, plen);
1933 break;
1934#ifdef CONFIG_ISDN_PPP
1935 case ISDN_NET_ENCAP_SYNCPPP:
1936 /* stick on a fake header to keep fragmentation code happy. */
1937 len = IPPP_MAX_HEADER;
1938 skb_push(skb,len);
1939 break;
1940#endif
1941 case ISDN_NET_ENCAP_RAWIP:
1942 printk(KERN_WARNING "isdn_net_header called with RAW_IP!\n");
1943 len = 0;
1944 break;
1945 case ISDN_NET_ENCAP_IPTYP:
1946 /* ethernet type field */
1947 *((ushort *) skb_push(skb, 2)) = htons(type);
1948 len = 2;
1949 break;
1950 case ISDN_NET_ENCAP_UIHDLC:
1951 /* HDLC with UI-Frames (for ispa with -h1 option) */
1952 *((ushort *) skb_push(skb, 2)) = htons(0x0103);
1953 len = 2;
1954 break;
1955 case ISDN_NET_ENCAP_CISCOHDLC:
1956 case ISDN_NET_ENCAP_CISCOHDLCK:
1957 p = skb_push(skb, 4);
1958 p += put_u8 (p, CISCO_ADDR_UNICAST);
1959 p += put_u8 (p, CISCO_CTRL);
1960 p += put_u16(p, type);
1961 len = 4;
1962 break;
1963#ifdef CONFIG_ISDN_X25
1964 default:
1965 /* try if there are generic concap protocol routines */
1966 if( lp-> netdev -> cprot ){
1967 printk(KERN_WARNING "isdn_net_header called with concap_proto!\n");
1968 len = 0;
1969 break;
1970 }
1971 break;
1972#endif /* CONFIG_ISDN_X25 */
1973 }
1974 return len;
1975}
1976
1977/* We don't need to send arp, because we have point-to-point connections. */
1978static int
1979isdn_net_rebuild_header(struct sk_buff *skb)
1980{
1981 struct net_device *dev = skb->dev;
1982 isdn_net_local *lp = dev->priv;
1983 int ret = 0;
1984
1985 if (lp->p_encap == ISDN_NET_ENCAP_ETHER) {
1986 struct ethhdr *eth = (struct ethhdr *) skb->data;
1987
1988 /*
1989 * Only ARP/IP is currently supported
1990 */
1991
1992 if (eth->h_proto != htons(ETH_P_IP)) {
1993 printk(KERN_WARNING
1994 "isdn_net: %s don't know how to resolve type %d addresses?\n",
1995 dev->name, (int) eth->h_proto);
1996 memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
1997 return 0;
1998 }
1999 /*
2000 * Try to get ARP to resolve the header.
2001 */
2002#ifdef CONFIG_INET
2003 ret = arp_find(eth->h_dest, skb);
2004#endif
2005 }
2006 return ret;
2007}
2008
2009/*
2010 * Interface-setup. (just after registering a new interface)
2011 */
2012static int
2013isdn_net_init(struct net_device *ndev)
2014{
2015 ushort max_hlhdr_len = 0;
2016 isdn_net_local *lp = (isdn_net_local *) ndev->priv;
2017 int drvidx, i;
2018
2019 ether_setup(ndev);
2020 lp->org_hhc = ndev->hard_header_cache;
2021 lp->org_hcu = ndev->header_cache_update;
2022
2023 /* Setup the generic properties */
2024
2025 ndev->hard_header = NULL;
2026 ndev->hard_header_cache = NULL;
2027 ndev->header_cache_update = NULL;
2028 ndev->mtu = 1500;
2029 ndev->flags = IFF_NOARP|IFF_POINTOPOINT;
2030 ndev->type = ARPHRD_ETHER;
2031 ndev->addr_len = ETH_ALEN;
2032
2033 /* for clients with MPPP maybe higher values better */
2034 ndev->tx_queue_len = 30;
2035
2036 for (i = 0; i < ETH_ALEN; i++)
2037 ndev->broadcast[i] = 0xff;
2038
2039 /* The ISDN-specific entries in the device structure. */
2040 ndev->open = &isdn_net_open;
2041 ndev->hard_start_xmit = &isdn_net_start_xmit;
2042
2043 /*
2044 * up till binding we ask the protocol layer to reserve as much
2045 * as we might need for HL layer
2046 */
2047
2048 for (drvidx = 0; drvidx < ISDN_MAX_DRIVERS; drvidx++)
2049 if (dev->drv[drvidx])
2050 if (max_hlhdr_len < dev->drv[drvidx]->interface->hl_hdrlen)
2051 max_hlhdr_len = dev->drv[drvidx]->interface->hl_hdrlen;
2052
2053 ndev->hard_header_len = ETH_HLEN + max_hlhdr_len;
2054 ndev->stop = &isdn_net_close;
2055 ndev->get_stats = &isdn_net_get_stats;
2056 ndev->rebuild_header = &isdn_net_rebuild_header;
2057 ndev->do_ioctl = NULL;
2058 return 0;
2059}
2060
2061static void
2062isdn_net_swapbind(int drvidx)
2063{
2064 isdn_net_dev *p;
2065
2066#ifdef ISDN_DEBUG_NET_ICALL
2067 printk(KERN_DEBUG "n_fi: swapping ch of %d\n", drvidx);
2068#endif
2069 p = dev->netdev;
2070 while (p) {
2071 if (p->local->pre_device == drvidx)
2072 switch (p->local->pre_channel) {
2073 case 0:
2074 p->local->pre_channel = 1;
2075 break;
2076 case 1:
2077 p->local->pre_channel = 0;
2078 break;
2079 }
2080 p = (isdn_net_dev *) p->next;
2081 }
2082}
2083
2084static void
2085isdn_net_swap_usage(int i1, int i2)
2086{
2087 int u1 = dev->usage[i1] & ISDN_USAGE_EXCLUSIVE;
2088 int u2 = dev->usage[i2] & ISDN_USAGE_EXCLUSIVE;
2089
2090#ifdef ISDN_DEBUG_NET_ICALL
2091 printk(KERN_DEBUG "n_fi: usage of %d and %d\n", i1, i2);
2092#endif
2093 dev->usage[i1] &= ~ISDN_USAGE_EXCLUSIVE;
2094 dev->usage[i1] |= u2;
2095 dev->usage[i2] &= ~ISDN_USAGE_EXCLUSIVE;
2096 dev->usage[i2] |= u1;
2097 isdn_info_update();
2098}
2099
2100/*
2101 * An incoming call-request has arrived.
2102 * Search the interface-chain for an appropriate interface.
2103 * If found, connect the interface to the ISDN-channel and initiate
2104 * D- and B-Channel-setup. If secure-flag is set, accept only
2105 * configured phone-numbers. If callback-flag is set, initiate
2106 * callback-dialing.
2107 *
2108 * Return-Value: 0 = No appropriate interface for this call.
2109 * 1 = Call accepted
2110 * 2 = Reject call, wait cbdelay, then call back
2111 * 3 = Reject call
2112 * 4 = Wait cbdelay, then call back
2113 * 5 = No appropriate interface for this call,
2114 * would eventually match if CID was longer.
2115 */
2116
2117int
2118isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
2119{
2120 char *eaz;
2121 int si1;
2122 int si2;
2123 int ematch;
2124 int wret;
2125 int swapped;
2126 int sidx = 0;
2127 u_long flags;
2128 isdn_net_dev *p;
2129 isdn_net_phone *n;
2130 char nr[32];
2131 char *my_eaz;
2132
2133 /* Search name in netdev-chain */
2134 if (!setup->phone[0]) {
2135 nr[0] = '0';
2136 nr[1] = '\0';
2137 printk(KERN_INFO "isdn_net: Incoming call without OAD, assuming '0'\n");
2138 } else
2139 strcpy(nr, setup->phone);
2140 si1 = (int) setup->si1;
2141 si2 = (int) setup->si2;
2142 if (!setup->eazmsn[0]) {
2143 printk(KERN_WARNING "isdn_net: Incoming call without CPN, assuming '0'\n");
2144 eaz = "0";
2145 } else
2146 eaz = setup->eazmsn;
2147 if (dev->net_verbose > 1)
2148 printk(KERN_INFO "isdn_net: call from %s,%d,%d -> %s\n", nr, si1, si2, eaz);
2149 /* Accept DATA and VOICE calls at this stage
2150 * local eaz is checked later for allowed call types
2151 */
2152 if ((si1 != 7) && (si1 != 1)) {
2153 if (dev->net_verbose > 1)
2154 printk(KERN_INFO "isdn_net: Service-Indicator not 1 or 7, ignored\n");
2155 return 0;
2156 }
2157 n = (isdn_net_phone *) 0;
2158 p = dev->netdev;
2159 ematch = wret = swapped = 0;
2160#ifdef ISDN_DEBUG_NET_ICALL
2161 printk(KERN_DEBUG "n_fi: di=%d ch=%d idx=%d usg=%d\n", di, ch, idx,
2162 dev->usage[idx]);
2163#endif
2164 while (p) {
2165 int matchret;
2166 isdn_net_local *lp = p->local;
2167
2168 /* If last check has triggered as binding-swap, revert it */
2169 switch (swapped) {
2170 case 2:
2171 isdn_net_swap_usage(idx, sidx);
2172 /* fall through */
2173 case 1:
2174 isdn_net_swapbind(di);
2175 break;
2176 }
2177 swapped = 0;
2178 /* check acceptable call types for DOV */
2179 my_eaz = isdn_map_eaz2msn(lp->msn, di);
2180 if (si1 == 1) { /* it's a DOV call, check if we allow it */
2181 if (*my_eaz == 'v' || *my_eaz == 'V' ||
2182 *my_eaz == 'b' || *my_eaz == 'B')
2183 my_eaz++; /* skip to allow a match */
2184 else
2185 my_eaz = NULL; /* force non match */
2186 } else { /* it's a DATA call, check if we allow it */
2187 if (*my_eaz == 'b' || *my_eaz == 'B')
2188 my_eaz++; /* skip to allow a match */
2189 }
2190 if (my_eaz)
2191 matchret = isdn_msncmp(eaz, my_eaz);
2192 else
2193 matchret = 1;
2194 if (!matchret)
2195 ematch = 1;
2196
2197 /* Remember if more numbers eventually can match */
2198 if (matchret > wret)
2199 wret = matchret;
2200#ifdef ISDN_DEBUG_NET_ICALL
2201 printk(KERN_DEBUG "n_fi: if='%s', l.msn=%s, l.flags=%d, l.dstate=%d\n",
2202 lp->name, lp->msn, lp->flags, lp->dialstate);
2203#endif
2204 if ((!matchret) && /* EAZ is matching */
2205 (((!(lp->flags & ISDN_NET_CONNECTED)) && /* but not connected */
2206 (USG_NONE(dev->usage[idx]))) || /* and ch. unused or */
2207 ((((lp->dialstate == 4) || (lp->dialstate == 12)) && /* if dialing */
2208 (!(lp->flags & ISDN_NET_CALLBACK))) /* but no callback */
2209 )))
2210 {
2211#ifdef ISDN_DEBUG_NET_ICALL
2212 printk(KERN_DEBUG "n_fi: match1, pdev=%d pch=%d\n",
2213 lp->pre_device, lp->pre_channel);
2214#endif
2215 if (dev->usage[idx] & ISDN_USAGE_EXCLUSIVE) {
2216 if ((lp->pre_channel != ch) ||
2217 (lp->pre_device != di)) {
2218 /* Here we got a problem:
2219 * If using an ICN-Card, an incoming call is always signaled on
2220 * on the first channel of the card, if both channels are
2221 * down. However this channel may be bound exclusive. If the
2222 * second channel is free, this call should be accepted.
2223 * The solution is horribly but it runs, so what:
2224 * We exchange the exclusive bindings of the two channels, the
2225 * corresponding variables in the interface-structs.
2226 */
2227 if (ch == 0) {
2228 sidx = isdn_dc2minor(di, 1);
2229#ifdef ISDN_DEBUG_NET_ICALL
2230 printk(KERN_DEBUG "n_fi: ch is 0\n");
2231#endif
2232 if (USG_NONE(dev->usage[sidx])) {
2233 /* Second Channel is free, now see if it is bound
2234 * exclusive too. */
2235 if (dev->usage[sidx] & ISDN_USAGE_EXCLUSIVE) {
2236#ifdef ISDN_DEBUG_NET_ICALL
2237 printk(KERN_DEBUG "n_fi: 2nd channel is down and bound\n");
2238#endif
2239 /* Yes, swap bindings only, if the original
2240 * binding is bound to channel 1 of this driver */
2241 if ((lp->pre_device == di) &&
2242 (lp->pre_channel == 1)) {
2243 isdn_net_swapbind(di);
2244 swapped = 1;
2245 } else {
2246 /* ... else iterate next device */
2247 p = (isdn_net_dev *) p->next;
2248 continue;
2249 }
2250 } else {
2251#ifdef ISDN_DEBUG_NET_ICALL
2252 printk(KERN_DEBUG "n_fi: 2nd channel is down and unbound\n");
2253#endif
2254 /* No, swap always and swap excl-usage also */
2255 isdn_net_swap_usage(idx, sidx);
2256 isdn_net_swapbind(di);
2257 swapped = 2;
2258 }
2259 /* Now check for exclusive binding again */
2260#ifdef ISDN_DEBUG_NET_ICALL
2261 printk(KERN_DEBUG "n_fi: final check\n");
2262#endif
2263 if ((dev->usage[idx] & ISDN_USAGE_EXCLUSIVE) &&
2264 ((lp->pre_channel != ch) ||
2265 (lp->pre_device != di))) {
2266#ifdef ISDN_DEBUG_NET_ICALL
2267 printk(KERN_DEBUG "n_fi: final check failed\n");
2268#endif
2269 p = (isdn_net_dev *) p->next;
2270 continue;
2271 }
2272 }
2273 } else {
2274 /* We are already on the second channel, so nothing to do */
2275#ifdef ISDN_DEBUG_NET_ICALL
2276 printk(KERN_DEBUG "n_fi: already on 2nd channel\n");
2277#endif
2278 }
2279 }
2280 }
2281#ifdef ISDN_DEBUG_NET_ICALL
2282 printk(KERN_DEBUG "n_fi: match2\n");
2283#endif
2284 n = lp->phone[0];
2285 if (lp->flags & ISDN_NET_SECURE) {
2286 while (n) {
2287 if (!isdn_msncmp(nr, n->num))
2288 break;
2289 n = (isdn_net_phone *) n->next;
2290 }
2291 }
2292 if (n || (!(lp->flags & ISDN_NET_SECURE))) {
2293#ifdef ISDN_DEBUG_NET_ICALL
2294 printk(KERN_DEBUG "n_fi: match3\n");
2295#endif
2296 /* matching interface found */
2297
2298 /*
2299 * Is the state STOPPED?
2300 * If so, no dialin is allowed,
2301 * so reject actively.
2302 * */
2303 if (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF) {
2304 printk(KERN_INFO "incoming call, interface %s `stopped' -> rejected\n",
2305 lp->name);
2306 return 3;
2307 }
2308 /*
2309 * Is the interface up?
2310 * If not, reject the call actively.
2311 */
2312 if (!isdn_net_device_started(p)) {
2313 printk(KERN_INFO "%s: incoming call, interface down -> rejected\n",
2314 lp->name);
2315 return 3;
2316 }
2317 /* Interface is up, now see if it's a slave. If so, see if
2318 * it's master and parent slave is online. If not, reject the call.
2319 */
2320 if (lp->master) {
2321 isdn_net_local *mlp = (isdn_net_local *) lp->master->priv;
2322 printk(KERN_DEBUG "ICALLslv: %s\n", lp->name);
2323 printk(KERN_DEBUG "master=%s\n", mlp->name);
2324 if (mlp->flags & ISDN_NET_CONNECTED) {
2325 printk(KERN_DEBUG "master online\n");
2326 /* Master is online, find parent-slave (master if first slave) */
2327 while (mlp->slave) {
2328 if ((isdn_net_local *) mlp->slave->priv == lp)
2329 break;
2330 mlp = (isdn_net_local *) mlp->slave->priv;
2331 }
2332 } else
2333 printk(KERN_DEBUG "master offline\n");
2334 /* Found parent, if it's offline iterate next device */
2335 printk(KERN_DEBUG "mlpf: %d\n", mlp->flags & ISDN_NET_CONNECTED);
2336 if (!(mlp->flags & ISDN_NET_CONNECTED)) {
2337 p = (isdn_net_dev *) p->next;
2338 continue;
2339 }
2340 }
2341 if (lp->flags & ISDN_NET_CALLBACK) {
2342 int chi;
2343 /*
2344 * Is the state MANUAL?
2345 * If so, no callback can be made,
2346 * so reject actively.
2347 * */
2348 if (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF) {
2349 printk(KERN_INFO "incoming call for callback, interface %s `off' -> rejected\n",
2350 lp->name);
2351 return 3;
2352 }
2353 printk(KERN_DEBUG "%s: call from %s -> %s, start callback\n",
2354 lp->name, nr, eaz);
2355 if (lp->phone[1]) {
2356 /* Grab a free ISDN-Channel */
2357 spin_lock_irqsave(&dev->lock, flags);
2358 if ((chi =
2359 isdn_get_free_channel(
2360 ISDN_USAGE_NET,
2361 lp->l2_proto,
2362 lp->l3_proto,
2363 lp->pre_device,
2364 lp->pre_channel,
2365 lp->msn)
2366 ) < 0) {
2367
2368 printk(KERN_WARNING "isdn_net_find_icall: No channel for %s\n", lp->name);
2369 spin_unlock_irqrestore(&dev->lock, flags);
2370 return 0;
2371 }
2372 /* Setup dialstate. */
2373 lp->dtimer = 0;
2374 lp->dialstate = 11;
2375 /* Connect interface with channel */
2376 isdn_net_bind_channel(lp, chi);
2377#ifdef CONFIG_ISDN_PPP
2378 if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
2379 if (isdn_ppp_bind(lp) < 0) {
2380 spin_unlock_irqrestore(&dev->lock, flags);
2381 isdn_net_unbind_channel(lp);
2382 return 0;
2383 }
2384#endif
2385 spin_unlock_irqrestore(&dev->lock, flags);
2386 /* Initiate dialing by returning 2 or 4 */
2387 return (lp->flags & ISDN_NET_CBHUP) ? 2 : 4;
2388 } else
2389 printk(KERN_WARNING "isdn_net: %s: No phone number\n", lp->name);
2390 return 0;
2391 } else {
2392 printk(KERN_DEBUG "%s: call from %s -> %s accepted\n", lp->name, nr,
2393 eaz);
2394 /* if this interface is dialing, it does it probably on a different
2395 device, so free this device */
2396 if ((lp->dialstate == 4) || (lp->dialstate == 12)) {
2397#ifdef CONFIG_ISDN_PPP
2398 if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
2399 isdn_ppp_free(lp);
2400#endif
2401 isdn_net_lp_disconnected(lp);
2402 isdn_free_channel(lp->isdn_device, lp->isdn_channel,
2403 ISDN_USAGE_NET);
2404 }
2405 spin_lock_irqsave(&dev->lock, flags);
2406 dev->usage[idx] &= ISDN_USAGE_EXCLUSIVE;
2407 dev->usage[idx] |= ISDN_USAGE_NET;
2408 strcpy(dev->num[idx], nr);
2409 isdn_info_update();
2410 dev->st_netdev[idx] = lp->netdev;
2411 lp->isdn_device = di;
2412 lp->isdn_channel = ch;
2413 lp->ppp_slot = -1;
2414 lp->flags |= ISDN_NET_CONNECTED;
2415 lp->dialstate = 7;
2416 lp->dtimer = 0;
2417 lp->outgoing = 0;
2418 lp->huptimer = 0;
2419 lp->hupflags |= ISDN_WAITCHARGE;
2420 lp->hupflags &= ~ISDN_HAVECHARGE;
2421#ifdef CONFIG_ISDN_PPP
2422 if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) {
2423 if (isdn_ppp_bind(lp) < 0) {
2424 isdn_net_unbind_channel(lp);
2425 spin_unlock_irqrestore(&dev->lock, flags);
2426 return 0;
2427 }
2428 }
2429#endif
2430 spin_unlock_irqrestore(&dev->lock, flags);
2431 return 1;
2432 }
2433 }
2434 }
2435 p = (isdn_net_dev *) p->next;
2436 }
2437 /* If none of configured EAZ/MSN matched and not verbose, be silent */
2438 if (!ematch || dev->net_verbose)
2439 printk(KERN_INFO "isdn_net: call from %s -> %d %s ignored\n", nr, di, eaz);
2440 return (wret == 2)?5:0;
2441}
2442
2443/*
2444 * Search list of net-interfaces for an interface with given name.
2445 */
2446isdn_net_dev *
2447isdn_net_findif(char *name)
2448{
2449 isdn_net_dev *p = dev->netdev;
2450
2451 while (p) {
2452 if (!strcmp(p->local->name, name))
2453 return p;
2454 p = (isdn_net_dev *) p->next;
2455 }
2456 return (isdn_net_dev *) NULL;
2457}
2458
2459/*
2460 * Force a net-interface to dial out.
2461 * This is called from the userlevel-routine below or
2462 * from isdn_net_start_xmit().
2463 */
2464int
2465isdn_net_force_dial_lp(isdn_net_local * lp)
2466{
2467 if ((!(lp->flags & ISDN_NET_CONNECTED)) && !lp->dialstate) {
2468 int chi;
2469 if (lp->phone[1]) {
2470 ulong flags;
2471
2472 /* Grab a free ISDN-Channel */
2473 spin_lock_irqsave(&dev->lock, flags);
2474 if ((chi = isdn_get_free_channel(
2475 ISDN_USAGE_NET,
2476 lp->l2_proto,
2477 lp->l3_proto,
2478 lp->pre_device,
2479 lp->pre_channel,
2480 lp->msn)) < 0) {
2481 printk(KERN_WARNING "isdn_net_force_dial: No channel for %s\n", lp->name);
2482 spin_unlock_irqrestore(&dev->lock, flags);
2483 return -EAGAIN;
2484 }
2485 lp->dialstate = 1;
2486 /* Connect interface with channel */
2487 isdn_net_bind_channel(lp, chi);
2488#ifdef CONFIG_ISDN_PPP
2489 if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
2490 if (isdn_ppp_bind(lp) < 0) {
2491 isdn_net_unbind_channel(lp);
2492 spin_unlock_irqrestore(&dev->lock, flags);
2493 return -EAGAIN;
2494 }
2495#endif
2496 /* Initiate dialing */
2497 spin_unlock_irqrestore(&dev->lock, flags);
2498 isdn_net_dial();
2499 return 0;
2500 } else
2501 return -EINVAL;
2502 } else
2503 return -EBUSY;
2504}
2505
2506/*
2507 * This is called from certain upper protocol layers (multilink ppp
2508 * and x25iface encapsulation module) that want to initiate dialing
2509 * themselves.
2510 */
2511int
2512isdn_net_dial_req(isdn_net_local * lp)
2513{
2514 /* is there a better error code? */
2515 if (!(ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_AUTO)) return -EBUSY;
2516
2517 return isdn_net_force_dial_lp(lp);
2518}
2519
2520/*
2521 * Force a net-interface to dial out.
2522 * This is always called from within userspace (ISDN_IOCTL_NET_DIAL).
2523 */
2524int
2525isdn_net_force_dial(char *name)
2526{
2527 isdn_net_dev *p = isdn_net_findif(name);
2528
2529 if (!p)
2530 return -ENODEV;
2531 return (isdn_net_force_dial_lp(p->local));
2532}
2533
2534/*
2535 * Allocate a new network-interface and initialize its data structures.
2536 */
2537char *
2538isdn_net_new(char *name, struct net_device *master)
2539{
2540 isdn_net_dev *netdev;
2541
2542 /* Avoid creating an existing interface */
2543 if (isdn_net_findif(name)) {
2544 printk(KERN_WARNING "isdn_net: interface %s already exists\n", name);
2545 return NULL;
2546 }
2547 if (!(netdev = (isdn_net_dev *) kmalloc(sizeof(isdn_net_dev), GFP_KERNEL))) {
2548 printk(KERN_WARNING "isdn_net: Could not allocate net-device\n");
2549 return NULL;
2550 }
2551 memset(netdev, 0, sizeof(isdn_net_dev));
2552 if (!(netdev->local = (isdn_net_local *) kmalloc(sizeof(isdn_net_local), GFP_KERNEL))) {
2553 printk(KERN_WARNING "isdn_net: Could not allocate device locals\n");
2554 kfree(netdev);
2555 return NULL;
2556 }
2557 memset(netdev->local, 0, sizeof(isdn_net_local));
2558 if (name == NULL)
2559 strcpy(netdev->local->name, " ");
2560 else
2561 strcpy(netdev->local->name, name);
2562 strcpy(netdev->dev.name, netdev->local->name);
2563 netdev->dev.priv = netdev->local;
2564 netdev->dev.init = isdn_net_init;
2565 netdev->local->p_encap = ISDN_NET_ENCAP_RAWIP;
2566 if (master) {
2567 /* Device shall be a slave */
2568 struct net_device *p = (((isdn_net_local *) master->priv)->slave);
2569 struct net_device *q = master;
2570
2571 netdev->local->master = master;
2572 /* Put device at end of slave-chain */
2573 while (p) {
2574 q = p;
2575 p = (((isdn_net_local *) p->priv)->slave);
2576 }
2577 ((isdn_net_local *) q->priv)->slave = &(netdev->dev);
2578 } else {
2579 /* Device shall be a master */
2580 /*
2581 * Watchdog timer (currently) for master only.
2582 */
2583 netdev->dev.tx_timeout = isdn_net_tx_timeout;
2584 netdev->dev.watchdog_timeo = ISDN_NET_TX_TIMEOUT;
2585 if (register_netdev(&netdev->dev) != 0) {
2586 printk(KERN_WARNING "isdn_net: Could not register net-device\n");
2587 kfree(netdev->local);
2588 kfree(netdev);
2589 return NULL;
2590 }
2591 }
2592 netdev->local->magic = ISDN_NET_MAGIC;
2593
2594 netdev->queue = netdev->local;
2595 spin_lock_init(&netdev->queue_lock);
2596
2597 netdev->local->last = netdev->local;
2598 netdev->local->netdev = netdev;
2599 netdev->local->next = netdev->local;
2600
2601 INIT_WORK(&netdev->local->tqueue, (void *)(void *) isdn_net_softint, netdev->local);
2602 spin_lock_init(&netdev->local->xmit_lock);
2603
2604 netdev->local->isdn_device = -1;
2605 netdev->local->isdn_channel = -1;
2606 netdev->local->pre_device = -1;
2607 netdev->local->pre_channel = -1;
2608 netdev->local->exclusive = -1;
2609 netdev->local->ppp_slot = -1;
2610 netdev->local->pppbind = -1;
2611 skb_queue_head_init(&netdev->local->super_tx_queue);
2612 netdev->local->l2_proto = ISDN_PROTO_L2_X75I;
2613 netdev->local->l3_proto = ISDN_PROTO_L3_TRANS;
2614 netdev->local->triggercps = 6000;
2615 netdev->local->slavedelay = 10 * HZ;
2616 netdev->local->hupflags = ISDN_INHUP; /* Do hangup even on incoming calls */
2617 netdev->local->onhtime = 10; /* Default hangup-time for saving costs
2618 of those who forget configuring this */
2619 netdev->local->dialmax = 1;
2620 netdev->local->flags = ISDN_NET_CBHUP | ISDN_NET_DM_MANUAL; /* Hangup before Callback, manual dial */
2621 netdev->local->cbdelay = 25; /* Wait 5 secs before Callback */
2622 netdev->local->dialtimeout = -1; /* Infinite Dial-Timeout */
2623 netdev->local->dialwait = 5 * HZ; /* Wait 5 sec. after failed dial */
2624 netdev->local->dialstarted = 0; /* Jiffies of last dial-start */
2625 netdev->local->dialwait_timer = 0; /* Jiffies of earliest next dial-start */
2626
2627 /* Put into to netdev-chain */
2628 netdev->next = (void *) dev->netdev;
2629 dev->netdev = netdev;
2630 return netdev->dev.name;
2631}
2632
2633char *
2634isdn_net_newslave(char *parm)
2635{
2636 char *p = strchr(parm, ',');
2637 isdn_net_dev *n;
2638 char newname[10];
2639
2640 if (p) {
2641 /* Slave-Name MUST not be empty */
2642 if (!strlen(p + 1))
2643 return NULL;
2644 strcpy(newname, p + 1);
2645 *p = 0;
2646 /* Master must already exist */
2647 if (!(n = isdn_net_findif(parm)))
2648 return NULL;
2649 /* Master must be a real interface, not a slave */
2650 if (n->local->master)
2651 return NULL;
2652 /* Master must not be started yet */
2653 if (isdn_net_device_started(n))
2654 return NULL;
2655 return (isdn_net_new(newname, &(n->dev)));
2656 }
2657 return NULL;
2658}
2659
2660/*
2661 * Set interface-parameters.
2662 * Always set all parameters, so the user-level application is responsible
2663 * for not overwriting existing setups. It has to get the current
2664 * setup first, if only selected parameters are to be changed.
2665 */
2666int
2667isdn_net_setcfg(isdn_net_ioctl_cfg * cfg)
2668{
2669 isdn_net_dev *p = isdn_net_findif(cfg->name);
2670 ulong features;
2671 int i;
2672 int drvidx;
2673 int chidx;
2674 char drvid[25];
2675
2676 if (p) {
2677 isdn_net_local *lp = p->local;
2678
2679 /* See if any registered driver supports the features we want */
2680 features = ((1 << cfg->l2_proto) << ISDN_FEATURE_L2_SHIFT) |
2681 ((1 << cfg->l3_proto) << ISDN_FEATURE_L3_SHIFT);
2682 for (i = 0; i < ISDN_MAX_DRIVERS; i++)
2683 if (dev->drv[i])
2684 if ((dev->drv[i]->interface->features & features) == features)
2685 break;
2686 if (i == ISDN_MAX_DRIVERS) {
2687 printk(KERN_WARNING "isdn_net: No driver with selected features\n");
2688 return -ENODEV;
2689 }
2690 if (lp->p_encap != cfg->p_encap){
2691#ifdef CONFIG_ISDN_X25
2692 struct concap_proto * cprot = p -> cprot;
2693#endif
2694 if (isdn_net_device_started(p)) {
2695 printk(KERN_WARNING "%s: cannot change encap when if is up\n",
2696 lp->name);
2697 return -EBUSY;
2698 }
2699#ifdef CONFIG_ISDN_X25
2700 if( cprot && cprot -> pops )
2701 cprot -> pops -> proto_del ( cprot );
2702 p -> cprot = NULL;
2703 lp -> dops = NULL;
2704 /* ... , prepare for configuration of new one ... */
2705 switch ( cfg -> p_encap ){
2706 case ISDN_NET_ENCAP_X25IFACE:
2707 lp -> dops = &isdn_concap_reliable_dl_dops;
2708 }
2709 /* ... and allocate new one ... */
2710 p -> cprot = isdn_concap_new( cfg -> p_encap );
2711 /* p -> cprot == NULL now if p_encap is not supported
2712 by means of the concap_proto mechanism */
2713 /* the protocol is not configured yet; this will
2714 happen later when isdn_net_reset() is called */
2715#endif
2716 }
2717 switch ( cfg->p_encap ) {
2718 case ISDN_NET_ENCAP_SYNCPPP:
2719#ifndef CONFIG_ISDN_PPP
2720 printk(KERN_WARNING "%s: SyncPPP support not configured\n",
2721 lp->name);
2722 return -EINVAL;
2723#else
2724 p->dev.type = ARPHRD_PPP; /* change ARP type */
2725 p->dev.addr_len = 0;
2726 p->dev.do_ioctl = isdn_ppp_dev_ioctl;
2727#endif
2728 break;
2729 case ISDN_NET_ENCAP_X25IFACE:
2730#ifndef CONFIG_ISDN_X25
2731 printk(KERN_WARNING "%s: isdn-x25 support not configured\n",
2732 p->local->name);
2733 return -EINVAL;
2734#else
2735 p->dev.type = ARPHRD_X25; /* change ARP type */
2736 p->dev.addr_len = 0;
2737#endif
2738 break;
2739 case ISDN_NET_ENCAP_CISCOHDLCK:
2740 p->dev.do_ioctl = isdn_ciscohdlck_dev_ioctl;
2741 break;
2742 default:
2743 if( cfg->p_encap >= 0 &&
2744 cfg->p_encap <= ISDN_NET_ENCAP_MAX_ENCAP )
2745 break;
2746 printk(KERN_WARNING
2747 "%s: encapsulation protocol %d not supported\n",
2748 p->local->name, cfg->p_encap);
2749 return -EINVAL;
2750 }
2751 if (strlen(cfg->drvid)) {
2752 /* A bind has been requested ... */
2753 char *c,
2754 *e;
2755
2756 drvidx = -1;
2757 chidx = -1;
2758 strcpy(drvid, cfg->drvid);
2759 if ((c = strchr(drvid, ','))) {
2760 /* The channel-number is appended to the driver-Id with a comma */
2761 chidx = (int) simple_strtoul(c + 1, &e, 10);
2762 if (e == c)
2763 chidx = -1;
2764 *c = '\0';
2765 }
2766 for (i = 0; i < ISDN_MAX_DRIVERS; i++)
2767 /* Lookup driver-Id in array */
2768 if (!(strcmp(dev->drvid[i], drvid))) {
2769 drvidx = i;
2770 break;
2771 }
2772 if ((drvidx == -1) || (chidx == -1))
2773 /* Either driver-Id or channel-number invalid */
2774 return -ENODEV;
2775 } else {
2776 /* Parameters are valid, so get them */
2777 drvidx = lp->pre_device;
2778 chidx = lp->pre_channel;
2779 }
2780 if (cfg->exclusive > 0) {
2781 unsigned long flags;
2782
2783 /* If binding is exclusive, try to grab the channel */
2784 spin_lock_irqsave(&dev->lock, flags);
2785 if ((i = isdn_get_free_channel(ISDN_USAGE_NET,
2786 lp->l2_proto, lp->l3_proto, drvidx,
2787 chidx, lp->msn)) < 0) {
2788 /* Grab failed, because desired channel is in use */
2789 lp->exclusive = -1;
2790 spin_unlock_irqrestore(&dev->lock, flags);
2791 return -EBUSY;
2792 }
2793 /* All went ok, so update isdninfo */
2794 dev->usage[i] = ISDN_USAGE_EXCLUSIVE;
2795 isdn_info_update();
2796 spin_unlock_irqrestore(&dev->lock, flags);
2797 lp->exclusive = i;
2798 } else {
2799 /* Non-exclusive binding or unbind. */
2800 lp->exclusive = -1;
2801 if ((lp->pre_device != -1) && (cfg->exclusive == -1)) {
2802 isdn_unexclusive_channel(lp->pre_device, lp->pre_channel);
2803 isdn_free_channel(lp->pre_device, lp->pre_channel, ISDN_USAGE_NET);
2804 drvidx = -1;
2805 chidx = -1;
2806 }
2807 }
2808 strcpy(lp->msn, cfg->eaz);
2809 lp->pre_device = drvidx;
2810 lp->pre_channel = chidx;
2811 lp->onhtime = cfg->onhtime;
2812 lp->charge = cfg->charge;
2813 lp->l2_proto = cfg->l2_proto;
2814 lp->l3_proto = cfg->l3_proto;
2815 lp->cbdelay = cfg->cbdelay;
2816 lp->dialmax = cfg->dialmax;
2817 lp->triggercps = cfg->triggercps;
2818 lp->slavedelay = cfg->slavedelay * HZ;
2819 lp->pppbind = cfg->pppbind;
2820 lp->dialtimeout = cfg->dialtimeout >= 0 ? cfg->dialtimeout * HZ : -1;
2821 lp->dialwait = cfg->dialwait * HZ;
2822 if (cfg->secure)
2823 lp->flags |= ISDN_NET_SECURE;
2824 else
2825 lp->flags &= ~ISDN_NET_SECURE;
2826 if (cfg->cbhup)
2827 lp->flags |= ISDN_NET_CBHUP;
2828 else
2829 lp->flags &= ~ISDN_NET_CBHUP;
2830 switch (cfg->callback) {
2831 case 0:
2832 lp->flags &= ~(ISDN_NET_CALLBACK | ISDN_NET_CBOUT);
2833 break;
2834 case 1:
2835 lp->flags |= ISDN_NET_CALLBACK;
2836 lp->flags &= ~ISDN_NET_CBOUT;
2837 break;
2838 case 2:
2839 lp->flags |= ISDN_NET_CBOUT;
2840 lp->flags &= ~ISDN_NET_CALLBACK;
2841 break;
2842 }
2843 lp->flags &= ~ISDN_NET_DIALMODE_MASK; /* first all bits off */
2844 if (cfg->dialmode && !(cfg->dialmode & ISDN_NET_DIALMODE_MASK)) {
2845 /* old isdnctrl version, where only 0 or 1 is given */
2846 printk(KERN_WARNING
2847 "Old isdnctrl version detected! Please update.\n");
2848 lp->flags |= ISDN_NET_DM_OFF; /* turn on `off' bit */
2849 }
2850 else {
2851 lp->flags |= cfg->dialmode; /* turn on selected bits */
2852 }
2853 if (cfg->chargehup)
2854 lp->hupflags |= ISDN_CHARGEHUP;
2855 else
2856 lp->hupflags &= ~ISDN_CHARGEHUP;
2857 if (cfg->ihup)
2858 lp->hupflags |= ISDN_INHUP;
2859 else
2860 lp->hupflags &= ~ISDN_INHUP;
2861 if (cfg->chargeint > 10) {
2862 lp->hupflags |= ISDN_CHARGEHUP | ISDN_HAVECHARGE | ISDN_MANCHARGE;
2863 lp->chargeint = cfg->chargeint * HZ;
2864 }
2865 if (cfg->p_encap != lp->p_encap) {
2866 if (cfg->p_encap == ISDN_NET_ENCAP_RAWIP) {
2867 p->dev.hard_header = NULL;
2868 p->dev.hard_header_cache = NULL;
2869 p->dev.header_cache_update = NULL;
2870 p->dev.flags = IFF_NOARP|IFF_POINTOPOINT;
2871 } else {
2872 p->dev.hard_header = isdn_net_header;
2873 if (cfg->p_encap == ISDN_NET_ENCAP_ETHER) {
2874 p->dev.hard_header_cache = lp->org_hhc;
2875 p->dev.header_cache_update = lp->org_hcu;
2876 p->dev.flags = IFF_BROADCAST | IFF_MULTICAST;
2877 } else {
2878 p->dev.hard_header_cache = NULL;
2879 p->dev.header_cache_update = NULL;
2880 p->dev.flags = IFF_NOARP|IFF_POINTOPOINT;
2881 }
2882 }
2883 }
2884 lp->p_encap = cfg->p_encap;
2885 return 0;
2886 }
2887 return -ENODEV;
2888}
2889
2890/*
2891 * Perform get-interface-parameters.ioctl
2892 */
2893int
2894isdn_net_getcfg(isdn_net_ioctl_cfg * cfg)
2895{
2896 isdn_net_dev *p = isdn_net_findif(cfg->name);
2897
2898 if (p) {
2899 isdn_net_local *lp = p->local;
2900
2901 strcpy(cfg->eaz, lp->msn);
2902 cfg->exclusive = lp->exclusive;
2903 if (lp->pre_device >= 0) {
2904 sprintf(cfg->drvid, "%s,%d", dev->drvid[lp->pre_device],
2905 lp->pre_channel);
2906 } else
2907 cfg->drvid[0] = '\0';
2908 cfg->onhtime = lp->onhtime;
2909 cfg->charge = lp->charge;
2910 cfg->l2_proto = lp->l2_proto;
2911 cfg->l3_proto = lp->l3_proto;
2912 cfg->p_encap = lp->p_encap;
2913 cfg->secure = (lp->flags & ISDN_NET_SECURE) ? 1 : 0;
2914 cfg->callback = 0;
2915 if (lp->flags & ISDN_NET_CALLBACK)
2916 cfg->callback = 1;
2917 if (lp->flags & ISDN_NET_CBOUT)
2918 cfg->callback = 2;
2919 cfg->cbhup = (lp->flags & ISDN_NET_CBHUP) ? 1 : 0;
2920 cfg->dialmode = lp->flags & ISDN_NET_DIALMODE_MASK;
2921 cfg->chargehup = (lp->hupflags & 4) ? 1 : 0;
2922 cfg->ihup = (lp->hupflags & 8) ? 1 : 0;
2923 cfg->cbdelay = lp->cbdelay;
2924 cfg->dialmax = lp->dialmax;
2925 cfg->triggercps = lp->triggercps;
2926 cfg->slavedelay = lp->slavedelay / HZ;
2927 cfg->chargeint = (lp->hupflags & ISDN_CHARGEHUP) ?
2928 (lp->chargeint / HZ) : 0;
2929 cfg->pppbind = lp->pppbind;
2930 cfg->dialtimeout = lp->dialtimeout >= 0 ? lp->dialtimeout / HZ : -1;
2931 cfg->dialwait = lp->dialwait / HZ;
2932 if (lp->slave)
2933 strcpy(cfg->slave, ((isdn_net_local *) lp->slave->priv)->name);
2934 else
2935 cfg->slave[0] = '\0';
2936 if (lp->master)
2937 strcpy(cfg->master, ((isdn_net_local *) lp->master->priv)->name);
2938 else
2939 cfg->master[0] = '\0';
2940 return 0;
2941 }
2942 return -ENODEV;
2943}
2944
2945/*
2946 * Add a phone-number to an interface.
2947 */
2948int
2949isdn_net_addphone(isdn_net_ioctl_phone * phone)
2950{
2951 isdn_net_dev *p = isdn_net_findif(phone->name);
2952 isdn_net_phone *n;
2953
2954 if (p) {
2955 if (!(n = (isdn_net_phone *) kmalloc(sizeof(isdn_net_phone), GFP_KERNEL)))
2956 return -ENOMEM;
2957 strcpy(n->num, phone->phone);
2958 n->next = p->local->phone[phone->outgoing & 1];
2959 p->local->phone[phone->outgoing & 1] = n;
2960 return 0;
2961 }
2962 return -ENODEV;
2963}
2964
2965/*
2966 * Copy a string of all phone-numbers of an interface to user space.
2967 * This might sleep and must be called with the isdn semaphore down.
2968 */
2969int
2970isdn_net_getphones(isdn_net_ioctl_phone * phone, char __user *phones)
2971{
2972 isdn_net_dev *p = isdn_net_findif(phone->name);
2973 int inout = phone->outgoing & 1;
2974 int more = 0;
2975 int count = 0;
2976 isdn_net_phone *n;
2977
2978 if (!p)
2979 return -ENODEV;
2980 inout &= 1;
2981 for (n = p->local->phone[inout]; n; n = n->next) {
2982 if (more) {
2983 put_user(' ', phones++);
2984 count++;
2985 }
2986 if (copy_to_user(phones, n->num, strlen(n->num) + 1)) {
2987 return -EFAULT;
2988 }
2989 phones += strlen(n->num);
2990 count += strlen(n->num);
2991 more = 1;
2992 }
2993 put_user(0, phones);
2994 count++;
2995 return count;
2996}
2997
2998/*
2999 * Copy a string containing the peer's phone number of a connected interface
3000 * to user space.
3001 */
3002int
3003isdn_net_getpeer(isdn_net_ioctl_phone *phone, isdn_net_ioctl_phone __user *peer)
3004{
3005 isdn_net_dev *p = isdn_net_findif(phone->name);
3006 int ch, dv, idx;
3007
3008 if (!p) return -ENODEV;
3009 /*
3010 * Theoretical race: while this executes, the remote number might
3011 * become invalid (hang up) or change (new connection), resulting
3012 * in (partially) wrong number copied to user. This race
3013 * currently ignored.
3014 */
3015 ch = p->local->isdn_channel;
3016 dv = p->local->isdn_device;
3017 if(ch<0 && dv<0) return -ENOTCONN;
3018 idx = isdn_dc2minor(dv, ch);
3019 if (idx<0) return -ENODEV;
3020 /* for pre-bound channels, we need this extra check */
3021 if ( strncmp(dev->num[idx],"???",3) == 0 ) return -ENOTCONN;
3022 strncpy(phone->phone,dev->num[idx],ISDN_MSNLEN);
3023 phone->outgoing=USG_OUTGOING(dev->usage[idx]);
3024 if ( copy_to_user(peer,phone,sizeof(*peer)) ) return -EFAULT;
3025 return 0;
3026}
3027/*
3028 * Delete a phone-number from an interface.
3029 */
3030int
3031isdn_net_delphone(isdn_net_ioctl_phone * phone)
3032{
3033 isdn_net_dev *p = isdn_net_findif(phone->name);
3034 int inout = phone->outgoing & 1;
3035 isdn_net_phone *n;
3036 isdn_net_phone *m;
3037
3038 if (p) {
3039 n = p->local->phone[inout];
3040 m = NULL;
3041 while (n) {
3042 if (!strcmp(n->num, phone->phone)) {
3043 if (p->local->dial == n)
3044 p->local->dial = n->next;
3045 if (m)
3046 m->next = n->next;
3047 else
3048 p->local->phone[inout] = n->next;
3049 kfree(n);
3050 return 0;
3051 }
3052 m = n;
3053 n = (isdn_net_phone *) n->next;
3054 }
3055 return -EINVAL;
3056 }
3057 return -ENODEV;
3058}
3059
3060/*
3061 * Delete all phone-numbers of an interface.
3062 */
3063static int
3064isdn_net_rmallphone(isdn_net_dev * p)
3065{
3066 isdn_net_phone *n;
3067 isdn_net_phone *m;
3068 int i;
3069
3070 for (i = 0; i < 2; i++) {
3071 n = p->local->phone[i];
3072 while (n) {
3073 m = n->next;
3074 kfree(n);
3075 n = m;
3076 }
3077 p->local->phone[i] = NULL;
3078 }
3079 p->local->dial = NULL;
3080 return 0;
3081}
3082
3083/*
3084 * Force a hangup of a network-interface.
3085 */
3086int
3087isdn_net_force_hangup(char *name)
3088{
3089 isdn_net_dev *p = isdn_net_findif(name);
3090 struct net_device *q;
3091
3092 if (p) {
3093 if (p->local->isdn_device < 0)
3094 return 1;
3095 q = p->local->slave;
3096 /* If this interface has slaves, do a hangup for them also. */
3097 while (q) {
3098 isdn_net_hangup(q);
3099 q = (((isdn_net_local *) q->priv)->slave);
3100 }
3101 isdn_net_hangup(&p->dev);
3102 return 0;
3103 }
3104 return -ENODEV;
3105}
3106
3107/*
3108 * Helper-function for isdn_net_rm: Do the real work.
3109 */
3110static int
3111isdn_net_realrm(isdn_net_dev * p, isdn_net_dev * q)
3112{
3113 u_long flags;
3114
3115 if (isdn_net_device_started(p)) {
3116 return -EBUSY;
3117 }
3118#ifdef CONFIG_ISDN_X25
3119 if( p -> cprot && p -> cprot -> pops )
3120 p -> cprot -> pops -> proto_del ( p -> cprot );
3121#endif
3122 /* Free all phone-entries */
3123 isdn_net_rmallphone(p);
3124 /* If interface is bound exclusive, free channel-usage */
3125 if (p->local->exclusive != -1)
3126 isdn_unexclusive_channel(p->local->pre_device, p->local->pre_channel);
3127 if (p->local->master) {
3128 /* It's a slave-device, so update master's slave-pointer if necessary */
3129 if (((isdn_net_local *) (p->local->master->priv))->slave == &p->dev)
3130 ((isdn_net_local *) (p->local->master->priv))->slave = p->local->slave;
3131 } else {
3132 /* Unregister only if it's a master-device */
3133 p->dev.hard_header_cache = p->local->org_hhc;
3134 p->dev.header_cache_update = p->local->org_hcu;
3135 unregister_netdev(&p->dev);
3136 }
3137 /* Unlink device from chain */
3138 spin_lock_irqsave(&dev->lock, flags);
3139 if (q)
3140 q->next = p->next;
3141 else
3142 dev->netdev = p->next;
3143 if (p->local->slave) {
3144 /* If this interface has a slave, remove it also */
3145 char *slavename = ((isdn_net_local *) (p->local->slave->priv))->name;
3146 isdn_net_dev *n = dev->netdev;
3147 q = NULL;
3148 while (n) {
3149 if (!strcmp(n->local->name, slavename)) {
3150 spin_unlock_irqrestore(&dev->lock, flags);
3151 isdn_net_realrm(n, q);
3152 spin_lock_irqsave(&dev->lock, flags);
3153 break;
3154 }
3155 q = n;
3156 n = (isdn_net_dev *) n->next;
3157 }
3158 }
3159 spin_unlock_irqrestore(&dev->lock, flags);
3160 /* If no more net-devices remain, disable auto-hangup timer */
3161 if (dev->netdev == NULL)
3162 isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, 0);
3163 kfree(p->local);
3164 kfree(p);
3165
3166 return 0;
3167}
3168
3169/*
3170 * Remove a single network-interface.
3171 */
3172int
3173isdn_net_rm(char *name)
3174{
3175 u_long flags;
3176 isdn_net_dev *p;
3177 isdn_net_dev *q;
3178
3179 /* Search name in netdev-chain */
3180 spin_lock_irqsave(&dev->lock, flags);
3181 p = dev->netdev;
3182 q = NULL;
3183 while (p) {
3184 if (!strcmp(p->local->name, name)) {
3185 spin_unlock_irqrestore(&dev->lock, flags);
3186 return (isdn_net_realrm(p, q));
3187 }
3188 q = p;
3189 p = (isdn_net_dev *) p->next;
3190 }
3191 spin_unlock_irqrestore(&dev->lock, flags);
3192 /* If no more net-devices remain, disable auto-hangup timer */
3193 if (dev->netdev == NULL)
3194 isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, 0);
3195 return -ENODEV;
3196}
3197
3198/*
3199 * Remove all network-interfaces
3200 */
3201int
3202isdn_net_rmall(void)
3203{
3204 u_long flags;
3205 int ret;
3206
3207 /* Walk through netdev-chain */
3208 spin_lock_irqsave(&dev->lock, flags);
3209 while (dev->netdev) {
3210 if (!dev->netdev->local->master) {
3211 /* Remove master-devices only, slaves get removed with their master */
3212 spin_unlock_irqrestore(&dev->lock, flags);
3213 if ((ret = isdn_net_realrm(dev->netdev, NULL))) {
3214 return ret;
3215 }
3216 spin_lock_irqsave(&dev->lock, flags);
3217 }
3218 }
3219 dev->netdev = NULL;
3220 spin_unlock_irqrestore(&dev->lock, flags);
3221 return 0;
3222}
diff --git a/drivers/isdn/i4l/isdn_net.h b/drivers/isdn/i4l/isdn_net.h
new file mode 100644
index 000000000000..bc2f0dd962ea
--- /dev/null
+++ b/drivers/isdn/i4l/isdn_net.h
@@ -0,0 +1,190 @@
1/* $Id: isdn_net.h,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $
2 *
3 * header for Linux ISDN subsystem, network related functions (linklevel).
4 *
5 * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de)
6 * Copyright 1995,96 by Thinking Objects Software GmbH Wuerzburg
7 * Copyright 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.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.
11 *
12 */
13
14 /* Definitions for hupflags: */
15#define ISDN_WAITCHARGE 1 /* did not get a charge info yet */
16#define ISDN_HAVECHARGE 2 /* We know a charge info */
17#define ISDN_CHARGEHUP 4 /* We want to use the charge mechanism */
18#define ISDN_INHUP 8 /* Even if incoming, close after huptimeout */
19#define ISDN_MANCHARGE 16 /* Charge Interval manually set */
20
21/*
22 * Definitions for Cisco-HDLC header.
23 */
24
25#define CISCO_ADDR_UNICAST 0x0f
26#define CISCO_ADDR_BROADCAST 0x8f
27#define CISCO_CTRL 0x00
28#define CISCO_TYPE_CDP 0x2000
29#define CISCO_TYPE_SLARP 0x8035
30#define CISCO_SLARP_REQUEST 0
31#define CISCO_SLARP_REPLY 1
32#define CISCO_SLARP_KEEPALIVE 2
33
34extern char *isdn_net_new(char *, struct net_device *);
35extern char *isdn_net_newslave(char *);
36extern int isdn_net_rm(char *);
37extern int isdn_net_rmall(void);
38extern int isdn_net_stat_callback(int, isdn_ctrl *);
39extern int isdn_net_setcfg(isdn_net_ioctl_cfg *);
40extern int isdn_net_getcfg(isdn_net_ioctl_cfg *);
41extern int isdn_net_addphone(isdn_net_ioctl_phone *);
42extern int isdn_net_getphones(isdn_net_ioctl_phone *, char __user *);
43extern int isdn_net_getpeer(isdn_net_ioctl_phone *, isdn_net_ioctl_phone __user *);
44extern int isdn_net_delphone(isdn_net_ioctl_phone *);
45extern int isdn_net_find_icall(int, int, int, setup_parm *);
46extern void isdn_net_hangup(struct net_device *);
47extern void isdn_net_dial(void);
48extern void isdn_net_autohup(void);
49extern int isdn_net_force_hangup(char *);
50extern int isdn_net_force_dial(char *);
51extern isdn_net_dev *isdn_net_findif(char *);
52extern int isdn_net_rcv_skb(int, struct sk_buff *);
53extern int isdn_net_dial_req(isdn_net_local *);
54extern void isdn_net_writebuf_skb(isdn_net_local *lp, struct sk_buff *skb);
55extern void isdn_net_write_super(isdn_net_local *lp, struct sk_buff *skb);
56
57#define ISDN_NET_MAX_QUEUE_LENGTH 2
58
59/*
60 * is this particular channel busy?
61 */
62static __inline__ int isdn_net_lp_busy(isdn_net_local *lp)
63{
64 if (atomic_read(&lp->frame_cnt) < ISDN_NET_MAX_QUEUE_LENGTH)
65 return 0;
66 else
67 return 1;
68}
69
70/*
71 * For the given net device, this will get a non-busy channel out of the
72 * corresponding bundle. The returned channel is locked.
73 */
74static __inline__ isdn_net_local * isdn_net_get_locked_lp(isdn_net_dev *nd)
75{
76 unsigned long flags;
77 isdn_net_local *lp;
78
79 spin_lock_irqsave(&nd->queue_lock, flags);
80 lp = nd->queue; /* get lp on top of queue */
81 spin_lock(&nd->queue->xmit_lock);
82 while (isdn_net_lp_busy(nd->queue)) {
83 spin_unlock(&nd->queue->xmit_lock);
84 nd->queue = nd->queue->next;
85 if (nd->queue == lp) { /* not found -- should never happen */
86 lp = NULL;
87 goto errout;
88 }
89 spin_lock(&nd->queue->xmit_lock);
90 }
91 lp = nd->queue;
92 nd->queue = nd->queue->next;
93 local_bh_disable();
94errout:
95 spin_unlock_irqrestore(&nd->queue_lock, flags);
96 return lp;
97}
98
99/*
100 * add a channel to a bundle
101 */
102static __inline__ void isdn_net_add_to_bundle(isdn_net_dev *nd, isdn_net_local *nlp)
103{
104 isdn_net_local *lp;
105 unsigned long flags;
106
107 spin_lock_irqsave(&nd->queue_lock, flags);
108
109 lp = nd->queue;
110// printk(KERN_DEBUG "%s: lp:%s(%p) nlp:%s(%p) last(%p)\n",
111// __FUNCTION__, lp->name, lp, nlp->name, nlp, lp->last);
112 nlp->last = lp->last;
113 lp->last->next = nlp;
114 lp->last = nlp;
115 nlp->next = lp;
116 nd->queue = nlp;
117
118 spin_unlock_irqrestore(&nd->queue_lock, flags);
119}
120/*
121 * remove a channel from the bundle it belongs to
122 */
123static __inline__ void isdn_net_rm_from_bundle(isdn_net_local *lp)
124{
125 isdn_net_local *master_lp = lp;
126 unsigned long flags;
127
128 if (lp->master)
129 master_lp = (isdn_net_local *) lp->master->priv;
130
131// printk(KERN_DEBUG "%s: lp:%s(%p) mlp:%s(%p) last(%p) next(%p) mndq(%p)\n",
132// __FUNCTION__, lp->name, lp, master_lp->name, master_lp, lp->last, lp->next, master_lp->netdev->queue);
133 spin_lock_irqsave(&master_lp->netdev->queue_lock, flags);
134 lp->last->next = lp->next;
135 lp->next->last = lp->last;
136 if (master_lp->netdev->queue == lp) {
137 master_lp->netdev->queue = lp->next;
138 if (lp->next == lp) { /* last in queue */
139 master_lp->netdev->queue = master_lp->netdev->local;
140 }
141 }
142 lp->next = lp->last = lp; /* (re)set own pointers */
143// printk(KERN_DEBUG "%s: mndq(%p)\n",
144// __FUNCTION__, master_lp->netdev->queue);
145 spin_unlock_irqrestore(&master_lp->netdev->queue_lock, flags);
146}
147
148static inline int
149put_u8(unsigned char *p, u8 x)
150{
151 *p = x;
152 return 1;
153}
154
155static inline int
156put_u16(unsigned char *p, u16 x)
157{
158 *((u16 *)p) = htons(x);
159 return 2;
160}
161
162static inline int
163put_u32(unsigned char *p, u32 x)
164{
165 *((u32 *)p) = htonl(x);
166 return 4;
167}
168
169static inline int
170get_u8(unsigned char *p, u8 *x)
171{
172 *x = *p;
173 return 1;
174}
175
176static inline int
177get_u16(unsigned char *p, u16 *x)
178{
179 *x = ntohs(*((u16 *)p));
180 return 2;
181}
182
183static inline int
184get_u32(unsigned char *p, u32 *x)
185{
186 *x = ntohl(*((u32 *)p));
187 return 4;
188}
189
190
diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c
new file mode 100644
index 000000000000..3c092117a8ea
--- /dev/null
+++ b/drivers/isdn/i4l/isdn_ppp.c
@@ -0,0 +1,3020 @@
1/* $Id: isdn_ppp.c,v 1.1.2.3 2004/02/10 01:07:13 keil Exp $
2 *
3 * Linux ISDN subsystem, functions for synchronous PPP (linklevel).
4 *
5 * Copyright 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
6 *
7 * This software may be used and distributed according to the terms
8 * of the GNU General Public License, incorporated herein by reference.
9 *
10 */
11
12#include <linux/config.h>
13#include <linux/isdn.h>
14#include <linux/poll.h>
15#include <linux/ppp-comp.h>
16#ifdef CONFIG_IPPP_FILTER
17#include <linux/filter.h>
18#endif
19
20#include "isdn_common.h"
21#include "isdn_ppp.h"
22#include "isdn_net.h"
23
24#ifndef PPP_IPX
25#define PPP_IPX 0x002b
26#endif
27
28/* Prototypes */
29static int isdn_ppp_fill_rq(unsigned char *buf, int len, int proto, int slot);
30static int isdn_ppp_closewait(int slot);
31static void isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp,
32 struct sk_buff *skb, int proto);
33static int isdn_ppp_if_get_unit(char *namebuf);
34static int isdn_ppp_set_compressor(struct ippp_struct *is,struct isdn_ppp_comp_data *);
35static struct sk_buff *isdn_ppp_decompress(struct sk_buff *,
36 struct ippp_struct *,struct ippp_struct *,int *proto);
37static void isdn_ppp_receive_ccp(isdn_net_dev * net_dev, isdn_net_local * lp,
38 struct sk_buff *skb,int proto);
39static struct sk_buff *isdn_ppp_compress(struct sk_buff *skb_in,int *proto,
40 struct ippp_struct *is,struct ippp_struct *master,int type);
41static void isdn_ppp_send_ccp(isdn_net_dev *net_dev, isdn_net_local *lp,
42 struct sk_buff *skb);
43
44/* New CCP stuff */
45static void isdn_ppp_ccp_kickup(struct ippp_struct *is);
46static void isdn_ppp_ccp_xmit_reset(struct ippp_struct *is, int proto,
47 unsigned char code, unsigned char id,
48 unsigned char *data, int len);
49static struct ippp_ccp_reset *isdn_ppp_ccp_reset_alloc(struct ippp_struct *is);
50static void isdn_ppp_ccp_reset_free(struct ippp_struct *is);
51static void isdn_ppp_ccp_reset_free_state(struct ippp_struct *is,
52 unsigned char id);
53static void isdn_ppp_ccp_timer_callback(unsigned long closure);
54static struct ippp_ccp_reset_state *isdn_ppp_ccp_reset_alloc_state(struct ippp_struct *is,
55 unsigned char id);
56static void isdn_ppp_ccp_reset_trans(struct ippp_struct *is,
57 struct isdn_ppp_resetparams *rp);
58static void isdn_ppp_ccp_reset_ack_rcvd(struct ippp_struct *is,
59 unsigned char id);
60
61
62
63#ifdef CONFIG_ISDN_MPP
64static ippp_bundle * isdn_ppp_bundle_arr = NULL;
65
66static int isdn_ppp_mp_bundle_array_init(void);
67static int isdn_ppp_mp_init( isdn_net_local * lp, ippp_bundle * add_to );
68static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
69 struct sk_buff *skb);
70static void isdn_ppp_mp_cleanup( isdn_net_local * lp );
71
72static int isdn_ppp_bundle(struct ippp_struct *, int unit);
73#endif /* CONFIG_ISDN_MPP */
74
75char *isdn_ppp_revision = "$Revision: 1.1.2.3 $";
76
77static struct ippp_struct *ippp_table[ISDN_MAX_CHANNELS];
78
79static struct isdn_ppp_compressor *ipc_head = NULL;
80
81/*
82 * frame log (debug)
83 */
84static void
85isdn_ppp_frame_log(char *info, char *data, int len, int maxlen,int unit,int slot)
86{
87 int cnt,
88 j,
89 i;
90 char buf[80];
91
92 if (len < maxlen)
93 maxlen = len;
94
95 for (i = 0, cnt = 0; cnt < maxlen; i++) {
96 for (j = 0; j < 16 && cnt < maxlen; j++, cnt++)
97 sprintf(buf + j * 3, "%02x ", (unsigned char) data[cnt]);
98 printk(KERN_DEBUG "[%d/%d].%s[%d]: %s\n",unit,slot, info, i, buf);
99 }
100}
101
102/*
103 * unbind isdn_net_local <=> ippp-device
104 * note: it can happen, that we hangup/free the master before the slaves
105 * in this case we bind another lp to the master device
106 */
107int
108isdn_ppp_free(isdn_net_local * lp)
109{
110 struct ippp_struct *is;
111
112 if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) {
113 printk(KERN_ERR "%s: ppp_slot(%d) out of range\n",
114 __FUNCTION__, lp->ppp_slot);
115 return 0;
116 }
117
118#ifdef CONFIG_ISDN_MPP
119 spin_lock(&lp->netdev->pb->lock);
120#endif
121 isdn_net_rm_from_bundle(lp);
122#ifdef CONFIG_ISDN_MPP
123 if (lp->netdev->pb->ref_ct == 1) /* last link in queue? */
124 isdn_ppp_mp_cleanup(lp);
125
126 lp->netdev->pb->ref_ct--;
127 spin_unlock(&lp->netdev->pb->lock);
128#endif /* CONFIG_ISDN_MPP */
129 if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) {
130 printk(KERN_ERR "%s: ppp_slot(%d) now invalid\n",
131 __FUNCTION__, lp->ppp_slot);
132 return 0;
133 }
134 is = ippp_table[lp->ppp_slot];
135 if ((is->state & IPPP_CONNECT))
136 isdn_ppp_closewait(lp->ppp_slot); /* force wakeup on ippp device */
137 else if (is->state & IPPP_ASSIGNED)
138 is->state = IPPP_OPEN; /* fallback to 'OPEN but not ASSIGNED' state */
139
140 if (is->debug & 0x1)
141 printk(KERN_DEBUG "isdn_ppp_free %d %lx %lx\n", lp->ppp_slot, (long) lp, (long) is->lp);
142
143 is->lp = NULL; /* link is down .. set lp to NULL */
144 lp->ppp_slot = -1; /* is this OK ?? */
145
146 return 0;
147}
148
149/*
150 * bind isdn_net_local <=> ippp-device
151 *
152 * This function is allways called with holding dev->lock so
153 * no additional lock is needed
154 */
155int
156isdn_ppp_bind(isdn_net_local * lp)
157{
158 int i;
159 int unit = 0;
160 struct ippp_struct *is;
161 int retval;
162
163 if (lp->pppbind < 0) { /* device bounded to ippp device ? */
164 isdn_net_dev *net_dev = dev->netdev;
165 char exclusive[ISDN_MAX_CHANNELS]; /* exclusive flags */
166 memset(exclusive, 0, ISDN_MAX_CHANNELS);
167 while (net_dev) { /* step through net devices to find exclusive minors */
168 isdn_net_local *lp = net_dev->local;
169 if (lp->pppbind >= 0)
170 exclusive[lp->pppbind] = 1;
171 net_dev = net_dev->next;
172 }
173 /*
174 * search a free device / slot
175 */
176 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
177 if (ippp_table[i]->state == IPPP_OPEN && !exclusive[ippp_table[i]->minor]) { /* OPEN, but not connected! */
178 break;
179 }
180 }
181 } else {
182 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
183 if (ippp_table[i]->minor == lp->pppbind &&
184 (ippp_table[i]->state & IPPP_OPEN) == IPPP_OPEN)
185 break;
186 }
187 }
188
189 if (i >= ISDN_MAX_CHANNELS) {
190 printk(KERN_WARNING "isdn_ppp_bind: Can't find a (free) connection to the ipppd daemon.\n");
191 retval = -1;
192 goto out;
193 }
194 unit = isdn_ppp_if_get_unit(lp->name); /* get unit number from interface name .. ugly! */
195 if (unit < 0) {
196 printk(KERN_ERR "isdn_ppp_bind: illegal interface name %s.\n", lp->name);
197 retval = -1;
198 goto out;
199 }
200
201 lp->ppp_slot = i;
202 is = ippp_table[i];
203 is->lp = lp;
204 is->unit = unit;
205 is->state = IPPP_OPEN | IPPP_ASSIGNED; /* assigned to a netdevice but not connected */
206#ifdef CONFIG_ISDN_MPP
207 retval = isdn_ppp_mp_init(lp, NULL);
208 if (retval < 0)
209 goto out;
210#endif /* CONFIG_ISDN_MPP */
211
212 retval = lp->ppp_slot;
213
214 out:
215 return retval;
216}
217
218/*
219 * kick the ipppd on the device
220 * (wakes up daemon after B-channel connect)
221 */
222
223void
224isdn_ppp_wakeup_daemon(isdn_net_local * lp)
225{
226 if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) {
227 printk(KERN_ERR "%s: ppp_slot(%d) out of range\n",
228 __FUNCTION__, lp->ppp_slot);
229 return;
230 }
231 ippp_table[lp->ppp_slot]->state = IPPP_OPEN | IPPP_CONNECT | IPPP_NOBLOCK;
232 wake_up_interruptible(&ippp_table[lp->ppp_slot]->wq);
233}
234
235/*
236 * there was a hangup on the netdevice
237 * force wakeup of the ippp device
238 * go into 'device waits for release' state
239 */
240static int
241isdn_ppp_closewait(int slot)
242{
243 struct ippp_struct *is;
244
245 if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
246 printk(KERN_ERR "%s: slot(%d) out of range\n",
247 __FUNCTION__, slot);
248 return 0;
249 }
250 is = ippp_table[slot];
251 if (is->state)
252 wake_up_interruptible(&is->wq);
253 is->state = IPPP_CLOSEWAIT;
254 return 1;
255}
256
257/*
258 * isdn_ppp_find_slot / isdn_ppp_free_slot
259 */
260
261static int
262isdn_ppp_get_slot(void)
263{
264 int i;
265 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
266 if (!ippp_table[i]->state)
267 return i;
268 }
269 return -1;
270}
271
272/*
273 * isdn_ppp_open
274 */
275
276int
277isdn_ppp_open(int min, struct file *file)
278{
279 int slot;
280 struct ippp_struct *is;
281
282 if (min < 0 || min > ISDN_MAX_CHANNELS)
283 return -ENODEV;
284
285 slot = isdn_ppp_get_slot();
286 if (slot < 0) {
287 return -EBUSY;
288 }
289 is = file->private_data = ippp_table[slot];
290
291 printk(KERN_DEBUG "ippp, open, slot: %d, minor: %d, state: %04x\n",
292 slot, min, is->state);
293
294 /* compression stuff */
295 is->link_compressor = is->compressor = NULL;
296 is->link_decompressor = is->decompressor = NULL;
297 is->link_comp_stat = is->comp_stat = NULL;
298 is->link_decomp_stat = is->decomp_stat = NULL;
299 is->compflags = 0;
300
301 is->reset = isdn_ppp_ccp_reset_alloc(is);
302
303 is->lp = NULL;
304 is->mp_seqno = 0; /* MP sequence number */
305 is->pppcfg = 0; /* ppp configuration */
306 is->mpppcfg = 0; /* mppp configuration */
307 is->last_link_seqno = -1; /* MP: maybe set to Bundle-MIN, when joining a bundle ?? */
308 is->unit = -1; /* set, when we have our interface */
309 is->mru = 1524; /* MRU, default 1524 */
310 is->maxcid = 16; /* VJ: maxcid */
311 is->tk = current;
312 init_waitqueue_head(&is->wq);
313 is->first = is->rq + NUM_RCV_BUFFS - 1; /* receive queue */
314 is->last = is->rq;
315 is->minor = min;
316#ifdef CONFIG_ISDN_PPP_VJ
317 /*
318 * VJ header compression init
319 */
320 is->slcomp = slhc_init(16, 16); /* not necessary for 2. link in bundle */
321#endif
322#ifdef CONFIG_IPPP_FILTER
323 is->pass_filter = NULL;
324 is->active_filter = NULL;
325#endif
326 is->state = IPPP_OPEN;
327
328 return 0;
329}
330
331/*
332 * release ippp device
333 */
334void
335isdn_ppp_release(int min, struct file *file)
336{
337 int i;
338 struct ippp_struct *is;
339
340 if (min < 0 || min >= ISDN_MAX_CHANNELS)
341 return;
342 is = file->private_data;
343
344 if (!is) {
345 printk(KERN_ERR "%s: no file->private_data\n", __FUNCTION__);
346 return;
347 }
348 if (is->debug & 0x1)
349 printk(KERN_DEBUG "ippp: release, minor: %d %lx\n", min, (long) is->lp);
350
351 if (is->lp) { /* a lp address says: this link is still up */
352 isdn_net_dev *p = is->lp->netdev;
353
354 if (!p) {
355 printk(KERN_ERR "%s: no lp->netdev\n", __FUNCTION__);
356 return;
357 }
358 is->state &= ~IPPP_CONNECT; /* -> effect: no call of wakeup */
359 /*
360 * isdn_net_hangup() calls isdn_ppp_free()
361 * isdn_ppp_free() sets is->lp to NULL and lp->ppp_slot to -1
362 * removing the IPPP_CONNECT flag omits calling of isdn_ppp_wakeup_daemon()
363 */
364 isdn_net_hangup(&p->dev);
365 }
366 for (i = 0; i < NUM_RCV_BUFFS; i++) {
367 if (is->rq[i].buf) {
368 kfree(is->rq[i].buf);
369 is->rq[i].buf = NULL;
370 }
371 }
372 is->first = is->rq + NUM_RCV_BUFFS - 1; /* receive queue */
373 is->last = is->rq;
374
375#ifdef CONFIG_ISDN_PPP_VJ
376/* TODO: if this was the previous master: link the slcomp to the new master */
377 slhc_free(is->slcomp);
378 is->slcomp = NULL;
379#endif
380#ifdef CONFIG_IPPP_FILTER
381 if (is->pass_filter) {
382 kfree(is->pass_filter);
383 is->pass_filter = NULL;
384 }
385 if (is->active_filter) {
386 kfree(is->active_filter);
387 is->active_filter = NULL;
388 }
389#endif
390
391/* TODO: if this was the previous master: link the stuff to the new master */
392 if(is->comp_stat)
393 is->compressor->free(is->comp_stat);
394 if(is->link_comp_stat)
395 is->link_compressor->free(is->link_comp_stat);
396 if(is->link_decomp_stat)
397 is->link_decompressor->free(is->link_decomp_stat);
398 if(is->decomp_stat)
399 is->decompressor->free(is->decomp_stat);
400 is->compressor = is->link_compressor = NULL;
401 is->decompressor = is->link_decompressor = NULL;
402 is->comp_stat = is->link_comp_stat = NULL;
403 is->decomp_stat = is->link_decomp_stat = NULL;
404
405 /* Clean up if necessary */
406 if(is->reset)
407 isdn_ppp_ccp_reset_free(is);
408
409 /* this slot is ready for new connections */
410 is->state = 0;
411}
412
413/*
414 * get_arg .. ioctl helper
415 */
416static int
417get_arg(void __user *b, void *val, int len)
418{
419 if (len <= 0)
420 len = sizeof(void *);
421 if (copy_from_user(val, b, len))
422 return -EFAULT;
423 return 0;
424}
425
426/*
427 * set arg .. ioctl helper
428 */
429static int
430set_arg(void __user *b, void *val,int len)
431{
432 if(len <= 0)
433 len = sizeof(void *);
434 if (copy_to_user(b, val, len))
435 return -EFAULT;
436 return 0;
437}
438
439static int get_filter(void __user *arg, struct sock_filter **p)
440{
441 struct sock_fprog uprog;
442 struct sock_filter *code = NULL;
443 int len, err;
444
445 if (copy_from_user(&uprog, arg, sizeof(uprog)))
446 return -EFAULT;
447
448 if (!uprog.len) {
449 *p = NULL;
450 return 0;
451 }
452
453 /* uprog.len is unsigned short, so no overflow here */
454 len = uprog.len * sizeof(struct sock_filter);
455 code = kmalloc(len, GFP_KERNEL);
456 if (code == NULL)
457 return -ENOMEM;
458
459 if (copy_from_user(code, uprog.filter, len)) {
460 kfree(code);
461 return -EFAULT;
462 }
463
464 err = sk_chk_filter(code, uprog.len);
465 if (err) {
466 kfree(code);
467 return err;
468 }
469
470 *p = code;
471 return uprog.len;
472}
473
474/*
475 * ippp device ioctl
476 */
477int
478isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg)
479{
480 unsigned long val;
481 int r,i,j;
482 struct ippp_struct *is;
483 isdn_net_local *lp;
484 struct isdn_ppp_comp_data data;
485 void __user *argp = (void __user *)arg;
486
487 is = (struct ippp_struct *) file->private_data;
488 lp = is->lp;
489
490 if (is->debug & 0x1)
491 printk(KERN_DEBUG "isdn_ppp_ioctl: minor: %d cmd: %x state: %x\n", min, cmd, is->state);
492
493 if (!(is->state & IPPP_OPEN))
494 return -EINVAL;
495
496 switch (cmd) {
497 case PPPIOCBUNDLE:
498#ifdef CONFIG_ISDN_MPP
499 if (!(is->state & IPPP_CONNECT))
500 return -EINVAL;
501 if ((r = get_arg(argp, &val, sizeof(val) )))
502 return r;
503 printk(KERN_DEBUG "iPPP-bundle: minor: %d, slave unit: %d, master unit: %d\n",
504 (int) min, (int) is->unit, (int) val);
505 return isdn_ppp_bundle(is, val);
506#else
507 return -1;
508#endif
509 break;
510 case PPPIOCGUNIT: /* get ppp/isdn unit number */
511 if ((r = set_arg(argp, &is->unit, sizeof(is->unit) )))
512 return r;
513 break;
514 case PPPIOCGIFNAME:
515 if(!lp)
516 return -EINVAL;
517 if ((r = set_arg(argp, lp->name, strlen(lp->name))))
518 return r;
519 break;
520 case PPPIOCGMPFLAGS: /* get configuration flags */
521 if ((r = set_arg(argp, &is->mpppcfg, sizeof(is->mpppcfg) )))
522 return r;
523 break;
524 case PPPIOCSMPFLAGS: /* set configuration flags */
525 if ((r = get_arg(argp, &val, sizeof(val) )))
526 return r;
527 is->mpppcfg = val;
528 break;
529 case PPPIOCGFLAGS: /* get configuration flags */
530 if ((r = set_arg(argp, &is->pppcfg,sizeof(is->pppcfg) )))
531 return r;
532 break;
533 case PPPIOCSFLAGS: /* set configuration flags */
534 if ((r = get_arg(argp, &val, sizeof(val) ))) {
535 return r;
536 }
537 if (val & SC_ENABLE_IP && !(is->pppcfg & SC_ENABLE_IP) && (is->state & IPPP_CONNECT)) {
538 if (lp) {
539 /* OK .. we are ready to send buffers */
540 is->pppcfg = val; /* isdn_ppp_xmit test for SC_ENABLE_IP !!! */
541 netif_wake_queue(&lp->netdev->dev);
542 break;
543 }
544 }
545 is->pppcfg = val;
546 break;
547 case PPPIOCGIDLE: /* get idle time information */
548 if (lp) {
549 struct ppp_idle pidle;
550 pidle.xmit_idle = pidle.recv_idle = lp->huptimer;
551 if ((r = set_arg(argp, &pidle,sizeof(struct ppp_idle))))
552 return r;
553 }
554 break;
555 case PPPIOCSMRU: /* set receive unit size for PPP */
556 if ((r = get_arg(argp, &val, sizeof(val) )))
557 return r;
558 is->mru = val;
559 break;
560 case PPPIOCSMPMRU:
561 break;
562 case PPPIOCSMPMTU:
563 break;
564 case PPPIOCSMAXCID: /* set the maximum compression slot id */
565 if ((r = get_arg(argp, &val, sizeof(val) )))
566 return r;
567 val++;
568 if (is->maxcid != val) {
569#ifdef CONFIG_ISDN_PPP_VJ
570 struct slcompress *sltmp;
571#endif
572 if (is->debug & 0x1)
573 printk(KERN_DEBUG "ippp, ioctl: changed MAXCID to %ld\n", val);
574 is->maxcid = val;
575#ifdef CONFIG_ISDN_PPP_VJ
576 sltmp = slhc_init(16, val);
577 if (!sltmp) {
578 printk(KERN_ERR "ippp, can't realloc slhc struct\n");
579 return -ENOMEM;
580 }
581 if (is->slcomp)
582 slhc_free(is->slcomp);
583 is->slcomp = sltmp;
584#endif
585 }
586 break;
587 case PPPIOCGDEBUG:
588 if ((r = set_arg(argp, &is->debug, sizeof(is->debug) )))
589 return r;
590 break;
591 case PPPIOCSDEBUG:
592 if ((r = get_arg(argp, &val, sizeof(val) )))
593 return r;
594 is->debug = val;
595 break;
596 case PPPIOCGCOMPRESSORS:
597 {
598 unsigned long protos[8] = {0,};
599 struct isdn_ppp_compressor *ipc = ipc_head;
600 while(ipc) {
601 j = ipc->num / (sizeof(long)*8);
602 i = ipc->num % (sizeof(long)*8);
603 if(j < 8)
604 protos[j] |= (0x1<<i);
605 ipc = ipc->next;
606 }
607 if ((r = set_arg(argp,protos,8*sizeof(long) )))
608 return r;
609 }
610 break;
611 case PPPIOCSCOMPRESSOR:
612 if ((r = get_arg(argp, &data, sizeof(struct isdn_ppp_comp_data))))
613 return r;
614 return isdn_ppp_set_compressor(is, &data);
615 case PPPIOCGCALLINFO:
616 {
617 struct pppcallinfo pci;
618 memset((char *) &pci,0,sizeof(struct pppcallinfo));
619 if(lp)
620 {
621 strncpy(pci.local_num,lp->msn,63);
622 if(lp->dial) {
623 strncpy(pci.remote_num,lp->dial->num,63);
624 }
625 pci.charge_units = lp->charge;
626 if(lp->outgoing)
627 pci.calltype = CALLTYPE_OUTGOING;
628 else
629 pci.calltype = CALLTYPE_INCOMING;
630 if(lp->flags & ISDN_NET_CALLBACK)
631 pci.calltype |= CALLTYPE_CALLBACK;
632 }
633 return set_arg(argp,&pci,sizeof(struct pppcallinfo));
634 }
635#ifdef CONFIG_IPPP_FILTER
636 case PPPIOCSPASS:
637 {
638 struct sock_filter *code;
639 int len = get_filter(argp, &code);
640 if (len < 0)
641 return len;
642 kfree(is->pass_filter);
643 is->pass_filter = code;
644 is->pass_len = len;
645 break;
646 }
647 case PPPIOCSACTIVE:
648 {
649 struct sock_filter *code;
650 int len = get_filter(argp, &code);
651 if (len < 0)
652 return len;
653 kfree(is->active_filter);
654 is->active_filter = code;
655 is->active_len = len;
656 break;
657 }
658#endif /* CONFIG_IPPP_FILTER */
659 default:
660 break;
661 }
662 return 0;
663}
664
665unsigned int
666isdn_ppp_poll(struct file *file, poll_table * wait)
667{
668 u_int mask;
669 struct ippp_buf_queue *bf, *bl;
670 u_long flags;
671 struct ippp_struct *is;
672
673 is = file->private_data;
674
675 if (is->debug & 0x2)
676 printk(KERN_DEBUG "isdn_ppp_poll: minor: %d\n",
677 MINOR(file->f_dentry->d_inode->i_rdev));
678
679 /* just registers wait_queue hook. This doesn't really wait. */
680 poll_wait(file, &is->wq, wait);
681
682 if (!(is->state & IPPP_OPEN)) {
683 if(is->state == IPPP_CLOSEWAIT)
684 return POLLHUP;
685 printk(KERN_DEBUG "isdn_ppp: device not open\n");
686 return POLLERR;
687 }
688 /* we're always ready to send .. */
689 mask = POLLOUT | POLLWRNORM;
690
691 spin_lock_irqsave(&is->buflock, flags);
692 bl = is->last;
693 bf = is->first;
694 /*
695 * if IPPP_NOBLOCK is set we return even if we have nothing to read
696 */
697 if (bf->next != bl || (is->state & IPPP_NOBLOCK)) {
698 is->state &= ~IPPP_NOBLOCK;
699 mask |= POLLIN | POLLRDNORM;
700 }
701 spin_unlock_irqrestore(&is->buflock, flags);
702 return mask;
703}
704
705/*
706 * fill up isdn_ppp_read() queue ..
707 */
708
709static int
710isdn_ppp_fill_rq(unsigned char *buf, int len, int proto, int slot)
711{
712 struct ippp_buf_queue *bf, *bl;
713 u_long flags;
714 u_char *nbuf;
715 struct ippp_struct *is;
716
717 if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
718 printk(KERN_WARNING "ippp: illegal slot(%d).\n", slot);
719 return 0;
720 }
721 is = ippp_table[slot];
722
723 if (!(is->state & IPPP_CONNECT)) {
724 printk(KERN_DEBUG "ippp: device not activated.\n");
725 return 0;
726 }
727 nbuf = (unsigned char *) kmalloc(len + 4, GFP_ATOMIC);
728 if (!nbuf) {
729 printk(KERN_WARNING "ippp: Can't alloc buf\n");
730 return 0;
731 }
732 nbuf[0] = PPP_ALLSTATIONS;
733 nbuf[1] = PPP_UI;
734 nbuf[2] = proto >> 8;
735 nbuf[3] = proto & 0xff;
736 memcpy(nbuf + 4, buf, len);
737
738 spin_lock_irqsave(&is->buflock, flags);
739 bf = is->first;
740 bl = is->last;
741
742 if (bf == bl) {
743 printk(KERN_WARNING "ippp: Queue is full; discarding first buffer\n");
744 bf = bf->next;
745 kfree(bf->buf);
746 is->first = bf;
747 }
748 bl->buf = (char *) nbuf;
749 bl->len = len + 4;
750
751 is->last = bl->next;
752 spin_unlock_irqrestore(&is->buflock, flags);
753 wake_up_interruptible(&is->wq);
754 return len;
755}
756
757/*
758 * read() .. non-blocking: ipppd calls it only after select()
759 * reports, that there is data
760 */
761
762int
763isdn_ppp_read(int min, struct file *file, char __user *buf, int count)
764{
765 struct ippp_struct *is;
766 struct ippp_buf_queue *b;
767 u_long flags;
768 u_char *save_buf;
769
770 is = file->private_data;
771
772 if (!(is->state & IPPP_OPEN))
773 return 0;
774
775 if (!access_ok(VERIFY_WRITE, buf, count))
776 return -EFAULT;
777
778 spin_lock_irqsave(&is->buflock, flags);
779 b = is->first->next;
780 save_buf = b->buf;
781 if (!save_buf) {
782 spin_unlock_irqrestore(&is->buflock, flags);
783 return -EAGAIN;
784 }
785 if (b->len < count)
786 count = b->len;
787 b->buf = NULL;
788 is->first = b;
789
790 spin_unlock_irqrestore(&is->buflock, flags);
791 copy_to_user(buf, save_buf, count);
792 kfree(save_buf);
793
794 return count;
795}
796
797/*
798 * ipppd wanna write a packet to the card .. non-blocking
799 */
800
801int
802isdn_ppp_write(int min, struct file *file, const char __user *buf, int count)
803{
804 isdn_net_local *lp;
805 struct ippp_struct *is;
806 int proto;
807 unsigned char protobuf[4];
808
809 is = file->private_data;
810
811 if (!(is->state & IPPP_CONNECT))
812 return 0;
813
814 lp = is->lp;
815
816 /* -> push it directly to the lowlevel interface */
817
818 if (!lp)
819 printk(KERN_DEBUG "isdn_ppp_write: lp == NULL\n");
820 else {
821 /*
822 * Don't reset huptimer for
823 * LCP packets. (Echo requests).
824 */
825 if (copy_from_user(protobuf, buf, 4))
826 return -EFAULT;
827 proto = PPP_PROTOCOL(protobuf);
828 if (proto != PPP_LCP)
829 lp->huptimer = 0;
830
831 if (lp->isdn_device < 0 || lp->isdn_channel < 0)
832 return 0;
833
834 if ((dev->drv[lp->isdn_device]->flags & DRV_FLAG_RUNNING) &&
835 lp->dialstate == 0 &&
836 (lp->flags & ISDN_NET_CONNECTED)) {
837 unsigned short hl;
838 struct sk_buff *skb;
839 /*
840 * we need to reserve enought space in front of
841 * sk_buff. old call to dev_alloc_skb only reserved
842 * 16 bytes, now we are looking what the driver want
843 */
844 hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen;
845 skb = alloc_skb(hl+count, GFP_ATOMIC);
846 if (!skb) {
847 printk(KERN_WARNING "isdn_ppp_write: out of memory!\n");
848 return count;
849 }
850 skb_reserve(skb, hl);
851 if (copy_from_user(skb_put(skb, count), buf, count))
852 {
853 kfree_skb(skb);
854 return -EFAULT;
855 }
856 if (is->debug & 0x40) {
857 printk(KERN_DEBUG "ppp xmit: len %d\n", (int) skb->len);
858 isdn_ppp_frame_log("xmit", skb->data, skb->len, 32,is->unit,lp->ppp_slot);
859 }
860
861 isdn_ppp_send_ccp(lp->netdev,lp,skb); /* keeps CCP/compression states in sync */
862
863 isdn_net_write_super(lp, skb);
864 }
865 }
866 return count;
867}
868
869/*
870 * init memory, structures etc.
871 */
872
873int
874isdn_ppp_init(void)
875{
876 int i,
877 j;
878
879#ifdef CONFIG_ISDN_MPP
880 if( isdn_ppp_mp_bundle_array_init() < 0 )
881 return -ENOMEM;
882#endif /* CONFIG_ISDN_MPP */
883
884 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
885 if (!(ippp_table[i] = (struct ippp_struct *)
886 kmalloc(sizeof(struct ippp_struct), GFP_KERNEL))) {
887 printk(KERN_WARNING "isdn_ppp_init: Could not alloc ippp_table\n");
888 for (j = 0; j < i; j++)
889 kfree(ippp_table[j]);
890 return -1;
891 }
892 memset((char *) ippp_table[i], 0, sizeof(struct ippp_struct));
893 spin_lock_init(&ippp_table[i]->buflock);
894 ippp_table[i]->state = 0;
895 ippp_table[i]->first = ippp_table[i]->rq + NUM_RCV_BUFFS - 1;
896 ippp_table[i]->last = ippp_table[i]->rq;
897
898 for (j = 0; j < NUM_RCV_BUFFS; j++) {
899 ippp_table[i]->rq[j].buf = NULL;
900 ippp_table[i]->rq[j].last = ippp_table[i]->rq +
901 (NUM_RCV_BUFFS + j - 1) % NUM_RCV_BUFFS;
902 ippp_table[i]->rq[j].next = ippp_table[i]->rq + (j + 1) % NUM_RCV_BUFFS;
903 }
904 }
905 return 0;
906}
907
908void
909isdn_ppp_cleanup(void)
910{
911 int i;
912
913 for (i = 0; i < ISDN_MAX_CHANNELS; i++)
914 kfree(ippp_table[i]);
915
916#ifdef CONFIG_ISDN_MPP
917 if (isdn_ppp_bundle_arr)
918 kfree(isdn_ppp_bundle_arr);
919#endif /* CONFIG_ISDN_MPP */
920
921}
922
923/*
924 * check for address/control field and skip if allowed
925 * retval != 0 -> discard packet silently
926 */
927static int isdn_ppp_skip_ac(struct ippp_struct *is, struct sk_buff *skb)
928{
929 if (skb->len < 1)
930 return -1;
931
932 if (skb->data[0] == 0xff) {
933 if (skb->len < 2)
934 return -1;
935
936 if (skb->data[1] != 0x03)
937 return -1;
938
939 // skip address/control (AC) field
940 skb_pull(skb, 2);
941 } else {
942 if (is->pppcfg & SC_REJ_COMP_AC)
943 // if AC compression was not negotiated, but used, discard packet
944 return -1;
945 }
946 return 0;
947}
948
949/*
950 * get the PPP protocol header and pull skb
951 * retval < 0 -> discard packet silently
952 */
953static int isdn_ppp_strip_proto(struct sk_buff *skb)
954{
955 int proto;
956
957 if (skb->len < 1)
958 return -1;
959
960 if (skb->data[0] & 0x1) {
961 // protocol field is compressed
962 proto = skb->data[0];
963 skb_pull(skb, 1);
964 } else {
965 if (skb->len < 2)
966 return -1;
967 proto = ((int) skb->data[0] << 8) + skb->data[1];
968 skb_pull(skb, 2);
969 }
970 return proto;
971}
972
973
974/*
975 * handler for incoming packets on a syncPPP interface
976 */
977void isdn_ppp_receive(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff *skb)
978{
979 struct ippp_struct *is;
980 int slot;
981 int proto;
982
983 if (net_dev->local->master)
984 BUG(); // we're called with the master device always
985
986 slot = lp->ppp_slot;
987 if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
988 printk(KERN_ERR "isdn_ppp_receive: lp->ppp_slot(%d)\n",
989 lp->ppp_slot);
990 kfree_skb(skb);
991 return;
992 }
993 is = ippp_table[slot];
994
995 if (is->debug & 0x4) {
996 printk(KERN_DEBUG "ippp_receive: is:%08lx lp:%08lx slot:%d unit:%d len:%d\n",
997 (long)is,(long)lp,lp->ppp_slot,is->unit,(int) skb->len);
998 isdn_ppp_frame_log("receive", skb->data, skb->len, 32,is->unit,lp->ppp_slot);
999 }
1000
1001 if (isdn_ppp_skip_ac(is, skb) < 0) {
1002 kfree_skb(skb);
1003 return;
1004 }
1005 proto = isdn_ppp_strip_proto(skb);
1006 if (proto < 0) {
1007 kfree_skb(skb);
1008 return;
1009 }
1010
1011#ifdef CONFIG_ISDN_MPP
1012 if (is->compflags & SC_LINK_DECOMP_ON) {
1013 skb = isdn_ppp_decompress(skb, is, NULL, &proto);
1014 if (!skb) // decompression error
1015 return;
1016 }
1017
1018 if (!(is->mpppcfg & SC_REJ_MP_PROT)) { // we agreed to receive MPPP
1019 if (proto == PPP_MP) {
1020 isdn_ppp_mp_receive(net_dev, lp, skb);
1021 return;
1022 }
1023 }
1024#endif
1025 isdn_ppp_push_higher(net_dev, lp, skb, proto);
1026}
1027
1028/*
1029 * we receive a reassembled frame, MPPP has been taken care of before.
1030 * address/control and protocol have been stripped from the skb
1031 * note: net_dev has to be master net_dev
1032 */
1033static void
1034isdn_ppp_push_higher(isdn_net_dev * net_dev, isdn_net_local * lp, struct sk_buff *skb, int proto)
1035{
1036 struct net_device *dev = &net_dev->dev;
1037 struct ippp_struct *is, *mis;
1038 isdn_net_local *mlp = NULL;
1039 int slot;
1040
1041 slot = lp->ppp_slot;
1042 if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
1043 printk(KERN_ERR "isdn_ppp_push_higher: lp->ppp_slot(%d)\n",
1044 lp->ppp_slot);
1045 goto drop_packet;
1046 }
1047 is = ippp_table[slot];
1048
1049 if (lp->master) { // FIXME?
1050 mlp = (isdn_net_local *) lp->master->priv;
1051 slot = mlp->ppp_slot;
1052 if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
1053 printk(KERN_ERR "isdn_ppp_push_higher: master->ppp_slot(%d)\n",
1054 lp->ppp_slot);
1055 goto drop_packet;
1056 }
1057 }
1058 mis = ippp_table[slot];
1059
1060 if (is->debug & 0x10) {
1061 printk(KERN_DEBUG "push, skb %d %04x\n", (int) skb->len, proto);
1062 isdn_ppp_frame_log("rpush", skb->data, skb->len, 32,is->unit,lp->ppp_slot);
1063 }
1064 if (mis->compflags & SC_DECOMP_ON) {
1065 skb = isdn_ppp_decompress(skb, is, mis, &proto);
1066 if (!skb) // decompression error
1067 return;
1068 }
1069 switch (proto) {
1070 case PPP_IPX: /* untested */
1071 if (is->debug & 0x20)
1072 printk(KERN_DEBUG "isdn_ppp: IPX\n");
1073 skb->protocol = htons(ETH_P_IPX);
1074 break;
1075 case PPP_IP:
1076 if (is->debug & 0x20)
1077 printk(KERN_DEBUG "isdn_ppp: IP\n");
1078 skb->protocol = htons(ETH_P_IP);
1079 break;
1080 case PPP_COMP:
1081 case PPP_COMPFRAG:
1082 printk(KERN_INFO "isdn_ppp: unexpected compressed frame dropped\n");
1083 goto drop_packet;
1084#ifdef CONFIG_ISDN_PPP_VJ
1085 case PPP_VJC_UNCOMP:
1086 if (is->debug & 0x20)
1087 printk(KERN_DEBUG "isdn_ppp: VJC_UNCOMP\n");
1088 if (net_dev->local->ppp_slot < 0) {
1089 printk(KERN_ERR "%s: net_dev->local->ppp_slot(%d) out of range\n",
1090 __FUNCTION__, net_dev->local->ppp_slot);
1091 goto drop_packet;
1092 }
1093 if (slhc_remember(ippp_table[net_dev->local->ppp_slot]->slcomp, skb->data, skb->len) <= 0) {
1094 printk(KERN_WARNING "isdn_ppp: received illegal VJC_UNCOMP frame!\n");
1095 goto drop_packet;
1096 }
1097 skb->protocol = htons(ETH_P_IP);
1098 break;
1099 case PPP_VJC_COMP:
1100 if (is->debug & 0x20)
1101 printk(KERN_DEBUG "isdn_ppp: VJC_COMP\n");
1102 {
1103 struct sk_buff *skb_old = skb;
1104 int pkt_len;
1105 skb = dev_alloc_skb(skb_old->len + 128);
1106
1107 if (!skb) {
1108 printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n", dev->name);
1109 skb = skb_old;
1110 goto drop_packet;
1111 }
1112 skb_put(skb, skb_old->len + 128);
1113 memcpy(skb->data, skb_old->data, skb_old->len);
1114 if (net_dev->local->ppp_slot < 0) {
1115 printk(KERN_ERR "%s: net_dev->local->ppp_slot(%d) out of range\n",
1116 __FUNCTION__, net_dev->local->ppp_slot);
1117 goto drop_packet;
1118 }
1119 pkt_len = slhc_uncompress(ippp_table[net_dev->local->ppp_slot]->slcomp,
1120 skb->data, skb_old->len);
1121 kfree_skb(skb_old);
1122 if (pkt_len < 0)
1123 goto drop_packet;
1124
1125 skb_trim(skb, pkt_len);
1126 skb->protocol = htons(ETH_P_IP);
1127 }
1128 break;
1129#endif
1130 case PPP_CCP:
1131 case PPP_CCPFRAG:
1132 isdn_ppp_receive_ccp(net_dev,lp,skb,proto);
1133 /* Dont pop up ResetReq/Ack stuff to the daemon any
1134 longer - the job is done already */
1135 if(skb->data[0] == CCP_RESETREQ ||
1136 skb->data[0] == CCP_RESETACK)
1137 break;
1138 /* fall through */
1139 default:
1140 isdn_ppp_fill_rq(skb->data, skb->len, proto, lp->ppp_slot); /* push data to pppd device */
1141 kfree_skb(skb);
1142 return;
1143 }
1144
1145#ifdef CONFIG_IPPP_FILTER
1146 /* check if the packet passes the pass and active filters
1147 * the filter instructions are constructed assuming
1148 * a four-byte PPP header on each packet (which is still present) */
1149 skb_push(skb, 4);
1150
1151 {
1152 u_int16_t *p = (u_int16_t *) skb->data;
1153
1154 *p = 0; /* indicate inbound in DLT_LINUX_SLL */
1155 }
1156
1157 if (is->pass_filter
1158 && sk_run_filter(skb, is->pass_filter, is->pass_len) == 0) {
1159 if (is->debug & 0x2)
1160 printk(KERN_DEBUG "IPPP: inbound frame filtered.\n");
1161 kfree_skb(skb);
1162 return;
1163 }
1164 if (!(is->active_filter
1165 && sk_run_filter(skb, is->active_filter,
1166 is->active_len) == 0)) {
1167 if (is->debug & 0x2)
1168 printk(KERN_DEBUG "IPPP: link-active filter: reseting huptimer.\n");
1169 lp->huptimer = 0;
1170 if (mlp)
1171 mlp->huptimer = 0;
1172 }
1173 skb_pull(skb, 4);
1174#else /* CONFIG_IPPP_FILTER */
1175 lp->huptimer = 0;
1176 if (mlp)
1177 mlp->huptimer = 0;
1178#endif /* CONFIG_IPPP_FILTER */
1179 skb->dev = dev;
1180 skb->input_dev = dev;
1181 skb->mac.raw = skb->data;
1182 netif_rx(skb);
1183 /* net_dev->local->stats.rx_packets++; done in isdn_net.c */
1184 return;
1185
1186 drop_packet:
1187 net_dev->local->stats.rx_dropped++;
1188 kfree_skb(skb);
1189}
1190
1191/*
1192 * isdn_ppp_skb_push ..
1193 * checks whether we have enough space at the beginning of the skb
1194 * and allocs a new SKB if necessary
1195 */
1196static unsigned char *isdn_ppp_skb_push(struct sk_buff **skb_p,int len)
1197{
1198 struct sk_buff *skb = *skb_p;
1199
1200 if(skb_headroom(skb) < len) {
1201 struct sk_buff *nskb = skb_realloc_headroom(skb, len);
1202
1203 if (!nskb) {
1204 printk(KERN_ERR "isdn_ppp_skb_push: can't realloc headroom!\n");
1205 dev_kfree_skb(skb);
1206 return NULL;
1207 }
1208 printk(KERN_DEBUG "isdn_ppp_skb_push:under %d %d\n",skb_headroom(skb),len);
1209 dev_kfree_skb(skb);
1210 *skb_p = nskb;
1211 return skb_push(nskb, len);
1212 }
1213 return skb_push(skb,len);
1214}
1215
1216/*
1217 * send ppp frame .. we expect a PIDCOMPressable proto --
1218 * (here: currently always PPP_IP,PPP_VJC_COMP,PPP_VJC_UNCOMP)
1219 *
1220 * VJ compression may change skb pointer!!! .. requeue with old
1221 * skb isn't allowed!!
1222 */
1223
1224int
1225isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev)
1226{
1227 isdn_net_local *lp,*mlp;
1228 isdn_net_dev *nd;
1229 unsigned int proto = PPP_IP; /* 0x21 */
1230 struct ippp_struct *ipt,*ipts;
1231 int slot, retval = 0;
1232
1233 mlp = (isdn_net_local *) (netdev->priv);
1234 nd = mlp->netdev; /* get master lp */
1235
1236 slot = mlp->ppp_slot;
1237 if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
1238 printk(KERN_ERR "isdn_ppp_xmit: lp->ppp_slot(%d)\n",
1239 mlp->ppp_slot);
1240 kfree_skb(skb);
1241 goto out;
1242 }
1243 ipts = ippp_table[slot];
1244
1245 if (!(ipts->pppcfg & SC_ENABLE_IP)) { /* PPP connected ? */
1246 if (ipts->debug & 0x1)
1247 printk(KERN_INFO "%s: IP frame delayed.\n", netdev->name);
1248 retval = 1;
1249 goto out;
1250 }
1251
1252 switch (ntohs(skb->protocol)) {
1253 case ETH_P_IP:
1254 proto = PPP_IP;
1255 break;
1256 case ETH_P_IPX:
1257 proto = PPP_IPX; /* untested */
1258 break;
1259 default:
1260 printk(KERN_ERR "isdn_ppp: skipped unsupported protocol: %#x.\n",
1261 skb->protocol);
1262 dev_kfree_skb(skb);
1263 goto out;
1264 }
1265
1266 lp = isdn_net_get_locked_lp(nd);
1267 if (!lp) {
1268 printk(KERN_WARNING "%s: all channels busy - requeuing!\n", netdev->name);
1269 retval = 1;
1270 goto out;
1271 }
1272 /* we have our lp locked from now on */
1273
1274 slot = lp->ppp_slot;
1275 if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
1276 printk(KERN_ERR "isdn_ppp_xmit: lp->ppp_slot(%d)\n",
1277 lp->ppp_slot);
1278 kfree_skb(skb);
1279 goto unlock;
1280 }
1281 ipt = ippp_table[slot];
1282
1283 /*
1284 * after this line .. requeueing in the device queue is no longer allowed!!!
1285 */
1286
1287 /* Pull off the fake header we stuck on earlier to keep
1288 * the fragmentation code happy.
1289 */
1290 skb_pull(skb,IPPP_MAX_HEADER);
1291
1292#ifdef CONFIG_IPPP_FILTER
1293 /* check if we should pass this packet
1294 * the filter instructions are constructed assuming
1295 * a four-byte PPP header on each packet */
1296 skb_push(skb, 4);
1297
1298 {
1299 u_int16_t *p = (u_int16_t *) skb->data;
1300
1301 *p++ = htons(4); /* indicate outbound in DLT_LINUX_SLL */
1302 *p = htons(proto);
1303 }
1304
1305 if (ipt->pass_filter
1306 && sk_run_filter(skb, ipt->pass_filter, ipt->pass_len) == 0) {
1307 if (ipt->debug & 0x4)
1308 printk(KERN_DEBUG "IPPP: outbound frame filtered.\n");
1309 kfree_skb(skb);
1310 goto unlock;
1311 }
1312 if (!(ipt->active_filter
1313 && sk_run_filter(skb, ipt->active_filter,
1314 ipt->active_len) == 0)) {
1315 if (ipt->debug & 0x4)
1316 printk(KERN_DEBUG "IPPP: link-active filter: reseting huptimer.\n");
1317 lp->huptimer = 0;
1318 }
1319 skb_pull(skb, 4);
1320#else /* CONFIG_IPPP_FILTER */
1321 lp->huptimer = 0;
1322#endif /* CONFIG_IPPP_FILTER */
1323
1324 if (ipt->debug & 0x4)
1325 printk(KERN_DEBUG "xmit skb, len %d\n", (int) skb->len);
1326 if (ipts->debug & 0x40)
1327 isdn_ppp_frame_log("xmit0", skb->data, skb->len, 32,ipts->unit,lp->ppp_slot);
1328
1329#ifdef CONFIG_ISDN_PPP_VJ
1330 if (proto == PPP_IP && ipts->pppcfg & SC_COMP_TCP) { /* ipts here? probably yes, but check this again */
1331 struct sk_buff *new_skb;
1332 unsigned short hl;
1333 /*
1334 * we need to reserve enought space in front of
1335 * sk_buff. old call to dev_alloc_skb only reserved
1336 * 16 bytes, now we are looking what the driver want.
1337 */
1338 hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen + IPPP_MAX_HEADER;
1339 /*
1340 * Note: hl might still be insufficient because the method
1341 * above does not account for a possibible MPPP slave channel
1342 * which had larger HL header space requirements than the
1343 * master.
1344 */
1345 new_skb = alloc_skb(hl+skb->len, GFP_ATOMIC);
1346 if (new_skb) {
1347 u_char *buf;
1348 int pktlen;
1349
1350 skb_reserve(new_skb, hl);
1351 new_skb->dev = skb->dev;
1352 skb_put(new_skb, skb->len);
1353 buf = skb->data;
1354
1355 pktlen = slhc_compress(ipts->slcomp, skb->data, skb->len, new_skb->data,
1356 &buf, !(ipts->pppcfg & SC_NO_TCP_CCID));
1357
1358 if (buf != skb->data) {
1359 if (new_skb->data != buf)
1360 printk(KERN_ERR "isdn_ppp: FATAL error after slhc_compress!!\n");
1361 dev_kfree_skb(skb);
1362 skb = new_skb;
1363 } else {
1364 dev_kfree_skb(new_skb);
1365 }
1366
1367 skb_trim(skb, pktlen);
1368 if (skb->data[0] & SL_TYPE_COMPRESSED_TCP) { /* cslip? style -> PPP */
1369 proto = PPP_VJC_COMP;
1370 skb->data[0] ^= SL_TYPE_COMPRESSED_TCP;
1371 } else {
1372 if (skb->data[0] >= SL_TYPE_UNCOMPRESSED_TCP)
1373 proto = PPP_VJC_UNCOMP;
1374 skb->data[0] = (skb->data[0] & 0x0f) | 0x40;
1375 }
1376 }
1377 }
1378#endif
1379
1380 /*
1381 * normal (single link) or bundle compression
1382 */
1383 if(ipts->compflags & SC_COMP_ON) {
1384 /* We send compressed only if both down- und upstream
1385 compression is negotiated, that means, CCP is up */
1386 if(ipts->compflags & SC_DECOMP_ON) {
1387 skb = isdn_ppp_compress(skb,&proto,ipt,ipts,0);
1388 } else {
1389 printk(KERN_DEBUG "isdn_ppp: CCP not yet up - sending as-is\n");
1390 }
1391 }
1392
1393 if (ipt->debug & 0x24)
1394 printk(KERN_DEBUG "xmit2 skb, len %d, proto %04x\n", (int) skb->len, proto);
1395
1396#ifdef CONFIG_ISDN_MPP
1397 if (ipt->mpppcfg & SC_MP_PROT) {
1398 /* we get mp_seqno from static isdn_net_local */
1399 long mp_seqno = ipts->mp_seqno;
1400 ipts->mp_seqno++;
1401 if (ipt->mpppcfg & SC_OUT_SHORT_SEQ) {
1402 unsigned char *data = isdn_ppp_skb_push(&skb, 3);
1403 if(!data)
1404 goto unlock;
1405 mp_seqno &= 0xfff;
1406 data[0] = MP_BEGIN_FRAG | MP_END_FRAG | ((mp_seqno >> 8) & 0xf); /* (B)egin & (E)ndbit .. */
1407 data[1] = mp_seqno & 0xff;
1408 data[2] = proto; /* PID compression */
1409 } else {
1410 unsigned char *data = isdn_ppp_skb_push(&skb, 5);
1411 if(!data)
1412 goto unlock;
1413 data[0] = MP_BEGIN_FRAG | MP_END_FRAG; /* (B)egin & (E)ndbit .. */
1414 data[1] = (mp_seqno >> 16) & 0xff; /* sequence number: 24bit */
1415 data[2] = (mp_seqno >> 8) & 0xff;
1416 data[3] = (mp_seqno >> 0) & 0xff;
1417 data[4] = proto; /* PID compression */
1418 }
1419 proto = PPP_MP; /* MP Protocol, 0x003d */
1420 }
1421#endif
1422
1423 /*
1424 * 'link in bundle' compression ...
1425 */
1426 if(ipt->compflags & SC_LINK_COMP_ON)
1427 skb = isdn_ppp_compress(skb,&proto,ipt,ipts,1);
1428
1429 if( (ipt->pppcfg & SC_COMP_PROT) && (proto <= 0xff) ) {
1430 unsigned char *data = isdn_ppp_skb_push(&skb,1);
1431 if(!data)
1432 goto unlock;
1433 data[0] = proto & 0xff;
1434 }
1435 else {
1436 unsigned char *data = isdn_ppp_skb_push(&skb,2);
1437 if(!data)
1438 goto unlock;
1439 data[0] = (proto >> 8) & 0xff;
1440 data[1] = proto & 0xff;
1441 }
1442 if(!(ipt->pppcfg & SC_COMP_AC)) {
1443 unsigned char *data = isdn_ppp_skb_push(&skb,2);
1444 if(!data)
1445 goto unlock;
1446 data[0] = 0xff; /* All Stations */
1447 data[1] = 0x03; /* Unnumbered information */
1448 }
1449
1450 /* tx-stats are now updated via BSENT-callback */
1451
1452 if (ipts->debug & 0x40) {
1453 printk(KERN_DEBUG "skb xmit: len: %d\n", (int) skb->len);
1454 isdn_ppp_frame_log("xmit", skb->data, skb->len, 32,ipt->unit,lp->ppp_slot);
1455 }
1456
1457 isdn_net_writebuf_skb(lp, skb);
1458
1459 unlock:
1460 spin_unlock_bh(&lp->xmit_lock);
1461 out:
1462 return retval;
1463}
1464
1465#ifdef CONFIG_IPPP_FILTER
1466/*
1467 * check if this packet may trigger auto-dial.
1468 */
1469
1470int isdn_ppp_autodial_filter(struct sk_buff *skb, isdn_net_local *lp)
1471{
1472 struct ippp_struct *is = ippp_table[lp->ppp_slot];
1473 u_int16_t proto;
1474 int drop = 0;
1475
1476 switch (ntohs(skb->protocol)) {
1477 case ETH_P_IP:
1478 proto = PPP_IP;
1479 break;
1480 case ETH_P_IPX:
1481 proto = PPP_IPX;
1482 break;
1483 default:
1484 printk(KERN_ERR "isdn_ppp_autodial_filter: unsupported protocol 0x%x.\n",
1485 skb->protocol);
1486 return 1;
1487 }
1488
1489 /* the filter instructions are constructed assuming
1490 * a four-byte PPP header on each packet. we have to
1491 * temporarily remove part of the fake header stuck on
1492 * earlier.
1493 */
1494 skb_pull(skb, IPPP_MAX_HEADER - 4);
1495
1496 {
1497 u_int16_t *p = (u_int16_t *) skb->data;
1498
1499 *p++ = htons(4); /* indicate outbound in DLT_LINUX_SLL */
1500 *p = htons(proto);
1501 }
1502
1503 drop |= is->pass_filter
1504 && sk_run_filter(skb, is->pass_filter, is->pass_len) == 0;
1505 drop |= is->active_filter
1506 && sk_run_filter(skb, is->active_filter, is->active_len) == 0;
1507
1508 skb_push(skb, IPPP_MAX_HEADER - 4);
1509 return drop;
1510}
1511#endif
1512#ifdef CONFIG_ISDN_MPP
1513
1514/* this is _not_ rfc1990 header, but something we convert both short and long
1515 * headers to for convinience's sake:
1516 * byte 0 is flags as in rfc1990
1517 * bytes 1...4 is 24-bit seqence number converted to host byte order
1518 */
1519#define MP_HEADER_LEN 5
1520
1521#define MP_LONGSEQ_MASK 0x00ffffff
1522#define MP_SHORTSEQ_MASK 0x00000fff
1523#define MP_LONGSEQ_MAX MP_LONGSEQ_MASK
1524#define MP_SHORTSEQ_MAX MP_SHORTSEQ_MASK
1525#define MP_LONGSEQ_MAXBIT ((MP_LONGSEQ_MASK+1)>>1)
1526#define MP_SHORTSEQ_MAXBIT ((MP_SHORTSEQ_MASK+1)>>1)
1527
1528/* sequence-wrap safe comparisions (for long sequence)*/
1529#define MP_LT(a,b) ((a-b)&MP_LONGSEQ_MAXBIT)
1530#define MP_LE(a,b) !((b-a)&MP_LONGSEQ_MAXBIT)
1531#define MP_GT(a,b) ((b-a)&MP_LONGSEQ_MAXBIT)
1532#define MP_GE(a,b) !((a-b)&MP_LONGSEQ_MAXBIT)
1533
1534#define MP_SEQ(f) ((*(u32*)(f->data+1)))
1535#define MP_FLAGS(f) (f->data[0])
1536
1537static int isdn_ppp_mp_bundle_array_init(void)
1538{
1539 int i;
1540 int sz = ISDN_MAX_CHANNELS*sizeof(ippp_bundle);
1541 if( (isdn_ppp_bundle_arr = (ippp_bundle*)kmalloc(sz,
1542 GFP_KERNEL)) == NULL )
1543 return -ENOMEM;
1544 memset(isdn_ppp_bundle_arr, 0, sz);
1545 for( i = 0; i < ISDN_MAX_CHANNELS; i++ )
1546 spin_lock_init(&isdn_ppp_bundle_arr[i].lock);
1547 return 0;
1548}
1549
1550static ippp_bundle * isdn_ppp_mp_bundle_alloc(void)
1551{
1552 int i;
1553 for( i = 0; i < ISDN_MAX_CHANNELS; i++ )
1554 if (isdn_ppp_bundle_arr[i].ref_ct <= 0)
1555 return (isdn_ppp_bundle_arr + i);
1556 return NULL;
1557}
1558
1559static int isdn_ppp_mp_init( isdn_net_local * lp, ippp_bundle * add_to )
1560{
1561 struct ippp_struct * is;
1562
1563 if (lp->ppp_slot < 0) {
1564 printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
1565 __FUNCTION__, lp->ppp_slot);
1566 return(-EINVAL);
1567 }
1568
1569 is = ippp_table[lp->ppp_slot];
1570 if (add_to) {
1571 if( lp->netdev->pb )
1572 lp->netdev->pb->ref_ct--;
1573 lp->netdev->pb = add_to;
1574 } else { /* first link in a bundle */
1575 is->mp_seqno = 0;
1576 if ((lp->netdev->pb = isdn_ppp_mp_bundle_alloc()) == NULL)
1577 return -ENOMEM;
1578 lp->next = lp->last = lp; /* nobody else in a queue */
1579 lp->netdev->pb->frags = NULL;
1580 lp->netdev->pb->frames = 0;
1581 lp->netdev->pb->seq = UINT_MAX;
1582 }
1583 lp->netdev->pb->ref_ct++;
1584
1585 is->last_link_seqno = 0;
1586 return 0;
1587}
1588
1589static u32 isdn_ppp_mp_get_seq( int short_seq,
1590 struct sk_buff * skb, u32 last_seq );
1591static struct sk_buff * isdn_ppp_mp_discard( ippp_bundle * mp,
1592 struct sk_buff * from, struct sk_buff * to );
1593static void isdn_ppp_mp_reassembly( isdn_net_dev * net_dev, isdn_net_local * lp,
1594 struct sk_buff * from, struct sk_buff * to );
1595static void isdn_ppp_mp_free_skb( ippp_bundle * mp, struct sk_buff * skb );
1596static void isdn_ppp_mp_print_recv_pkt( int slot, struct sk_buff * skb );
1597
1598static void isdn_ppp_mp_receive(isdn_net_dev * net_dev, isdn_net_local * lp,
1599 struct sk_buff *skb)
1600{
1601 struct ippp_struct *is;
1602 isdn_net_local * lpq;
1603 ippp_bundle * mp;
1604 isdn_mppp_stats * stats;
1605 struct sk_buff * newfrag, * frag, * start, *nextf;
1606 u32 newseq, minseq, thisseq;
1607 unsigned long flags;
1608 int slot;
1609
1610 spin_lock_irqsave(&net_dev->pb->lock, flags);
1611 mp = net_dev->pb;
1612 stats = &mp->stats;
1613 slot = lp->ppp_slot;
1614 if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
1615 printk(KERN_ERR "%s: lp->ppp_slot(%d)\n",
1616 __FUNCTION__, lp->ppp_slot);
1617 stats->frame_drops++;
1618 dev_kfree_skb(skb);
1619 spin_unlock_irqrestore(&mp->lock, flags);
1620 return;
1621 }
1622 is = ippp_table[slot];
1623 if( ++mp->frames > stats->max_queue_len )
1624 stats->max_queue_len = mp->frames;
1625
1626 if (is->debug & 0x8)
1627 isdn_ppp_mp_print_recv_pkt(lp->ppp_slot, skb);
1628
1629 newseq = isdn_ppp_mp_get_seq(is->mpppcfg & SC_IN_SHORT_SEQ,
1630 skb, is->last_link_seqno);
1631
1632
1633 /* if this packet seq # is less than last already processed one,
1634 * toss it right away, but check for sequence start case first
1635 */
1636 if( mp->seq > MP_LONGSEQ_MAX && (newseq & MP_LONGSEQ_MAXBIT) ) {
1637 mp->seq = newseq; /* the first packet: required for
1638 * rfc1990 non-compliant clients --
1639 * prevents constant packet toss */
1640 } else if( MP_LT(newseq, mp->seq) ) {
1641 stats->frame_drops++;
1642 isdn_ppp_mp_free_skb(mp, skb);
1643 spin_unlock_irqrestore(&mp->lock, flags);
1644 return;
1645 }
1646
1647 /* find the minimum received sequence number over all links */
1648 is->last_link_seqno = minseq = newseq;
1649 for (lpq = net_dev->queue;;) {
1650 slot = lpq->ppp_slot;
1651 if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
1652 printk(KERN_ERR "%s: lpq->ppp_slot(%d)\n",
1653 __FUNCTION__, lpq->ppp_slot);
1654 } else {
1655 u32 lls = ippp_table[slot]->last_link_seqno;
1656 if (MP_LT(lls, minseq))
1657 minseq = lls;
1658 }
1659 if ((lpq = lpq->next) == net_dev->queue)
1660 break;
1661 }
1662 if (MP_LT(minseq, mp->seq))
1663 minseq = mp->seq; /* can't go beyond already processed
1664 * packets */
1665 newfrag = skb;
1666
1667 /* if this new fragment is before the first one, then enqueue it now. */
1668 if ((frag = mp->frags) == NULL || MP_LT(newseq, MP_SEQ(frag))) {
1669 newfrag->next = frag;
1670 mp->frags = frag = newfrag;
1671 newfrag = NULL;
1672 }
1673
1674 start = MP_FLAGS(frag) & MP_BEGIN_FRAG &&
1675 MP_SEQ(frag) == mp->seq ? frag : NULL;
1676
1677 /*
1678 * main fragment traversing loop
1679 *
1680 * try to accomplish several tasks:
1681 * - insert new fragment into the proper sequence slot (once that's done
1682 * newfrag will be set to NULL)
1683 * - reassemble any complete fragment sequence (non-null 'start'
1684 * indicates there is a continguous sequence present)
1685 * - discard any incomplete sequences that are below minseq -- due
1686 * to the fact that sender always increment sequence number, if there
1687 * is an incomplete sequence below minseq, no new fragments would
1688 * come to complete such sequence and it should be discarded
1689 *
1690 * loop completes when we accomplished the following tasks:
1691 * - new fragment is inserted in the proper sequence ('newfrag' is
1692 * set to NULL)
1693 * - we hit a gap in the sequence, so no reassembly/processing is
1694 * possible ('start' would be set to NULL)
1695 *
1696 * algorightm for this code is derived from code in the book
1697 * 'PPP Design And Debugging' by James Carlson (Addison-Wesley)
1698 */
1699 while (start != NULL || newfrag != NULL) {
1700
1701 thisseq = MP_SEQ(frag);
1702 nextf = frag->next;
1703
1704 /* drop any duplicate fragments */
1705 if (newfrag != NULL && thisseq == newseq) {
1706 isdn_ppp_mp_free_skb(mp, newfrag);
1707 newfrag = NULL;
1708 }
1709
1710 /* insert new fragment before next element if possible. */
1711 if (newfrag != NULL && (nextf == NULL ||
1712 MP_LT(newseq, MP_SEQ(nextf)))) {
1713 newfrag->next = nextf;
1714 frag->next = nextf = newfrag;
1715 newfrag = NULL;
1716 }
1717
1718 if (start != NULL) {
1719 /* check for misplaced start */
1720 if (start != frag && (MP_FLAGS(frag) & MP_BEGIN_FRAG)) {
1721 printk(KERN_WARNING"isdn_mppp(seq %d): new "
1722 "BEGIN flag with no prior END", thisseq);
1723 stats->seqerrs++;
1724 stats->frame_drops++;
1725 start = isdn_ppp_mp_discard(mp, start,frag);
1726 nextf = frag->next;
1727 }
1728 } else if (MP_LE(thisseq, minseq)) {
1729 if (MP_FLAGS(frag) & MP_BEGIN_FRAG)
1730 start = frag;
1731 else {
1732 if (MP_FLAGS(frag) & MP_END_FRAG)
1733 stats->frame_drops++;
1734 if( mp->frags == frag )
1735 mp->frags = nextf;
1736 isdn_ppp_mp_free_skb(mp, frag);
1737 frag = nextf;
1738 continue;
1739 }
1740 }
1741
1742 /* if start is non-null and we have end fragment, then
1743 * we have full reassembly sequence -- reassemble
1744 * and process packet now
1745 */
1746 if (start != NULL && (MP_FLAGS(frag) & MP_END_FRAG)) {
1747 minseq = mp->seq = (thisseq+1) & MP_LONGSEQ_MASK;
1748 /* Reassemble the packet then dispatch it */
1749 isdn_ppp_mp_reassembly(net_dev, lp, start, nextf);
1750
1751 start = NULL;
1752 frag = NULL;
1753
1754 mp->frags = nextf;
1755 }
1756
1757 /* check if need to update start pointer: if we just
1758 * reassembled the packet and sequence is contiguous
1759 * then next fragment should be the start of new reassembly
1760 * if sequence is contiguous, but we haven't reassembled yet,
1761 * keep going.
1762 * if sequence is not contiguous, either clear everyting
1763 * below low watermark and set start to the next frag or
1764 * clear start ptr.
1765 */
1766 if (nextf != NULL &&
1767 ((thisseq+1) & MP_LONGSEQ_MASK) == MP_SEQ(nextf)) {
1768 /* if we just reassembled and the next one is here,
1769 * then start another reassembly. */
1770
1771 if (frag == NULL) {
1772 if (MP_FLAGS(nextf) & MP_BEGIN_FRAG)
1773 start = nextf;
1774 else
1775 {
1776 printk(KERN_WARNING"isdn_mppp(seq %d):"
1777 " END flag with no following "
1778 "BEGIN", thisseq);
1779 stats->seqerrs++;
1780 }
1781 }
1782
1783 } else {
1784 if ( nextf != NULL && frag != NULL &&
1785 MP_LT(thisseq, minseq)) {
1786 /* we've got a break in the sequence
1787 * and we not at the end yet
1788 * and we did not just reassembled
1789 *(if we did, there wouldn't be anything before)
1790 * and we below the low watermark
1791 * discard all the frames below low watermark
1792 * and start over */
1793 stats->frame_drops++;
1794 mp->frags = isdn_ppp_mp_discard(mp,start,nextf);
1795 }
1796 /* break in the sequence, no reassembly */
1797 start = NULL;
1798 }
1799
1800 frag = nextf;
1801 } /* while -- main loop */
1802
1803 if (mp->frags == NULL)
1804 mp->frags = frag;
1805
1806 /* rather straighforward way to deal with (not very) possible
1807 * queue overflow */
1808 if (mp->frames > MP_MAX_QUEUE_LEN) {
1809 stats->overflows++;
1810 while (mp->frames > MP_MAX_QUEUE_LEN) {
1811 frag = mp->frags->next;
1812 isdn_ppp_mp_free_skb(mp, mp->frags);
1813 mp->frags = frag;
1814 }
1815 }
1816 spin_unlock_irqrestore(&mp->lock, flags);
1817}
1818
1819static void isdn_ppp_mp_cleanup( isdn_net_local * lp )
1820{
1821 struct sk_buff * frag = lp->netdev->pb->frags;
1822 struct sk_buff * nextfrag;
1823 while( frag ) {
1824 nextfrag = frag->next;
1825 isdn_ppp_mp_free_skb(lp->netdev->pb, frag);
1826 frag = nextfrag;
1827 }
1828 lp->netdev->pb->frags = NULL;
1829}
1830
1831static u32 isdn_ppp_mp_get_seq( int short_seq,
1832 struct sk_buff * skb, u32 last_seq )
1833{
1834 u32 seq;
1835 int flags = skb->data[0] & (MP_BEGIN_FRAG | MP_END_FRAG);
1836
1837 if( !short_seq )
1838 {
1839 seq = ntohl(*(u32*)skb->data) & MP_LONGSEQ_MASK;
1840 skb_push(skb,1);
1841 }
1842 else
1843 {
1844 /* convert 12-bit short seq number to 24-bit long one
1845 */
1846 seq = ntohs(*(u16*)skb->data) & MP_SHORTSEQ_MASK;
1847
1848 /* check for seqence wrap */
1849 if( !(seq & MP_SHORTSEQ_MAXBIT) &&
1850 (last_seq & MP_SHORTSEQ_MAXBIT) &&
1851 (unsigned long)last_seq <= MP_LONGSEQ_MAX )
1852 seq |= (last_seq + MP_SHORTSEQ_MAX+1) &
1853 (~MP_SHORTSEQ_MASK & MP_LONGSEQ_MASK);
1854 else
1855 seq |= last_seq & (~MP_SHORTSEQ_MASK & MP_LONGSEQ_MASK);
1856
1857 skb_push(skb, 3); /* put converted seqence back in skb */
1858 }
1859 *(u32*)(skb->data+1) = seq; /* put seqence back in _host_ byte
1860 * order */
1861 skb->data[0] = flags; /* restore flags */
1862 return seq;
1863}
1864
1865struct sk_buff * isdn_ppp_mp_discard( ippp_bundle * mp,
1866 struct sk_buff * from, struct sk_buff * to )
1867{
1868 if( from )
1869 while (from != to) {
1870 struct sk_buff * next = from->next;
1871 isdn_ppp_mp_free_skb(mp, from);
1872 from = next;
1873 }
1874 return from;
1875}
1876
1877void isdn_ppp_mp_reassembly( isdn_net_dev * net_dev, isdn_net_local * lp,
1878 struct sk_buff * from, struct sk_buff * to )
1879{
1880 ippp_bundle * mp = net_dev->pb;
1881 int proto;
1882 struct sk_buff * skb;
1883 unsigned int tot_len;
1884
1885 if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) {
1886 printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
1887 __FUNCTION__, lp->ppp_slot);
1888 return;
1889 }
1890 if( MP_FLAGS(from) == (MP_BEGIN_FRAG | MP_END_FRAG) ) {
1891 if( ippp_table[lp->ppp_slot]->debug & 0x40 )
1892 printk(KERN_DEBUG "isdn_mppp: reassembly: frame %d, "
1893 "len %d\n", MP_SEQ(from), from->len );
1894 skb = from;
1895 skb_pull(skb, MP_HEADER_LEN);
1896 mp->frames--;
1897 } else {
1898 struct sk_buff * frag;
1899 int n;
1900
1901 for(tot_len=n=0, frag=from; frag != to; frag=frag->next, n++)
1902 tot_len += frag->len - MP_HEADER_LEN;
1903
1904 if( ippp_table[lp->ppp_slot]->debug & 0x40 )
1905 printk(KERN_DEBUG"isdn_mppp: reassembling frames %d "
1906 "to %d, len %d\n", MP_SEQ(from),
1907 (MP_SEQ(from)+n-1) & MP_LONGSEQ_MASK, tot_len );
1908 if( (skb = dev_alloc_skb(tot_len)) == NULL ) {
1909 printk(KERN_ERR "isdn_mppp: cannot allocate sk buff "
1910 "of size %d\n", tot_len);
1911 isdn_ppp_mp_discard(mp, from, to);
1912 return;
1913 }
1914
1915 while( from != to ) {
1916 unsigned int len = from->len - MP_HEADER_LEN;
1917
1918 memcpy(skb_put(skb,len), from->data+MP_HEADER_LEN, len);
1919 frag = from->next;
1920 isdn_ppp_mp_free_skb(mp, from);
1921 from = frag;
1922 }
1923 }
1924 proto = isdn_ppp_strip_proto(skb);
1925 isdn_ppp_push_higher(net_dev, lp, skb, proto);
1926}
1927
1928static void isdn_ppp_mp_free_skb(ippp_bundle * mp, struct sk_buff * skb)
1929{
1930 dev_kfree_skb(skb);
1931 mp->frames--;
1932}
1933
1934static void isdn_ppp_mp_print_recv_pkt( int slot, struct sk_buff * skb )
1935{
1936 printk(KERN_DEBUG "mp_recv: %d/%d -> %02x %02x %02x %02x %02x %02x\n",
1937 slot, (int) skb->len,
1938 (int) skb->data[0], (int) skb->data[1], (int) skb->data[2],
1939 (int) skb->data[3], (int) skb->data[4], (int) skb->data[5]);
1940}
1941
1942static int
1943isdn_ppp_bundle(struct ippp_struct *is, int unit)
1944{
1945 char ifn[IFNAMSIZ + 1];
1946 isdn_net_dev *p;
1947 isdn_net_local *lp, *nlp;
1948 int rc;
1949 unsigned long flags;
1950
1951 sprintf(ifn, "ippp%d", unit);
1952 p = isdn_net_findif(ifn);
1953 if (!p) {
1954 printk(KERN_ERR "ippp_bundle: cannot find %s\n", ifn);
1955 return -EINVAL;
1956 }
1957
1958 spin_lock_irqsave(&p->pb->lock, flags);
1959
1960 nlp = is->lp;
1961 lp = p->queue;
1962 if( nlp->ppp_slot < 0 || nlp->ppp_slot >= ISDN_MAX_CHANNELS ||
1963 lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS ) {
1964 printk(KERN_ERR "ippp_bundle: binding to invalid slot %d\n",
1965 nlp->ppp_slot < 0 || nlp->ppp_slot >= ISDN_MAX_CHANNELS ?
1966 nlp->ppp_slot : lp->ppp_slot );
1967 rc = -EINVAL;
1968 goto out;
1969 }
1970
1971 isdn_net_add_to_bundle(p, nlp);
1972
1973 ippp_table[nlp->ppp_slot]->unit = ippp_table[lp->ppp_slot]->unit;
1974
1975 /* maybe also SC_CCP stuff */
1976 ippp_table[nlp->ppp_slot]->pppcfg |= ippp_table[lp->ppp_slot]->pppcfg &
1977 (SC_ENABLE_IP | SC_NO_TCP_CCID | SC_REJ_COMP_TCP);
1978 ippp_table[nlp->ppp_slot]->mpppcfg |= ippp_table[lp->ppp_slot]->mpppcfg &
1979 (SC_MP_PROT | SC_REJ_MP_PROT | SC_OUT_SHORT_SEQ | SC_IN_SHORT_SEQ);
1980 rc = isdn_ppp_mp_init(nlp, p->pb);
1981out:
1982 spin_unlock_irqrestore(&p->pb->lock, flags);
1983 return rc;
1984}
1985
1986#endif /* CONFIG_ISDN_MPP */
1987
1988/*
1989 * network device ioctl handlers
1990 */
1991
1992static int
1993isdn_ppp_dev_ioctl_stats(int slot, struct ifreq *ifr, struct net_device *dev)
1994{
1995 struct ppp_stats __user *res = ifr->ifr_data;
1996 struct ppp_stats t;
1997 isdn_net_local *lp = (isdn_net_local *) dev->priv;
1998
1999 if (!access_ok(VERIFY_WRITE, res, sizeof(struct ppp_stats)))
2000 return -EFAULT;
2001
2002 /* build a temporary stat struct and copy it to user space */
2003
2004 memset(&t, 0, sizeof(struct ppp_stats));
2005 if (dev->flags & IFF_UP) {
2006 t.p.ppp_ipackets = lp->stats.rx_packets;
2007 t.p.ppp_ibytes = lp->stats.rx_bytes;
2008 t.p.ppp_ierrors = lp->stats.rx_errors;
2009 t.p.ppp_opackets = lp->stats.tx_packets;
2010 t.p.ppp_obytes = lp->stats.tx_bytes;
2011 t.p.ppp_oerrors = lp->stats.tx_errors;
2012#ifdef CONFIG_ISDN_PPP_VJ
2013 if (slot >= 0 && ippp_table[slot]->slcomp) {
2014 struct slcompress *slcomp = ippp_table[slot]->slcomp;
2015 t.vj.vjs_packets = slcomp->sls_o_compressed + slcomp->sls_o_uncompressed;
2016 t.vj.vjs_compressed = slcomp->sls_o_compressed;
2017 t.vj.vjs_searches = slcomp->sls_o_searches;
2018 t.vj.vjs_misses = slcomp->sls_o_misses;
2019 t.vj.vjs_errorin = slcomp->sls_i_error;
2020 t.vj.vjs_tossed = slcomp->sls_i_tossed;
2021 t.vj.vjs_uncompressedin = slcomp->sls_i_uncompressed;
2022 t.vj.vjs_compressedin = slcomp->sls_i_compressed;
2023 }
2024#endif
2025 }
2026 if (copy_to_user(res, &t, sizeof(struct ppp_stats)))
2027 return -EFAULT;
2028 return 0;
2029}
2030
2031int
2032isdn_ppp_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
2033{
2034 int error=0;
2035 int len;
2036 isdn_net_local *lp = (isdn_net_local *) dev->priv;
2037
2038
2039 if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP)
2040 return -EINVAL;
2041
2042 switch (cmd) {
2043#define PPP_VERSION "2.3.7"
2044 case SIOCGPPPVER:
2045 len = strlen(PPP_VERSION) + 1;
2046 if (copy_to_user(ifr->ifr_data, PPP_VERSION, len))
2047 error = -EFAULT;
2048 break;
2049
2050 case SIOCGPPPSTATS:
2051 error = isdn_ppp_dev_ioctl_stats(lp->ppp_slot, ifr, dev);
2052 break;
2053 default:
2054 error = -EINVAL;
2055 break;
2056 }
2057 return error;
2058}
2059
2060static int
2061isdn_ppp_if_get_unit(char *name)
2062{
2063 int len,
2064 i,
2065 unit = 0,
2066 deci;
2067
2068 len = strlen(name);
2069
2070 if (strncmp("ippp", name, 4) || len > 8)
2071 return -1;
2072
2073 for (i = 0, deci = 1; i < len; i++, deci *= 10) {
2074 char a = name[len - i - 1];
2075 if (a >= '0' && a <= '9')
2076 unit += (a - '0') * deci;
2077 else
2078 break;
2079 }
2080 if (!i || len - i != 4)
2081 unit = -1;
2082
2083 return unit;
2084}
2085
2086
2087int
2088isdn_ppp_dial_slave(char *name)
2089{
2090#ifdef CONFIG_ISDN_MPP
2091 isdn_net_dev *ndev;
2092 isdn_net_local *lp;
2093 struct net_device *sdev;
2094
2095 if (!(ndev = isdn_net_findif(name)))
2096 return 1;
2097 lp = ndev->local;
2098 if (!(lp->flags & ISDN_NET_CONNECTED))
2099 return 5;
2100
2101 sdev = lp->slave;
2102 while (sdev) {
2103 isdn_net_local *mlp = (isdn_net_local *) sdev->priv;
2104 if (!(mlp->flags & ISDN_NET_CONNECTED))
2105 break;
2106 sdev = mlp->slave;
2107 }
2108 if (!sdev)
2109 return 2;
2110
2111 isdn_net_dial_req((isdn_net_local *) sdev->priv);
2112 return 0;
2113#else
2114 return -1;
2115#endif
2116}
2117
2118int
2119isdn_ppp_hangup_slave(char *name)
2120{
2121#ifdef CONFIG_ISDN_MPP
2122 isdn_net_dev *ndev;
2123 isdn_net_local *lp;
2124 struct net_device *sdev;
2125
2126 if (!(ndev = isdn_net_findif(name)))
2127 return 1;
2128 lp = ndev->local;
2129 if (!(lp->flags & ISDN_NET_CONNECTED))
2130 return 5;
2131
2132 sdev = lp->slave;
2133 while (sdev) {
2134 isdn_net_local *mlp = (isdn_net_local *) sdev->priv;
2135
2136 if (mlp->slave) { /* find last connected link in chain */
2137 isdn_net_local *nlp = (isdn_net_local *) mlp->slave->priv;
2138
2139 if (!(nlp->flags & ISDN_NET_CONNECTED))
2140 break;
2141 } else if (mlp->flags & ISDN_NET_CONNECTED)
2142 break;
2143
2144 sdev = mlp->slave;
2145 }
2146 if (!sdev)
2147 return 2;
2148
2149 isdn_net_hangup(sdev);
2150 return 0;
2151#else
2152 return -1;
2153#endif
2154}
2155
2156/*
2157 * PPP compression stuff
2158 */
2159
2160
2161/* Push an empty CCP Data Frame up to the daemon to wake it up and let it
2162 generate a CCP Reset-Request or tear down CCP altogether */
2163
2164static void isdn_ppp_ccp_kickup(struct ippp_struct *is)
2165{
2166 isdn_ppp_fill_rq(NULL, 0, PPP_COMP, is->lp->ppp_slot);
2167}
2168
2169/* In-kernel handling of CCP Reset-Request and Reset-Ack is necessary,
2170 but absolutely nontrivial. The most abstruse problem we are facing is
2171 that the generation, reception and all the handling of timeouts and
2172 resends including proper request id management should be entirely left
2173 to the (de)compressor, but indeed is not covered by the current API to
2174 the (de)compressor. The API is a prototype version from PPP where only
2175 some (de)compressors have yet been implemented and all of them are
2176 rather simple in their reset handling. Especially, their is only one
2177 outstanding ResetAck at a time with all of them and ResetReq/-Acks do
2178 not have parameters. For this very special case it was sufficient to
2179 just return an error code from the decompressor and have a single
2180 reset() entry to communicate all the necessary information between
2181 the framework and the (de)compressor. Bad enough, LZS is different
2182 (and any other compressor may be different, too). It has multiple
2183 histories (eventually) and needs to Reset each of them independently
2184 and thus uses multiple outstanding Acks and history numbers as an
2185 additional parameter to Reqs/Acks.
2186 All that makes it harder to port the reset state engine into the
2187 kernel because it is not just the same simple one as in (i)pppd but
2188 it must be able to pass additional parameters and have multiple out-
2189 standing Acks. We are trying to achieve the impossible by handling
2190 reset transactions independent by their id. The id MUST change when
2191 the data portion changes, thus any (de)compressor who uses more than
2192 one resettable state must provide and recognize individual ids for
2193 each individual reset transaction. The framework itself does _only_
2194 differentiate them by id, because it has no other semantics like the
2195 (de)compressor might.
2196 This looks like a major redesign of the interface would be nice,
2197 but I don't have an idea how to do it better. */
2198
2199/* Send a CCP Reset-Request or Reset-Ack directly from the kernel. This is
2200 getting that lengthy because there is no simple "send-this-frame-out"
2201 function above but every wrapper does a bit different. Hope I guess
2202 correct in this hack... */
2203
2204static void isdn_ppp_ccp_xmit_reset(struct ippp_struct *is, int proto,
2205 unsigned char code, unsigned char id,
2206 unsigned char *data, int len)
2207{
2208 struct sk_buff *skb;
2209 unsigned char *p;
2210 int hl;
2211 int cnt = 0;
2212 isdn_net_local *lp = is->lp;
2213
2214 /* Alloc large enough skb */
2215 hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen;
2216 skb = alloc_skb(len + hl + 16,GFP_ATOMIC);
2217 if(!skb) {
2218 printk(KERN_WARNING
2219 "ippp: CCP cannot send reset - out of memory\n");
2220 return;
2221 }
2222 skb_reserve(skb, hl);
2223
2224 /* We may need to stuff an address and control field first */
2225 if(!(is->pppcfg & SC_COMP_AC)) {
2226 p = skb_put(skb, 2);
2227 *p++ = 0xff;
2228 *p++ = 0x03;
2229 }
2230
2231 /* Stuff proto, code, id and length */
2232 p = skb_put(skb, 6);
2233 *p++ = (proto >> 8);
2234 *p++ = (proto & 0xff);
2235 *p++ = code;
2236 *p++ = id;
2237 cnt = 4 + len;
2238 *p++ = (cnt >> 8);
2239 *p++ = (cnt & 0xff);
2240
2241 /* Now stuff remaining bytes */
2242 if(len) {
2243 p = skb_put(skb, len);
2244 memcpy(p, data, len);
2245 }
2246
2247 /* skb is now ready for xmit */
2248 printk(KERN_DEBUG "Sending CCP Frame:\n");
2249 isdn_ppp_frame_log("ccp-xmit", skb->data, skb->len, 32, is->unit,lp->ppp_slot);
2250
2251 isdn_net_write_super(lp, skb);
2252}
2253
2254/* Allocate the reset state vector */
2255static struct ippp_ccp_reset *isdn_ppp_ccp_reset_alloc(struct ippp_struct *is)
2256{
2257 struct ippp_ccp_reset *r;
2258 r = kmalloc(sizeof(struct ippp_ccp_reset), GFP_KERNEL);
2259 if(!r) {
2260 printk(KERN_ERR "ippp_ccp: failed to allocate reset data"
2261 " structure - no mem\n");
2262 return NULL;
2263 }
2264 memset(r, 0, sizeof(struct ippp_ccp_reset));
2265 printk(KERN_DEBUG "ippp_ccp: allocated reset data structure %p\n", r);
2266 is->reset = r;
2267 return r;
2268}
2269
2270/* Destroy the reset state vector. Kill all pending timers first. */
2271static void isdn_ppp_ccp_reset_free(struct ippp_struct *is)
2272{
2273 unsigned int id;
2274
2275 printk(KERN_DEBUG "ippp_ccp: freeing reset data structure %p\n",
2276 is->reset);
2277 for(id = 0; id < 256; id++) {
2278 if(is->reset->rs[id]) {
2279 isdn_ppp_ccp_reset_free_state(is, (unsigned char)id);
2280 }
2281 }
2282 kfree(is->reset);
2283 is->reset = NULL;
2284}
2285
2286/* Free a given state and clear everything up for later reallocation */
2287static void isdn_ppp_ccp_reset_free_state(struct ippp_struct *is,
2288 unsigned char id)
2289{
2290 struct ippp_ccp_reset_state *rs;
2291
2292 if(is->reset->rs[id]) {
2293 printk(KERN_DEBUG "ippp_ccp: freeing state for id %d\n", id);
2294 rs = is->reset->rs[id];
2295 /* Make sure the kernel will not call back later */
2296 if(rs->ta)
2297 del_timer(&rs->timer);
2298 is->reset->rs[id] = NULL;
2299 kfree(rs);
2300 } else {
2301 printk(KERN_WARNING "ippp_ccp: id %d is not allocated\n", id);
2302 }
2303}
2304
2305/* The timer callback function which is called when a ResetReq has timed out,
2306 aka has never been answered by a ResetAck */
2307static void isdn_ppp_ccp_timer_callback(unsigned long closure)
2308{
2309 struct ippp_ccp_reset_state *rs =
2310 (struct ippp_ccp_reset_state *)closure;
2311
2312 if(!rs) {
2313 printk(KERN_ERR "ippp_ccp: timer cb with zero closure.\n");
2314 return;
2315 }
2316 if(rs->ta && rs->state == CCPResetSentReq) {
2317 /* We are correct here */
2318 if(!rs->expra) {
2319 /* Hmm, there is no Ack really expected. We can clean
2320 up the state now, it will be reallocated if the
2321 decompressor insists on another reset */
2322 rs->ta = 0;
2323 isdn_ppp_ccp_reset_free_state(rs->is, rs->id);
2324 return;
2325 }
2326 printk(KERN_DEBUG "ippp_ccp: CCP Reset timed out for id %d\n",
2327 rs->id);
2328 /* Push it again */
2329 isdn_ppp_ccp_xmit_reset(rs->is, PPP_CCP, CCP_RESETREQ, rs->id,
2330 rs->data, rs->dlen);
2331 /* Restart timer */
2332 rs->timer.expires = jiffies + HZ*5;
2333 add_timer(&rs->timer);
2334 } else {
2335 printk(KERN_WARNING "ippp_ccp: timer cb in wrong state %d\n",
2336 rs->state);
2337 }
2338}
2339
2340/* Allocate a new reset transaction state */
2341static struct ippp_ccp_reset_state *isdn_ppp_ccp_reset_alloc_state(struct ippp_struct *is,
2342 unsigned char id)
2343{
2344 struct ippp_ccp_reset_state *rs;
2345 if(is->reset->rs[id]) {
2346 printk(KERN_WARNING "ippp_ccp: old state exists for id %d\n",
2347 id);
2348 return NULL;
2349 } else {
2350 rs = kmalloc(sizeof(struct ippp_ccp_reset_state), GFP_KERNEL);
2351 if(!rs)
2352 return NULL;
2353 memset(rs, 0, sizeof(struct ippp_ccp_reset_state));
2354 rs->state = CCPResetIdle;
2355 rs->is = is;
2356 rs->id = id;
2357 rs->timer.data = (unsigned long)rs;
2358 rs->timer.function = isdn_ppp_ccp_timer_callback;
2359 is->reset->rs[id] = rs;
2360 }
2361 return rs;
2362}
2363
2364
2365/* A decompressor wants a reset with a set of parameters - do what is
2366 necessary to fulfill it */
2367static void isdn_ppp_ccp_reset_trans(struct ippp_struct *is,
2368 struct isdn_ppp_resetparams *rp)
2369{
2370 struct ippp_ccp_reset_state *rs;
2371
2372 if(rp->valid) {
2373 /* The decompressor defines parameters by itself */
2374 if(rp->rsend) {
2375 /* And he wants us to send a request */
2376 if(!(rp->idval)) {
2377 printk(KERN_ERR "ippp_ccp: decompressor must"
2378 " specify reset id\n");
2379 return;
2380 }
2381 if(is->reset->rs[rp->id]) {
2382 /* There is already a transaction in existence
2383 for this id. May be still waiting for a
2384 Ack or may be wrong. */
2385 rs = is->reset->rs[rp->id];
2386 if(rs->state == CCPResetSentReq && rs->ta) {
2387 printk(KERN_DEBUG "ippp_ccp: reset"
2388 " trans still in progress"
2389 " for id %d\n", rp->id);
2390 } else {
2391 printk(KERN_WARNING "ippp_ccp: reset"
2392 " trans in wrong state %d for"
2393 " id %d\n", rs->state, rp->id);
2394 }
2395 } else {
2396 /* Ok, this is a new transaction */
2397 printk(KERN_DEBUG "ippp_ccp: new trans for id"
2398 " %d to be started\n", rp->id);
2399 rs = isdn_ppp_ccp_reset_alloc_state(is, rp->id);
2400 if(!rs) {
2401 printk(KERN_ERR "ippp_ccp: out of mem"
2402 " allocing ccp trans\n");
2403 return;
2404 }
2405 rs->state = CCPResetSentReq;
2406 rs->expra = rp->expra;
2407 if(rp->dtval) {
2408 rs->dlen = rp->dlen;
2409 memcpy(rs->data, rp->data, rp->dlen);
2410 }
2411 /* HACK TODO - add link comp here */
2412 isdn_ppp_ccp_xmit_reset(is, PPP_CCP,
2413 CCP_RESETREQ, rs->id,
2414 rs->data, rs->dlen);
2415 /* Start the timer */
2416 rs->timer.expires = jiffies + 5*HZ;
2417 add_timer(&rs->timer);
2418 rs->ta = 1;
2419 }
2420 } else {
2421 printk(KERN_DEBUG "ippp_ccp: no reset sent\n");
2422 }
2423 } else {
2424 /* The reset params are invalid. The decompressor does not
2425 care about them, so we just send the minimal requests
2426 and increase ids only when an Ack is received for a
2427 given id */
2428 if(is->reset->rs[is->reset->lastid]) {
2429 /* There is already a transaction in existence
2430 for this id. May be still waiting for a
2431 Ack or may be wrong. */
2432 rs = is->reset->rs[is->reset->lastid];
2433 if(rs->state == CCPResetSentReq && rs->ta) {
2434 printk(KERN_DEBUG "ippp_ccp: reset"
2435 " trans still in progress"
2436 " for id %d\n", rp->id);
2437 } else {
2438 printk(KERN_WARNING "ippp_ccp: reset"
2439 " trans in wrong state %d for"
2440 " id %d\n", rs->state, rp->id);
2441 }
2442 } else {
2443 printk(KERN_DEBUG "ippp_ccp: new trans for id"
2444 " %d to be started\n", is->reset->lastid);
2445 rs = isdn_ppp_ccp_reset_alloc_state(is,
2446 is->reset->lastid);
2447 if(!rs) {
2448 printk(KERN_ERR "ippp_ccp: out of mem"
2449 " allocing ccp trans\n");
2450 return;
2451 }
2452 rs->state = CCPResetSentReq;
2453 /* We always expect an Ack if the decompressor doesn't
2454 know better */
2455 rs->expra = 1;
2456 rs->dlen = 0;
2457 /* HACK TODO - add link comp here */
2458 isdn_ppp_ccp_xmit_reset(is, PPP_CCP, CCP_RESETREQ,
2459 rs->id, NULL, 0);
2460 /* Start the timer */
2461 rs->timer.expires = jiffies + 5*HZ;
2462 add_timer(&rs->timer);
2463 rs->ta = 1;
2464 }
2465 }
2466}
2467
2468/* An Ack was received for this id. This means we stop the timer and clean
2469 up the state prior to calling the decompressors reset routine. */
2470static void isdn_ppp_ccp_reset_ack_rcvd(struct ippp_struct *is,
2471 unsigned char id)
2472{
2473 struct ippp_ccp_reset_state *rs = is->reset->rs[id];
2474
2475 if(rs) {
2476 if(rs->ta && rs->state == CCPResetSentReq) {
2477 /* Great, we are correct */
2478 if(!rs->expra)
2479 printk(KERN_DEBUG "ippp_ccp: ResetAck received"
2480 " for id %d but not expected\n", id);
2481 } else {
2482 printk(KERN_INFO "ippp_ccp: ResetAck received out of"
2483 "sync for id %d\n", id);
2484 }
2485 if(rs->ta) {
2486 rs->ta = 0;
2487 del_timer(&rs->timer);
2488 }
2489 isdn_ppp_ccp_reset_free_state(is, id);
2490 } else {
2491 printk(KERN_INFO "ippp_ccp: ResetAck received for unknown id"
2492 " %d\n", id);
2493 }
2494 /* Make sure the simple reset stuff uses a new id next time */
2495 is->reset->lastid++;
2496}
2497
2498/*
2499 * decompress packet
2500 *
2501 * if master = 0, we're trying to uncompress an per-link compressed packet,
2502 * as opposed to an compressed reconstructed-from-MPPP packet.
2503 * proto is updated to protocol field of uncompressed packet.
2504 *
2505 * retval: decompressed packet,
2506 * same packet if uncompressed,
2507 * NULL if decompression error
2508 */
2509
2510static struct sk_buff *isdn_ppp_decompress(struct sk_buff *skb,struct ippp_struct *is,struct ippp_struct *master,
2511 int *proto)
2512{
2513 void *stat = NULL;
2514 struct isdn_ppp_compressor *ipc = NULL;
2515 struct sk_buff *skb_out;
2516 int len;
2517 struct ippp_struct *ri;
2518 struct isdn_ppp_resetparams rsparm;
2519 unsigned char rsdata[IPPP_RESET_MAXDATABYTES];
2520
2521 if(!master) {
2522 // per-link decompression
2523 stat = is->link_decomp_stat;
2524 ipc = is->link_decompressor;
2525 ri = is;
2526 } else {
2527 stat = master->decomp_stat;
2528 ipc = master->decompressor;
2529 ri = master;
2530 }
2531
2532 if (!ipc) {
2533 // no decompressor -> we can't decompress.
2534 printk(KERN_DEBUG "ippp: no decompressor defined!\n");
2535 return skb;
2536 }
2537 if (!stat) // if we have a compressor, stat has been set as well
2538 BUG();
2539
2540 if((master && *proto == PPP_COMP) || (!master && *proto == PPP_COMPFRAG) ) {
2541 // compressed packets are compressed by their protocol type
2542
2543 // Set up reset params for the decompressor
2544 memset(&rsparm, 0, sizeof(rsparm));
2545 rsparm.data = rsdata;
2546 rsparm.maxdlen = IPPP_RESET_MAXDATABYTES;
2547
2548 skb_out = dev_alloc_skb(is->mru + PPP_HDRLEN);
2549 len = ipc->decompress(stat, skb, skb_out, &rsparm);
2550 kfree_skb(skb);
2551 if (len <= 0) {
2552 switch(len) {
2553 case DECOMP_ERROR:
2554 printk(KERN_INFO "ippp: decomp wants reset %s params\n",
2555 rsparm.valid ? "with" : "without");
2556
2557 isdn_ppp_ccp_reset_trans(ri, &rsparm);
2558 break;
2559 case DECOMP_FATALERROR:
2560 ri->pppcfg |= SC_DC_FERROR;
2561 /* Kick ipppd to recognize the error */
2562 isdn_ppp_ccp_kickup(ri);
2563 break;
2564 }
2565 kfree_skb(skb_out);
2566 return NULL;
2567 }
2568 *proto = isdn_ppp_strip_proto(skb_out);
2569 if (*proto < 0) {
2570 kfree_skb(skb_out);
2571 return NULL;
2572 }
2573 return skb_out;
2574 } else {
2575 // uncompressed packets are fed through the decompressor to
2576 // update the decompressor state
2577 ipc->incomp(stat, skb, *proto);
2578 return skb;
2579 }
2580}
2581
2582/*
2583 * compress a frame
2584 * type=0: normal/bundle compression
2585 * =1: link compression
2586 * returns original skb if we haven't compressed the frame
2587 * and a new skb pointer if we've done it
2588 */
2589static struct sk_buff *isdn_ppp_compress(struct sk_buff *skb_in,int *proto,
2590 struct ippp_struct *is,struct ippp_struct *master,int type)
2591{
2592 int ret;
2593 int new_proto;
2594 struct isdn_ppp_compressor *compressor;
2595 void *stat;
2596 struct sk_buff *skb_out;
2597
2598 /* we do not compress control protocols */
2599 if(*proto < 0 || *proto > 0x3fff) {
2600 return skb_in;
2601 }
2602
2603 if(type) { /* type=1 => Link compression */
2604 return skb_in;
2605 }
2606 else {
2607 if(!master) {
2608 compressor = is->compressor;
2609 stat = is->comp_stat;
2610 }
2611 else {
2612 compressor = master->compressor;
2613 stat = master->comp_stat;
2614 }
2615 new_proto = PPP_COMP;
2616 }
2617
2618 if(!compressor) {
2619 printk(KERN_ERR "isdn_ppp: No compressor set!\n");
2620 return skb_in;
2621 }
2622 if(!stat) {
2623 printk(KERN_ERR "isdn_ppp: Compressor not initialized?\n");
2624 return skb_in;
2625 }
2626
2627 /* Allow for at least 150 % expansion (for now) */
2628 skb_out = alloc_skb(skb_in->len + skb_in->len/2 + 32 +
2629 skb_headroom(skb_in), GFP_ATOMIC);
2630 if(!skb_out)
2631 return skb_in;
2632 skb_reserve(skb_out, skb_headroom(skb_in));
2633
2634 ret = (compressor->compress)(stat,skb_in,skb_out,*proto);
2635 if(!ret) {
2636 dev_kfree_skb(skb_out);
2637 return skb_in;
2638 }
2639
2640 dev_kfree_skb(skb_in);
2641 *proto = new_proto;
2642 return skb_out;
2643}
2644
2645/*
2646 * we received a CCP frame ..
2647 * not a clean solution, but we MUST handle a few cases in the kernel
2648 */
2649static void isdn_ppp_receive_ccp(isdn_net_dev *net_dev, isdn_net_local *lp,
2650 struct sk_buff *skb,int proto)
2651{
2652 struct ippp_struct *is;
2653 struct ippp_struct *mis;
2654 int len;
2655 struct isdn_ppp_resetparams rsparm;
2656 unsigned char rsdata[IPPP_RESET_MAXDATABYTES];
2657
2658 printk(KERN_DEBUG "Received CCP frame from peer slot(%d)\n",
2659 lp->ppp_slot);
2660 if (lp->ppp_slot < 0 || lp->ppp_slot > ISDN_MAX_CHANNELS) {
2661 printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
2662 __FUNCTION__, lp->ppp_slot);
2663 return;
2664 }
2665 is = ippp_table[lp->ppp_slot];
2666 isdn_ppp_frame_log("ccp-rcv", skb->data, skb->len, 32, is->unit,lp->ppp_slot);
2667
2668 if(lp->master) {
2669 int slot = ((isdn_net_local *) (lp->master->priv))->ppp_slot;
2670 if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
2671 printk(KERN_ERR "%s: slot(%d) out of range\n",
2672 __FUNCTION__, slot);
2673 return;
2674 }
2675 mis = ippp_table[slot];
2676 } else
2677 mis = is;
2678
2679 switch(skb->data[0]) {
2680 case CCP_CONFREQ:
2681 if(is->debug & 0x10)
2682 printk(KERN_DEBUG "Disable compression here!\n");
2683 if(proto == PPP_CCP)
2684 mis->compflags &= ~SC_COMP_ON;
2685 else
2686 is->compflags &= ~SC_LINK_COMP_ON;
2687 break;
2688 case CCP_TERMREQ:
2689 case CCP_TERMACK:
2690 if(is->debug & 0x10)
2691 printk(KERN_DEBUG "Disable (de)compression here!\n");
2692 if(proto == PPP_CCP)
2693 mis->compflags &= ~(SC_DECOMP_ON|SC_COMP_ON);
2694 else
2695 is->compflags &= ~(SC_LINK_DECOMP_ON|SC_LINK_COMP_ON);
2696 break;
2697 case CCP_CONFACK:
2698 /* if we RECEIVE an ackowledge we enable the decompressor */
2699 if(is->debug & 0x10)
2700 printk(KERN_DEBUG "Enable decompression here!\n");
2701 if(proto == PPP_CCP) {
2702 if (!mis->decompressor)
2703 break;
2704 mis->compflags |= SC_DECOMP_ON;
2705 } else {
2706 if (!is->decompressor)
2707 break;
2708 is->compflags |= SC_LINK_DECOMP_ON;
2709 }
2710 break;
2711
2712 case CCP_RESETACK:
2713 printk(KERN_DEBUG "Received ResetAck from peer\n");
2714 len = (skb->data[2] << 8) | skb->data[3];
2715 len -= 4;
2716
2717 if(proto == PPP_CCP) {
2718 /* If a reset Ack was outstanding for this id, then
2719 clean up the state engine */
2720 isdn_ppp_ccp_reset_ack_rcvd(mis, skb->data[1]);
2721 if(mis->decompressor && mis->decomp_stat)
2722 mis->decompressor->
2723 reset(mis->decomp_stat,
2724 skb->data[0],
2725 skb->data[1],
2726 len ? &skb->data[4] : NULL,
2727 len, NULL);
2728 /* TODO: This is not easy to decide here */
2729 mis->compflags &= ~SC_DECOMP_DISCARD;
2730 }
2731 else {
2732 isdn_ppp_ccp_reset_ack_rcvd(is, skb->data[1]);
2733 if(is->link_decompressor && is->link_decomp_stat)
2734 is->link_decompressor->
2735 reset(is->link_decomp_stat,
2736 skb->data[0],
2737 skb->data[1],
2738 len ? &skb->data[4] : NULL,
2739 len, NULL);
2740 /* TODO: neither here */
2741 is->compflags &= ~SC_LINK_DECOMP_DISCARD;
2742 }
2743 break;
2744
2745 case CCP_RESETREQ:
2746 printk(KERN_DEBUG "Received ResetReq from peer\n");
2747 /* Receiving a ResetReq means we must reset our compressor */
2748 /* Set up reset params for the reset entry */
2749 memset(&rsparm, 0, sizeof(rsparm));
2750 rsparm.data = rsdata;
2751 rsparm.maxdlen = IPPP_RESET_MAXDATABYTES;
2752 /* Isolate data length */
2753 len = (skb->data[2] << 8) | skb->data[3];
2754 len -= 4;
2755 if(proto == PPP_CCP) {
2756 if(mis->compressor && mis->comp_stat)
2757 mis->compressor->
2758 reset(mis->comp_stat,
2759 skb->data[0],
2760 skb->data[1],
2761 len ? &skb->data[4] : NULL,
2762 len, &rsparm);
2763 }
2764 else {
2765 if(is->link_compressor && is->link_comp_stat)
2766 is->link_compressor->
2767 reset(is->link_comp_stat,
2768 skb->data[0],
2769 skb->data[1],
2770 len ? &skb->data[4] : NULL,
2771 len, &rsparm);
2772 }
2773 /* Ack the Req as specified by rsparm */
2774 if(rsparm.valid) {
2775 /* Compressor reset handler decided how to answer */
2776 if(rsparm.rsend) {
2777 /* We should send a Frame */
2778 isdn_ppp_ccp_xmit_reset(is, proto, CCP_RESETACK,
2779 rsparm.idval ? rsparm.id
2780 : skb->data[1],
2781 rsparm.dtval ?
2782 rsparm.data : NULL,
2783 rsparm.dtval ?
2784 rsparm.dlen : 0);
2785 } else {
2786 printk(KERN_DEBUG "ResetAck suppressed\n");
2787 }
2788 } else {
2789 /* We answer with a straight reflected Ack */
2790 isdn_ppp_ccp_xmit_reset(is, proto, CCP_RESETACK,
2791 skb->data[1],
2792 len ? &skb->data[4] : NULL,
2793 len);
2794 }
2795 break;
2796 }
2797}
2798
2799
2800/*
2801 * Daemon sends a CCP frame ...
2802 */
2803
2804/* TODO: Clean this up with new Reset semantics */
2805
2806/* I believe the CCP handling as-is is done wrong. Compressed frames
2807 * should only be sent/received after CCP reaches UP state, which means
2808 * both sides have sent CONF_ACK. Currently, we handle both directions
2809 * independently, which means we may accept compressed frames too early
2810 * (supposedly not a problem), but may also mean we send compressed frames
2811 * too early, which may turn out to be a problem.
2812 * This part of state machine should actually be handled by (i)pppd, but
2813 * that's too big of a change now. --kai
2814 */
2815
2816/* Actually, we might turn this into an advantage: deal with the RFC in
2817 * the old tradition of beeing generous on what we accept, but beeing
2818 * strict on what we send. Thus we should just
2819 * - accept compressed frames as soon as decompression is negotiated
2820 * - send compressed frames only when decomp *and* comp are negotiated
2821 * - drop rx compressed frames if we cannot decomp (instead of pushing them
2822 * up to ipppd)
2823 * and I tried to modify this file according to that. --abp
2824 */
2825
2826static void isdn_ppp_send_ccp(isdn_net_dev *net_dev, isdn_net_local *lp, struct sk_buff *skb)
2827{
2828 struct ippp_struct *mis,*is;
2829 int proto, slot = lp->ppp_slot;
2830 unsigned char *data;
2831
2832 if(!skb || skb->len < 3)
2833 return;
2834 if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
2835 printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
2836 __FUNCTION__, slot);
2837 return;
2838 }
2839 is = ippp_table[slot];
2840 /* Daemon may send with or without address and control field comp */
2841 data = skb->data;
2842 if(!(is->pppcfg & SC_COMP_AC) && data[0] == 0xff && data[1] == 0x03) {
2843 data += 2;
2844 if(skb->len < 5)
2845 return;
2846 }
2847
2848 proto = ((int)data[0]<<8)+data[1];
2849 if(proto != PPP_CCP && proto != PPP_CCPFRAG)
2850 return;
2851
2852 printk(KERN_DEBUG "Received CCP frame from daemon:\n");
2853 isdn_ppp_frame_log("ccp-xmit", skb->data, skb->len, 32, is->unit,lp->ppp_slot);
2854
2855 if (lp->master) {
2856 slot = ((isdn_net_local *) (lp->master->priv))->ppp_slot;
2857 if (slot < 0 || slot > ISDN_MAX_CHANNELS) {
2858 printk(KERN_ERR "%s: slot(%d) out of range\n",
2859 __FUNCTION__, slot);
2860 return;
2861 }
2862 mis = ippp_table[slot];
2863 } else
2864 mis = is;
2865 if (mis != is)
2866 printk(KERN_DEBUG "isdn_ppp: Ouch! Master CCP sends on slave slot!\n");
2867
2868 switch(data[2]) {
2869 case CCP_CONFREQ:
2870 if(is->debug & 0x10)
2871 printk(KERN_DEBUG "Disable decompression here!\n");
2872 if(proto == PPP_CCP)
2873 is->compflags &= ~SC_DECOMP_ON;
2874 else
2875 is->compflags &= ~SC_LINK_DECOMP_ON;
2876 break;
2877 case CCP_TERMREQ:
2878 case CCP_TERMACK:
2879 if(is->debug & 0x10)
2880 printk(KERN_DEBUG "Disable (de)compression here!\n");
2881 if(proto == PPP_CCP)
2882 is->compflags &= ~(SC_DECOMP_ON|SC_COMP_ON);
2883 else
2884 is->compflags &= ~(SC_LINK_DECOMP_ON|SC_LINK_COMP_ON);
2885 break;
2886 case CCP_CONFACK:
2887 /* if we SEND an ackowledge we can/must enable the compressor */
2888 if(is->debug & 0x10)
2889 printk(KERN_DEBUG "Enable compression here!\n");
2890 if(proto == PPP_CCP) {
2891 if (!is->compressor)
2892 break;
2893 is->compflags |= SC_COMP_ON;
2894 } else {
2895 if (!is->compressor)
2896 break;
2897 is->compflags |= SC_LINK_COMP_ON;
2898 }
2899 break;
2900 case CCP_RESETACK:
2901 /* If we send a ACK we should reset our compressor */
2902 if(is->debug & 0x10)
2903 printk(KERN_DEBUG "Reset decompression state here!\n");
2904 printk(KERN_DEBUG "ResetAck from daemon passed by\n");
2905 if(proto == PPP_CCP) {
2906 /* link to master? */
2907 if(is->compressor && is->comp_stat)
2908 is->compressor->reset(is->comp_stat, 0, 0,
2909 NULL, 0, NULL);
2910 is->compflags &= ~SC_COMP_DISCARD;
2911 }
2912 else {
2913 if(is->link_compressor && is->link_comp_stat)
2914 is->link_compressor->reset(is->link_comp_stat,
2915 0, 0, NULL, 0, NULL);
2916 is->compflags &= ~SC_LINK_COMP_DISCARD;
2917 }
2918 break;
2919 case CCP_RESETREQ:
2920 /* Just let it pass by */
2921 printk(KERN_DEBUG "ResetReq from daemon passed by\n");
2922 break;
2923 }
2924}
2925
2926int isdn_ppp_register_compressor(struct isdn_ppp_compressor *ipc)
2927{
2928 ipc->next = ipc_head;
2929 ipc->prev = NULL;
2930 if(ipc_head) {
2931 ipc_head->prev = ipc;
2932 }
2933 ipc_head = ipc;
2934 return 0;
2935}
2936
2937int isdn_ppp_unregister_compressor(struct isdn_ppp_compressor *ipc)
2938{
2939 if(ipc->prev)
2940 ipc->prev->next = ipc->next;
2941 else
2942 ipc_head = ipc->next;
2943 if(ipc->next)
2944 ipc->next->prev = ipc->prev;
2945 ipc->prev = ipc->next = NULL;
2946 return 0;
2947}
2948
2949static int isdn_ppp_set_compressor(struct ippp_struct *is, struct isdn_ppp_comp_data *data)
2950{
2951 struct isdn_ppp_compressor *ipc = ipc_head;
2952 int ret;
2953 void *stat;
2954 int num = data->num;
2955
2956 if(is->debug & 0x10)
2957 printk(KERN_DEBUG "[%d] Set %s type %d\n",is->unit,
2958 (data->flags&IPPP_COMP_FLAG_XMIT)?"compressor":"decompressor",num);
2959
2960 /* If is has no valid reset state vector, we cannot allocate a
2961 decompressor. The decompressor would cause reset transactions
2962 sooner or later, and they need that vector. */
2963
2964 if(!(data->flags & IPPP_COMP_FLAG_XMIT) && !is->reset) {
2965 printk(KERN_ERR "ippp_ccp: no reset data structure - can't"
2966 " allow decompression.\n");
2967 return -ENOMEM;
2968 }
2969
2970 while(ipc) {
2971 if(ipc->num == num) {
2972 stat = ipc->alloc(data);
2973 if(stat) {
2974 ret = ipc->init(stat,data,is->unit,0);
2975 if(!ret) {
2976 printk(KERN_ERR "Can't init (de)compression!\n");
2977 ipc->free(stat);
2978 stat = NULL;
2979 break;
2980 }
2981 }
2982 else {
2983 printk(KERN_ERR "Can't alloc (de)compression!\n");
2984 break;
2985 }
2986
2987 if(data->flags & IPPP_COMP_FLAG_XMIT) {
2988 if(data->flags & IPPP_COMP_FLAG_LINK) {
2989 if(is->link_comp_stat)
2990 is->link_compressor->free(is->link_comp_stat);
2991 is->link_comp_stat = stat;
2992 is->link_compressor = ipc;
2993 }
2994 else {
2995 if(is->comp_stat)
2996 is->compressor->free(is->comp_stat);
2997 is->comp_stat = stat;
2998 is->compressor = ipc;
2999 }
3000 }
3001 else {
3002 if(data->flags & IPPP_COMP_FLAG_LINK) {
3003 if(is->link_decomp_stat)
3004 is->link_decompressor->free(is->link_decomp_stat);
3005 is->link_decomp_stat = stat;
3006 is->link_decompressor = ipc;
3007 }
3008 else {
3009 if(is->decomp_stat)
3010 is->decompressor->free(is->decomp_stat);
3011 is->decomp_stat = stat;
3012 is->decompressor = ipc;
3013 }
3014 }
3015 return 0;
3016 }
3017 ipc = ipc->next;
3018 }
3019 return -EINVAL;
3020}
diff --git a/drivers/isdn/i4l/isdn_ppp.h b/drivers/isdn/i4l/isdn_ppp.h
new file mode 100644
index 000000000000..8cc05c7ccf78
--- /dev/null
+++ b/drivers/isdn/i4l/isdn_ppp.h
@@ -0,0 +1,43 @@
1/* $Id: isdn_ppp.h,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $
2 *
3 * header for Linux ISDN subsystem, functions for synchronous PPP (linklevel).
4 *
5 * Copyright 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
6 *
7 * This software may be used and distributed according to the terms
8 * of the GNU General Public License, incorporated herein by reference.
9 *
10 */
11
12#include <linux/ppp_defs.h> /* for PPP_PROTOCOL */
13#include <linux/isdn_ppp.h> /* for isdn_ppp info */
14
15extern int isdn_ppp_read(int, struct file *, char __user *, int);
16extern int isdn_ppp_write(int, struct file *, const char __user *, int);
17extern int isdn_ppp_open(int, struct file *);
18extern int isdn_ppp_init(void);
19extern void isdn_ppp_cleanup(void);
20extern int isdn_ppp_free(isdn_net_local *);
21extern int isdn_ppp_bind(isdn_net_local *);
22extern int isdn_ppp_autodial_filter(struct sk_buff *, isdn_net_local *);
23extern int isdn_ppp_xmit(struct sk_buff *, struct net_device *);
24extern void isdn_ppp_receive(isdn_net_dev *, isdn_net_local *, struct sk_buff *);
25extern int isdn_ppp_dev_ioctl(struct net_device *, struct ifreq *, int);
26extern unsigned int isdn_ppp_poll(struct file *, struct poll_table_struct *);
27extern int isdn_ppp_ioctl(int, struct file *, unsigned int, unsigned long);
28extern void isdn_ppp_release(int, struct file *);
29extern int isdn_ppp_dial_slave(char *);
30extern void isdn_ppp_wakeup_daemon(isdn_net_local *);
31
32extern int isdn_ppp_register_compressor(struct isdn_ppp_compressor *ipc);
33extern int isdn_ppp_unregister_compressor(struct isdn_ppp_compressor *ipc);
34
35#define IPPP_OPEN 0x01
36#define IPPP_CONNECT 0x02
37#define IPPP_CLOSEWAIT 0x04
38#define IPPP_NOBLOCK 0x08
39#define IPPP_ASSIGNED 0x10
40
41#define IPPP_MAX_HEADER 10
42
43
diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c
new file mode 100644
index 000000000000..e21007eca0f0
--- /dev/null
+++ b/drivers/isdn/i4l/isdn_tty.c
@@ -0,0 +1,3911 @@
1/* $Id: isdn_tty.c,v 1.1.2.3 2004/02/10 01:07:13 keil Exp $
2 *
3 * Linux ISDN subsystem, tty functions and AT-command emulator (linklevel).
4 *
5 * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de)
6 * Copyright 1995,96 by Thinking Objects Software GmbH Wuerzburg
7 *
8 * This software may be used and distributed according to the terms
9 * of the GNU General Public License, incorporated herein by reference.
10 *
11 */
12#undef ISDN_TTY_STAT_DEBUG
13
14#include <linux/config.h>
15#include <linux/isdn.h>
16#include <linux/delay.h>
17#include "isdn_common.h"
18#include "isdn_tty.h"
19#ifdef CONFIG_ISDN_AUDIO
20#include "isdn_audio.h"
21#define VBUF 0x3e0
22#define VBUFX (VBUF/16)
23#endif
24
25#define FIX_FILE_TRANSFER
26#define DUMMY_HAYES_AT
27
28/* Prototypes */
29
30static int isdn_tty_edit_at(const char *, int, modem_info *);
31static void isdn_tty_check_esc(const u_char *, u_char, int, int *, u_long *);
32static void isdn_tty_modem_reset_regs(modem_info *, int);
33static void isdn_tty_cmd_ATA(modem_info *);
34static void isdn_tty_flush_buffer(struct tty_struct *);
35static void isdn_tty_modem_result(int, modem_info *);
36#ifdef CONFIG_ISDN_AUDIO
37static int isdn_tty_countDLE(unsigned char *, int);
38#endif
39
40/* Leave this unchanged unless you know what you do! */
41#define MODEM_PARANOIA_CHECK
42#define MODEM_DO_RESTART
43
44static int bit2si[8] =
45{1, 5, 7, 7, 7, 7, 7, 7};
46static int si2bit[8] =
47{4, 1, 4, 4, 4, 4, 4, 4};
48
49char *isdn_tty_revision = "$Revision: 1.1.2.3 $";
50
51
52/* isdn_tty_try_read() is called from within isdn_tty_rcv_skb()
53 * to stuff incoming data directly into a tty's flip-buffer. This
54 * is done to speed up tty-receiving if the receive-queue is empty.
55 * This routine MUST be called with interrupts off.
56 * Return:
57 * 1 = Success
58 * 0 = Failure, data has to be buffered and later processed by
59 * isdn_tty_readmodem().
60 */
61static int
62isdn_tty_try_read(modem_info * info, struct sk_buff *skb)
63{
64 int c;
65 int len;
66 struct tty_struct *tty;
67
68 if (info->online) {
69 if ((tty = info->tty)) {
70 if (info->mcr & UART_MCR_RTS) {
71 c = TTY_FLIPBUF_SIZE - tty->flip.count;
72 len = skb->len
73#ifdef CONFIG_ISDN_AUDIO
74 + ISDN_AUDIO_SKB_DLECOUNT(skb)
75#endif
76 ;
77 if (c >= len) {
78#ifdef CONFIG_ISDN_AUDIO
79 if (ISDN_AUDIO_SKB_DLECOUNT(skb))
80 while (skb->len--) {
81 if (*skb->data == DLE)
82 tty_insert_flip_char(tty, DLE, 0);
83 tty_insert_flip_char(tty, *skb->data++, 0);
84 } else {
85#endif
86 memcpy(tty->flip.char_buf_ptr,
87 skb->data, len);
88 tty->flip.count += len;
89 tty->flip.char_buf_ptr += len;
90 memset(tty->flip.flag_buf_ptr, 0, len);
91 tty->flip.flag_buf_ptr += len;
92#ifdef CONFIG_ISDN_AUDIO
93 }
94#endif
95 if (info->emu.mdmreg[REG_CPPP] & BIT_CPPP)
96 tty->flip.flag_buf_ptr[len - 1] = 0xff;
97 schedule_delayed_work(&tty->flip.work, 1);
98 kfree_skb(skb);
99 return 1;
100 }
101 }
102 }
103 }
104 return 0;
105}
106
107/* isdn_tty_readmodem() is called periodically from within timer-interrupt.
108 * It tries getting received data from the receive queue an stuff it into
109 * the tty's flip-buffer.
110 */
111void
112isdn_tty_readmodem(void)
113{
114 int resched = 0;
115 int midx;
116 int i;
117 int c;
118 int r;
119 struct tty_struct *tty;
120 modem_info *info;
121
122 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
123 if ((midx = dev->m_idx[i]) >= 0) {
124 info = &dev->mdm.info[midx];
125 if (info->online) {
126 r = 0;
127#ifdef CONFIG_ISDN_AUDIO
128 isdn_audio_eval_dtmf(info);
129 if ((info->vonline & 1) && (info->emu.vpar[1]))
130 isdn_audio_eval_silence(info);
131#endif
132 if ((tty = info->tty)) {
133 if (info->mcr & UART_MCR_RTS) {
134 c = TTY_FLIPBUF_SIZE - tty->flip.count;
135 if (c > 0) {
136 r = isdn_readbchan(info->isdn_driver, info->isdn_channel,
137 tty->flip.char_buf_ptr,
138 tty->flip.flag_buf_ptr, c, NULL);
139 /* CISCO AsyncPPP Hack */
140 if (!(info->emu.mdmreg[REG_CPPP] & BIT_CPPP))
141 memset(tty->flip.flag_buf_ptr, 0, r);
142 tty->flip.count += r;
143 tty->flip.flag_buf_ptr += r;
144 tty->flip.char_buf_ptr += r;
145 if (r)
146 schedule_delayed_work(&tty->flip.work, 1);
147 }
148 } else
149 r = 1;
150 } else
151 r = 1;
152 if (r) {
153 info->rcvsched = 0;
154 resched = 1;
155 } else
156 info->rcvsched = 1;
157 }
158 }
159 }
160 if (!resched)
161 isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 0);
162}
163
164int
165isdn_tty_rcv_skb(int i, int di, int channel, struct sk_buff *skb)
166{
167 ulong flags;
168 int midx;
169#ifdef CONFIG_ISDN_AUDIO
170 int ifmt;
171#endif
172 modem_info *info;
173
174 if ((midx = dev->m_idx[i]) < 0) {
175 /* if midx is invalid, packet is not for tty */
176 return 0;
177 }
178 info = &dev->mdm.info[midx];
179#ifdef CONFIG_ISDN_AUDIO
180 ifmt = 1;
181
182 if ((info->vonline) && (!info->emu.vpar[4]))
183 isdn_audio_calc_dtmf(info, skb->data, skb->len, ifmt);
184 if ((info->vonline & 1) && (info->emu.vpar[1]))
185 isdn_audio_calc_silence(info, skb->data, skb->len, ifmt);
186#endif
187 if ((info->online < 2)
188#ifdef CONFIG_ISDN_AUDIO
189 && (!(info->vonline & 1))
190#endif
191 ) {
192 /* If Modem not listening, drop data */
193 kfree_skb(skb);
194 return 1;
195 }
196 if (info->emu.mdmreg[REG_T70] & BIT_T70) {
197 if (info->emu.mdmreg[REG_T70] & BIT_T70_EXT) {
198 /* T.70 decoding: throw away the T.70 header (2 or 4 bytes) */
199 if (skb->data[0] == 3) /* pure data packet -> 4 byte headers */
200 skb_pull(skb, 4);
201 else
202 if (skb->data[0] == 1) /* keepalive packet -> 2 byte hdr */
203 skb_pull(skb, 2);
204 } else
205 /* T.70 decoding: Simply throw away the T.70 header (4 bytes) */
206 if ((skb->data[0] == 1) && ((skb->data[1] == 0) || (skb->data[1] == 1)))
207 skb_pull(skb, 4);
208 }
209#ifdef CONFIG_ISDN_AUDIO
210 ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;
211 ISDN_AUDIO_SKB_LOCK(skb) = 0;
212 if (info->vonline & 1) {
213 /* voice conversion/compression */
214 switch (info->emu.vpar[3]) {
215 case 2:
216 case 3:
217 case 4:
218 /* adpcm
219 * Since compressed data takes less
220 * space, we can overwrite the buffer.
221 */
222 skb_trim(skb, isdn_audio_xlaw2adpcm(info->adpcmr,
223 ifmt,
224 skb->data,
225 skb->data,
226 skb->len));
227 break;
228 case 5:
229 /* a-law */
230 if (!ifmt)
231 isdn_audio_ulaw2alaw(skb->data, skb->len);
232 break;
233 case 6:
234 /* u-law */
235 if (ifmt)
236 isdn_audio_alaw2ulaw(skb->data, skb->len);
237 break;
238 }
239 ISDN_AUDIO_SKB_DLECOUNT(skb) =
240 isdn_tty_countDLE(skb->data, skb->len);
241 }
242#ifdef CONFIG_ISDN_TTY_FAX
243 else {
244 if (info->faxonline & 2) {
245 isdn_tty_fax_bitorder(info, skb);
246 ISDN_AUDIO_SKB_DLECOUNT(skb) =
247 isdn_tty_countDLE(skb->data, skb->len);
248 }
249 }
250#endif
251#endif
252 /* Try to deliver directly via tty-flip-buf if queue is empty */
253 spin_lock_irqsave(&info->readlock, flags);
254 if (skb_queue_empty(&dev->drv[di]->rpqueue[channel]))
255 if (isdn_tty_try_read(info, skb)) {
256 spin_unlock_irqrestore(&info->readlock, flags);
257 return 1;
258 }
259 /* Direct deliver failed or queue wasn't empty.
260 * Queue up for later dequeueing via timer-irq.
261 */
262 __skb_queue_tail(&dev->drv[di]->rpqueue[channel], skb);
263 dev->drv[di]->rcvcount[channel] +=
264 (skb->len
265#ifdef CONFIG_ISDN_AUDIO
266 + ISDN_AUDIO_SKB_DLECOUNT(skb)
267#endif
268 );
269 spin_unlock_irqrestore(&info->readlock, flags);
270 /* Schedule dequeuing */
271 if ((dev->modempoll) && (info->rcvsched))
272 isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
273 return 1;
274}
275
276void
277isdn_tty_cleanup_xmit(modem_info * info)
278{
279 skb_queue_purge(&info->xmit_queue);
280#ifdef CONFIG_ISDN_AUDIO
281 skb_queue_purge(&info->dtmf_queue);
282#endif
283}
284
285static void
286isdn_tty_tint(modem_info * info)
287{
288 struct sk_buff *skb = skb_dequeue(&info->xmit_queue);
289 int len, slen;
290
291 if (!skb)
292 return;
293 len = skb->len;
294 if ((slen = isdn_writebuf_skb_stub(info->isdn_driver,
295 info->isdn_channel, 1, skb)) == len) {
296 struct tty_struct *tty = info->tty;
297 info->send_outstanding++;
298 info->msr &= ~UART_MSR_CTS;
299 info->lsr &= ~UART_LSR_TEMT;
300 tty_wakeup(tty);
301 return;
302 }
303 if (slen < 0) {
304 /* Error: no channel, already shutdown, or wrong parameter */
305 dev_kfree_skb(skb);
306 return;
307 }
308 skb_queue_head(&info->xmit_queue, skb);
309}
310
311#ifdef CONFIG_ISDN_AUDIO
312static int
313isdn_tty_countDLE(unsigned char *buf, int len)
314{
315 int count = 0;
316
317 while (len--)
318 if (*buf++ == DLE)
319 count++;
320 return count;
321}
322
323/* This routine is called from within isdn_tty_write() to perform
324 * DLE-decoding when sending audio-data.
325 */
326static int
327isdn_tty_handleDLEdown(modem_info * info, atemu * m, int len)
328{
329 unsigned char *p = &info->xmit_buf[info->xmit_count];
330 int count = 0;
331
332 while (len > 0) {
333 if (m->lastDLE) {
334 m->lastDLE = 0;
335 switch (*p) {
336 case DLE:
337 /* Escape code */
338 if (len > 1)
339 memmove(p, p + 1, len - 1);
340 p--;
341 count++;
342 break;
343 case ETX:
344 /* End of data */
345 info->vonline |= 4;
346 return count;
347 case DC4:
348 /* Abort RX */
349 info->vonline &= ~1;
350#ifdef ISDN_DEBUG_MODEM_VOICE
351 printk(KERN_DEBUG
352 "DLEdown: got DLE-DC4, send DLE-ETX on ttyI%d\n",
353 info->line);
354#endif
355 isdn_tty_at_cout("\020\003", info);
356 if (!info->vonline) {
357#ifdef ISDN_DEBUG_MODEM_VOICE
358 printk(KERN_DEBUG
359 "DLEdown: send VCON on ttyI%d\n",
360 info->line);
361#endif
362 isdn_tty_at_cout("\r\nVCON\r\n", info);
363 }
364 /* Fall through */
365 case 'q':
366 case 's':
367 /* Silence */
368 if (len > 1)
369 memmove(p, p + 1, len - 1);
370 p--;
371 break;
372 }
373 } else {
374 if (*p == DLE)
375 m->lastDLE = 1;
376 else
377 count++;
378 }
379 p++;
380 len--;
381 }
382 if (len < 0) {
383 printk(KERN_WARNING "isdn_tty: len<0 in DLEdown\n");
384 return 0;
385 }
386 return count;
387}
388
389/* This routine is called from within isdn_tty_write() when receiving
390 * audio-data. It interrupts receiving, if an character other than
391 * ^S or ^Q is sent.
392 */
393static int
394isdn_tty_end_vrx(const char *buf, int c)
395{
396 char ch;
397
398 while (c--) {
399 ch = *buf;
400 if ((ch != 0x11) && (ch != 0x13))
401 return 1;
402 buf++;
403 }
404 return 0;
405}
406
407static int voice_cf[7] =
408{0, 0, 4, 3, 2, 0, 0};
409
410#endif /* CONFIG_ISDN_AUDIO */
411
412/* isdn_tty_senddown() is called either directly from within isdn_tty_write()
413 * or via timer-interrupt from within isdn_tty_modem_xmit(). It pulls
414 * outgoing data from the tty's xmit-buffer, handles voice-decompression or
415 * T.70 if necessary, and finally queues it up for sending via isdn_tty_tint.
416 */
417static void
418isdn_tty_senddown(modem_info * info)
419{
420 int buflen;
421 int skb_res;
422#ifdef CONFIG_ISDN_AUDIO
423 int audio_len;
424#endif
425 struct sk_buff *skb;
426
427#ifdef CONFIG_ISDN_AUDIO
428 if (info->vonline & 4) {
429 info->vonline &= ~6;
430 if (!info->vonline) {
431#ifdef ISDN_DEBUG_MODEM_VOICE
432 printk(KERN_DEBUG
433 "senddown: send VCON on ttyI%d\n",
434 info->line);
435#endif
436 isdn_tty_at_cout("\r\nVCON\r\n", info);
437 }
438 }
439#endif
440 if (!(buflen = info->xmit_count))
441 return;
442 if ((info->emu.mdmreg[REG_CTS] & BIT_CTS) != 0)
443 info->msr &= ~UART_MSR_CTS;
444 info->lsr &= ~UART_LSR_TEMT;
445 /* info->xmit_count is modified here and in isdn_tty_write().
446 * So we return here if isdn_tty_write() is in the
447 * critical section.
448 */
449 atomic_inc(&info->xmit_lock);
450 if (!(atomic_dec_and_test(&info->xmit_lock)))
451 return;
452 if (info->isdn_driver < 0) {
453 info->xmit_count = 0;
454 return;
455 }
456 skb_res = dev->drv[info->isdn_driver]->interface->hl_hdrlen + 4;
457#ifdef CONFIG_ISDN_AUDIO
458 if (info->vonline & 2)
459 audio_len = buflen * voice_cf[info->emu.vpar[3]];
460 else
461 audio_len = 0;
462 skb = dev_alloc_skb(skb_res + buflen + audio_len);
463#else
464 skb = dev_alloc_skb(skb_res + buflen);
465#endif
466 if (!skb) {
467 printk(KERN_WARNING
468 "isdn_tty: Out of memory in ttyI%d senddown\n",
469 info->line);
470 return;
471 }
472 skb_reserve(skb, skb_res);
473 memcpy(skb_put(skb, buflen), info->xmit_buf, buflen);
474 info->xmit_count = 0;
475#ifdef CONFIG_ISDN_AUDIO
476 if (info->vonline & 2) {
477 /* For now, ifmt is fixed to 1 (alaw), since this
478 * is used with ISDN everywhere in the world, except
479 * US, Canada and Japan.
480 * Later, when US-ISDN protocols are implemented,
481 * this setting will depend on the D-channel protocol.
482 */
483 int ifmt = 1;
484
485 /* voice conversion/decompression */
486 switch (info->emu.vpar[3]) {
487 case 2:
488 case 3:
489 case 4:
490 /* adpcm, compatible to ZyXel 1496 modem
491 * with ROM revision 6.01
492 */
493 audio_len = isdn_audio_adpcm2xlaw(info->adpcms,
494 ifmt,
495 skb->data,
496 skb_put(skb, audio_len),
497 buflen);
498 skb_pull(skb, buflen);
499 skb_trim(skb, audio_len);
500 break;
501 case 5:
502 /* a-law */
503 if (!ifmt)
504 isdn_audio_alaw2ulaw(skb->data,
505 buflen);
506 break;
507 case 6:
508 /* u-law */
509 if (ifmt)
510 isdn_audio_ulaw2alaw(skb->data,
511 buflen);
512 break;
513 }
514 }
515#endif /* CONFIG_ISDN_AUDIO */
516 if (info->emu.mdmreg[REG_T70] & BIT_T70) {
517 /* Add T.70 simplified header */
518 if (info->emu.mdmreg[REG_T70] & BIT_T70_EXT)
519 memcpy(skb_push(skb, 2), "\1\0", 2);
520 else
521 memcpy(skb_push(skb, 4), "\1\0\1\0", 4);
522 }
523 skb_queue_tail(&info->xmit_queue, skb);
524}
525
526/************************************************************
527 *
528 * Modem-functions
529 *
530 * mostly "stolen" from original Linux-serial.c and friends.
531 *
532 ************************************************************/
533
534/* The next routine is called once from within timer-interrupt
535 * triggered within isdn_tty_modem_ncarrier(). It calls
536 * isdn_tty_modem_result() to stuff a "NO CARRIER" Message
537 * into the tty's flip-buffer.
538 */
539static void
540isdn_tty_modem_do_ncarrier(unsigned long data)
541{
542 modem_info *info = (modem_info *) data;
543 isdn_tty_modem_result(RESULT_NO_CARRIER, info);
544}
545
546/* Next routine is called, whenever the DTR-signal is raised.
547 * It checks the ncarrier-flag, and triggers the above routine
548 * when necessary. The ncarrier-flag is set, whenever DTR goes
549 * low.
550 */
551static void
552isdn_tty_modem_ncarrier(modem_info * info)
553{
554 if (info->ncarrier) {
555 info->nc_timer.expires = jiffies + HZ;
556 add_timer(&info->nc_timer);
557 }
558}
559
560/*
561 * return the usage calculated by si and layer 2 protocol
562 */
563int
564isdn_calc_usage(int si, int l2)
565{
566 int usg = ISDN_USAGE_MODEM;
567
568#ifdef CONFIG_ISDN_AUDIO
569 if (si == 1) {
570 switch(l2) {
571 case ISDN_PROTO_L2_MODEM:
572 usg = ISDN_USAGE_MODEM;
573 break;
574#ifdef CONFIG_ISDN_TTY_FAX
575 case ISDN_PROTO_L2_FAX:
576 usg = ISDN_USAGE_FAX;
577 break;
578#endif
579 case ISDN_PROTO_L2_TRANS:
580 default:
581 usg = ISDN_USAGE_VOICE;
582 break;
583 }
584 }
585#endif
586 return(usg);
587}
588
589/* isdn_tty_dial() performs dialing of a tty an the necessary
590 * setup of the lower levels before that.
591 */
592static void
593isdn_tty_dial(char *n, modem_info * info, atemu * m)
594{
595 int usg = ISDN_USAGE_MODEM;
596 int si = 7;
597 int l2 = m->mdmreg[REG_L2PROT];
598 u_long flags;
599 isdn_ctrl cmd;
600 int i;
601 int j;
602
603 for (j = 7; j >= 0; j--)
604 if (m->mdmreg[REG_SI1] & (1 << j)) {
605 si = bit2si[j];
606 break;
607 }
608 usg = isdn_calc_usage(si, l2);
609#ifdef CONFIG_ISDN_AUDIO
610 if ((si == 1) &&
611 (l2 != ISDN_PROTO_L2_MODEM)
612#ifdef CONFIG_ISDN_TTY_FAX
613 && (l2 != ISDN_PROTO_L2_FAX)
614#endif
615 ) {
616 l2 = ISDN_PROTO_L2_TRANS;
617 usg = ISDN_USAGE_VOICE;
618 }
619#endif
620 m->mdmreg[REG_SI1I] = si2bit[si];
621 spin_lock_irqsave(&dev->lock, flags);
622 i = isdn_get_free_channel(usg, l2, m->mdmreg[REG_L3PROT], -1, -1, m->msn);
623 if (i < 0) {
624 spin_unlock_irqrestore(&dev->lock, flags);
625 isdn_tty_modem_result(RESULT_NO_DIALTONE, info);
626 } else {
627 info->isdn_driver = dev->drvmap[i];
628 info->isdn_channel = dev->chanmap[i];
629 info->drv_index = i;
630 dev->m_idx[i] = info->line;
631 dev->usage[i] |= ISDN_USAGE_OUTGOING;
632 info->last_dir = 1;
633 strcpy(info->last_num, n);
634 isdn_info_update();
635 spin_unlock_irqrestore(&dev->lock, flags);
636 cmd.driver = info->isdn_driver;
637 cmd.arg = info->isdn_channel;
638 cmd.command = ISDN_CMD_CLREAZ;
639 isdn_command(&cmd);
640 strcpy(cmd.parm.num, isdn_map_eaz2msn(m->msn, info->isdn_driver));
641 cmd.driver = info->isdn_driver;
642 cmd.command = ISDN_CMD_SETEAZ;
643 isdn_command(&cmd);
644 cmd.driver = info->isdn_driver;
645 cmd.command = ISDN_CMD_SETL2;
646 info->last_l2 = l2;
647 cmd.arg = info->isdn_channel + (l2 << 8);
648 isdn_command(&cmd);
649 cmd.driver = info->isdn_driver;
650 cmd.command = ISDN_CMD_SETL3;
651 cmd.arg = info->isdn_channel + (m->mdmreg[REG_L3PROT] << 8);
652#ifdef CONFIG_ISDN_TTY_FAX
653 if (l2 == ISDN_PROTO_L2_FAX) {
654 cmd.parm.fax = info->fax;
655 info->fax->direction = ISDN_TTY_FAX_CONN_OUT;
656 }
657#endif
658 isdn_command(&cmd);
659 cmd.driver = info->isdn_driver;
660 cmd.arg = info->isdn_channel;
661 sprintf(cmd.parm.setup.phone, "%s", n);
662 sprintf(cmd.parm.setup.eazmsn, "%s",
663 isdn_map_eaz2msn(m->msn, info->isdn_driver));
664 cmd.parm.setup.si1 = si;
665 cmd.parm.setup.si2 = m->mdmreg[REG_SI2];
666 cmd.command = ISDN_CMD_DIAL;
667 info->dialing = 1;
668 info->emu.carrierwait = 0;
669 strcpy(dev->num[i], n);
670 isdn_info_update();
671 isdn_command(&cmd);
672 isdn_timer_ctrl(ISDN_TIMER_CARRIER, 1);
673 }
674}
675
676/* isdn_tty_hangup() disassociates a tty from the real
677 * ISDN-line (hangup). The usage-status is cleared
678 * and some cleanup is done also.
679 */
680void
681isdn_tty_modem_hup(modem_info * info, int local)
682{
683 isdn_ctrl cmd;
684 int di, ch;
685
686 if (!info)
687 return;
688
689 di = info->isdn_driver;
690 ch = info->isdn_channel;
691 if (di < 0 || ch < 0)
692 return;
693
694 info->isdn_driver = -1;
695 info->isdn_channel = -1;
696
697#ifdef ISDN_DEBUG_MODEM_HUP
698 printk(KERN_DEBUG "Mhup ttyI%d\n", info->line);
699#endif
700 info->rcvsched = 0;
701 isdn_tty_flush_buffer(info->tty);
702 if (info->online) {
703 info->last_lhup = local;
704 info->online = 0;
705 isdn_tty_modem_result(RESULT_NO_CARRIER, info);
706 }
707#ifdef CONFIG_ISDN_AUDIO
708 info->vonline = 0;
709#ifdef CONFIG_ISDN_TTY_FAX
710 info->faxonline = 0;
711 info->fax->phase = ISDN_FAX_PHASE_IDLE;
712#endif
713 info->emu.vpar[4] = 0;
714 info->emu.vpar[5] = 8;
715 if (info->dtmf_state) {
716 kfree(info->dtmf_state);
717 info->dtmf_state = NULL;
718 }
719 if (info->silence_state) {
720 kfree(info->silence_state);
721 info->silence_state = NULL;
722 }
723 if (info->adpcms) {
724 kfree(info->adpcms);
725 info->adpcms = NULL;
726 }
727 if (info->adpcmr) {
728 kfree(info->adpcmr);
729 info->adpcmr = NULL;
730 }
731#endif
732 if ((info->msr & UART_MSR_RI) &&
733 (info->emu.mdmreg[REG_RUNG] & BIT_RUNG))
734 isdn_tty_modem_result(RESULT_RUNG, info);
735 info->msr &= ~(UART_MSR_DCD | UART_MSR_RI);
736 info->lsr |= UART_LSR_TEMT;
737
738 if (local) {
739 cmd.driver = di;
740 cmd.command = ISDN_CMD_HANGUP;
741 cmd.arg = ch;
742 isdn_command(&cmd);
743 }
744
745 isdn_all_eaz(di, ch);
746 info->emu.mdmreg[REG_RINGCNT] = 0;
747 isdn_free_channel(di, ch, 0);
748
749 if (info->drv_index >= 0) {
750 dev->m_idx[info->drv_index] = -1;
751 info->drv_index = -1;
752 }
753}
754
755/*
756 * Begin of a CAPI like interface, currently used only for
757 * supplementary service (CAPI 2.0 part III)
758 */
759#include <linux/isdn/capicmd.h>
760
761int
762isdn_tty_capi_facility(capi_msg *cm) {
763 return(-1); /* dummy */
764}
765
766/* isdn_tty_suspend() tries to suspend the current tty connection
767 */
768static void
769isdn_tty_suspend(char *id, modem_info * info, atemu * m)
770{
771 isdn_ctrl cmd;
772
773 int l;
774
775 if (!info)
776 return;
777
778#ifdef ISDN_DEBUG_MODEM_SERVICES
779 printk(KERN_DEBUG "Msusp ttyI%d\n", info->line);
780#endif
781 l = strlen(id);
782 if ((info->isdn_driver >= 0)) {
783 cmd.parm.cmsg.Length = l+18;
784 cmd.parm.cmsg.Command = CAPI_FACILITY;
785 cmd.parm.cmsg.Subcommand = CAPI_REQ;
786 cmd.parm.cmsg.adr.Controller = info->isdn_driver + 1;
787 cmd.parm.cmsg.para[0] = 3; /* 16 bit 0x0003 suplementary service */
788 cmd.parm.cmsg.para[1] = 0;
789 cmd.parm.cmsg.para[2] = l + 3;
790 cmd.parm.cmsg.para[3] = 4; /* 16 bit 0x0004 Suspend */
791 cmd.parm.cmsg.para[4] = 0;
792 cmd.parm.cmsg.para[5] = l;
793 strncpy(&cmd.parm.cmsg.para[6], id, l);
794 cmd.command = CAPI_PUT_MESSAGE;
795 cmd.driver = info->isdn_driver;
796 cmd.arg = info->isdn_channel;
797 isdn_command(&cmd);
798 }
799}
800
801/* isdn_tty_resume() tries to resume a suspended call
802 * setup of the lower levels before that. unfortunatly here is no
803 * checking for compatibility of used protocols implemented by Q931
804 * It does the same things like isdn_tty_dial, the last command
805 * is different, may be we can merge it.
806 */
807
808static void
809isdn_tty_resume(char *id, modem_info * info, atemu * m)
810{
811 int usg = ISDN_USAGE_MODEM;
812 int si = 7;
813 int l2 = m->mdmreg[REG_L2PROT];
814 isdn_ctrl cmd;
815 ulong flags;
816 int i;
817 int j;
818 int l;
819
820 l = strlen(id);
821 for (j = 7; j >= 0; j--)
822 if (m->mdmreg[REG_SI1] & (1 << j)) {
823 si = bit2si[j];
824 break;
825 }
826 usg = isdn_calc_usage(si, l2);
827#ifdef CONFIG_ISDN_AUDIO
828 if ((si == 1) &&
829 (l2 != ISDN_PROTO_L2_MODEM)
830#ifdef CONFIG_ISDN_TTY_FAX
831 && (l2 != ISDN_PROTO_L2_FAX)
832#endif
833 ) {
834 l2 = ISDN_PROTO_L2_TRANS;
835 usg = ISDN_USAGE_VOICE;
836 }
837#endif
838 m->mdmreg[REG_SI1I] = si2bit[si];
839 spin_lock_irqsave(&dev->lock, flags);
840 i = isdn_get_free_channel(usg, l2, m->mdmreg[REG_L3PROT], -1, -1, m->msn);
841 if (i < 0) {
842 spin_unlock_irqrestore(&dev->lock, flags);
843 isdn_tty_modem_result(RESULT_NO_DIALTONE, info);
844 } else {
845 info->isdn_driver = dev->drvmap[i];
846 info->isdn_channel = dev->chanmap[i];
847 info->drv_index = i;
848 dev->m_idx[i] = info->line;
849 dev->usage[i] |= ISDN_USAGE_OUTGOING;
850 info->last_dir = 1;
851// strcpy(info->last_num, n);
852 isdn_info_update();
853 spin_unlock_irqrestore(&dev->lock, flags);
854 cmd.driver = info->isdn_driver;
855 cmd.arg = info->isdn_channel;
856 cmd.command = ISDN_CMD_CLREAZ;
857 isdn_command(&cmd);
858 strcpy(cmd.parm.num, isdn_map_eaz2msn(m->msn, info->isdn_driver));
859 cmd.driver = info->isdn_driver;
860 cmd.command = ISDN_CMD_SETEAZ;
861 isdn_command(&cmd);
862 cmd.driver = info->isdn_driver;
863 cmd.command = ISDN_CMD_SETL2;
864 info->last_l2 = l2;
865 cmd.arg = info->isdn_channel + (l2 << 8);
866 isdn_command(&cmd);
867 cmd.driver = info->isdn_driver;
868 cmd.command = ISDN_CMD_SETL3;
869 cmd.arg = info->isdn_channel + (m->mdmreg[REG_L3PROT] << 8);
870 isdn_command(&cmd);
871 cmd.driver = info->isdn_driver;
872 cmd.arg = info->isdn_channel;
873 cmd.parm.cmsg.Length = l+18;
874 cmd.parm.cmsg.Command = CAPI_FACILITY;
875 cmd.parm.cmsg.Subcommand = CAPI_REQ;
876 cmd.parm.cmsg.adr.Controller = info->isdn_driver + 1;
877 cmd.parm.cmsg.para[0] = 3; /* 16 bit 0x0003 suplementary service */
878 cmd.parm.cmsg.para[1] = 0;
879 cmd.parm.cmsg.para[2] = l+3;
880 cmd.parm.cmsg.para[3] = 5; /* 16 bit 0x0005 Resume */
881 cmd.parm.cmsg.para[4] = 0;
882 cmd.parm.cmsg.para[5] = l;
883 strncpy(&cmd.parm.cmsg.para[6], id, l);
884 cmd.command =CAPI_PUT_MESSAGE;
885 info->dialing = 1;
886// strcpy(dev->num[i], n);
887 isdn_info_update();
888 isdn_command(&cmd);
889 isdn_timer_ctrl(ISDN_TIMER_CARRIER, 1);
890 }
891}
892
893/* isdn_tty_send_msg() sends a message to a HL driver
894 * This is used for hybrid modem cards to send AT commands to it
895 */
896
897static void
898isdn_tty_send_msg(modem_info * info, atemu * m, char *msg)
899{
900 int usg = ISDN_USAGE_MODEM;
901 int si = 7;
902 int l2 = m->mdmreg[REG_L2PROT];
903 isdn_ctrl cmd;
904 ulong flags;
905 int i;
906 int j;
907 int l;
908
909 l = strlen(msg);
910 if (!l) {
911 isdn_tty_modem_result(RESULT_ERROR, info);
912 return;
913 }
914 for (j = 7; j >= 0; j--)
915 if (m->mdmreg[REG_SI1] & (1 << j)) {
916 si = bit2si[j];
917 break;
918 }
919 usg = isdn_calc_usage(si, l2);
920#ifdef CONFIG_ISDN_AUDIO
921 if ((si == 1) &&
922 (l2 != ISDN_PROTO_L2_MODEM)
923#ifdef CONFIG_ISDN_TTY_FAX
924 && (l2 != ISDN_PROTO_L2_FAX)
925#endif
926 ) {
927 l2 = ISDN_PROTO_L2_TRANS;
928 usg = ISDN_USAGE_VOICE;
929 }
930#endif
931 m->mdmreg[REG_SI1I] = si2bit[si];
932 spin_lock_irqsave(&dev->lock, flags);
933 i = isdn_get_free_channel(usg, l2, m->mdmreg[REG_L3PROT], -1, -1, m->msn);
934 if (i < 0) {
935 spin_unlock_irqrestore(&dev->lock, flags);
936 isdn_tty_modem_result(RESULT_NO_DIALTONE, info);
937 } else {
938 info->isdn_driver = dev->drvmap[i];
939 info->isdn_channel = dev->chanmap[i];
940 info->drv_index = i;
941 dev->m_idx[i] = info->line;
942 dev->usage[i] |= ISDN_USAGE_OUTGOING;
943 info->last_dir = 1;
944 isdn_info_update();
945 spin_unlock_irqrestore(&dev->lock, flags);
946 cmd.driver = info->isdn_driver;
947 cmd.arg = info->isdn_channel;
948 cmd.command = ISDN_CMD_CLREAZ;
949 isdn_command(&cmd);
950 strcpy(cmd.parm.num, isdn_map_eaz2msn(m->msn, info->isdn_driver));
951 cmd.driver = info->isdn_driver;
952 cmd.command = ISDN_CMD_SETEAZ;
953 isdn_command(&cmd);
954 cmd.driver = info->isdn_driver;
955 cmd.command = ISDN_CMD_SETL2;
956 info->last_l2 = l2;
957 cmd.arg = info->isdn_channel + (l2 << 8);
958 isdn_command(&cmd);
959 cmd.driver = info->isdn_driver;
960 cmd.command = ISDN_CMD_SETL3;
961 cmd.arg = info->isdn_channel + (m->mdmreg[REG_L3PROT] << 8);
962 isdn_command(&cmd);
963 cmd.driver = info->isdn_driver;
964 cmd.arg = info->isdn_channel;
965 cmd.parm.cmsg.Length = l+14;
966 cmd.parm.cmsg.Command = CAPI_MANUFACTURER;
967 cmd.parm.cmsg.Subcommand = CAPI_REQ;
968 cmd.parm.cmsg.adr.Controller = info->isdn_driver + 1;
969 cmd.parm.cmsg.para[0] = l+1;
970 strncpy(&cmd.parm.cmsg.para[1], msg, l);
971 cmd.parm.cmsg.para[l+1] = 0xd;
972 cmd.command =CAPI_PUT_MESSAGE;
973/* info->dialing = 1;
974 strcpy(dev->num[i], n);
975 isdn_info_update();
976*/
977 isdn_command(&cmd);
978 }
979}
980
981static inline int
982isdn_tty_paranoia_check(modem_info *info, char *name, const char *routine)
983{
984#ifdef MODEM_PARANOIA_CHECK
985 if (!info) {
986 printk(KERN_WARNING "isdn_tty: null info_struct for %s in %s\n",
987 name, routine);
988 return 1;
989 }
990 if (info->magic != ISDN_ASYNC_MAGIC) {
991 printk(KERN_WARNING "isdn_tty: bad magic for modem struct %s in %s\n",
992 name, routine);
993 return 1;
994 }
995#endif
996 return 0;
997}
998
999/*
1000 * This routine is called to set the UART divisor registers to match
1001 * the specified baud rate for a serial port.
1002 */
1003static void
1004isdn_tty_change_speed(modem_info * info)
1005{
1006 uint cflag,
1007 cval,
1008 fcr,
1009 quot;
1010 int i;
1011
1012 if (!info->tty || !info->tty->termios)
1013 return;
1014 cflag = info->tty->termios->c_cflag;
1015
1016 quot = i = cflag & CBAUD;
1017 if (i & CBAUDEX) {
1018 i &= ~CBAUDEX;
1019 if (i < 1 || i > 2)
1020 info->tty->termios->c_cflag &= ~CBAUDEX;
1021 else
1022 i += 15;
1023 }
1024 if (quot) {
1025 info->mcr |= UART_MCR_DTR;
1026 isdn_tty_modem_ncarrier(info);
1027 } else {
1028 info->mcr &= ~UART_MCR_DTR;
1029 if (info->emu.mdmreg[REG_DTRHUP] & BIT_DTRHUP) {
1030#ifdef ISDN_DEBUG_MODEM_HUP
1031 printk(KERN_DEBUG "Mhup in changespeed\n");
1032#endif
1033 if (info->online)
1034 info->ncarrier = 1;
1035 isdn_tty_modem_reset_regs(info, 0);
1036 isdn_tty_modem_hup(info, 1);
1037 }
1038 return;
1039 }
1040 /* byte size and parity */
1041 cval = cflag & (CSIZE | CSTOPB);
1042 cval >>= 4;
1043 if (cflag & PARENB)
1044 cval |= UART_LCR_PARITY;
1045 if (!(cflag & PARODD))
1046 cval |= UART_LCR_EPAR;
1047 fcr = 0;
1048
1049 /* CTS flow control flag and modem status interrupts */
1050 if (cflag & CRTSCTS) {
1051 info->flags |= ISDN_ASYNC_CTS_FLOW;
1052 } else
1053 info->flags &= ~ISDN_ASYNC_CTS_FLOW;
1054 if (cflag & CLOCAL)
1055 info->flags &= ~ISDN_ASYNC_CHECK_CD;
1056 else {
1057 info->flags |= ISDN_ASYNC_CHECK_CD;
1058 }
1059}
1060
1061static int
1062isdn_tty_startup(modem_info * info)
1063{
1064 if (info->flags & ISDN_ASYNC_INITIALIZED)
1065 return 0;
1066 isdn_lock_drivers();
1067#ifdef ISDN_DEBUG_MODEM_OPEN
1068 printk(KERN_DEBUG "starting up ttyi%d ...\n", info->line);
1069#endif
1070 /*
1071 * Now, initialize the UART
1072 */
1073 info->mcr = UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2;
1074 if (info->tty)
1075 clear_bit(TTY_IO_ERROR, &info->tty->flags);
1076 /*
1077 * and set the speed of the serial port
1078 */
1079 isdn_tty_change_speed(info);
1080
1081 info->flags |= ISDN_ASYNC_INITIALIZED;
1082 info->msr |= (UART_MSR_DSR | UART_MSR_CTS);
1083 info->send_outstanding = 0;
1084 return 0;
1085}
1086
1087/*
1088 * This routine will shutdown a serial port; interrupts are disabled, and
1089 * DTR is dropped if the hangup on close termio flag is on.
1090 */
1091static void
1092isdn_tty_shutdown(modem_info * info)
1093{
1094 if (!(info->flags & ISDN_ASYNC_INITIALIZED))
1095 return;
1096#ifdef ISDN_DEBUG_MODEM_OPEN
1097 printk(KERN_DEBUG "Shutting down isdnmodem port %d ....\n", info->line);
1098#endif
1099 isdn_unlock_drivers();
1100 info->msr &= ~UART_MSR_RI;
1101 if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) {
1102 info->mcr &= ~(UART_MCR_DTR | UART_MCR_RTS);
1103 if (info->emu.mdmreg[REG_DTRHUP] & BIT_DTRHUP) {
1104 isdn_tty_modem_reset_regs(info, 0);
1105#ifdef ISDN_DEBUG_MODEM_HUP
1106 printk(KERN_DEBUG "Mhup in isdn_tty_shutdown\n");
1107#endif
1108 isdn_tty_modem_hup(info, 1);
1109 }
1110 }
1111 if (info->tty)
1112 set_bit(TTY_IO_ERROR, &info->tty->flags);
1113
1114 info->flags &= ~ISDN_ASYNC_INITIALIZED;
1115}
1116
1117/* isdn_tty_write() is the main send-routine. It is called from the upper
1118 * levels within the kernel to perform sending data. Depending on the
1119 * online-flag it either directs output to the at-command-interpreter or
1120 * to the lower level. Additional tasks done here:
1121 * - If online, check for escape-sequence (+++)
1122 * - If sending audio-data, call isdn_tty_DLEdown() to parse DLE-codes.
1123 * - If receiving audio-data, call isdn_tty_end_vrx() to abort if needed.
1124 * - If dialing, abort dial.
1125 */
1126static int
1127isdn_tty_write(struct tty_struct *tty, const u_char * buf, int count)
1128{
1129 int c;
1130 int total = 0;
1131 modem_info *info = (modem_info *) tty->driver_data;
1132 atemu *m = &info->emu;
1133
1134 if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_write"))
1135 return 0;
1136 /* See isdn_tty_senddown() */
1137 atomic_inc(&info->xmit_lock);
1138 while (1) {
1139 c = count;
1140 if (c > info->xmit_size - info->xmit_count)
1141 c = info->xmit_size - info->xmit_count;
1142 if (info->isdn_driver >= 0 && c > dev->drv[info->isdn_driver]->maxbufsize)
1143 c = dev->drv[info->isdn_driver]->maxbufsize;
1144 if (c <= 0)
1145 break;
1146 if ((info->online > 1)
1147#ifdef CONFIG_ISDN_AUDIO
1148 || (info->vonline & 3)
1149#endif
1150 ) {
1151#ifdef CONFIG_ISDN_AUDIO
1152 if (!info->vonline)
1153#endif
1154 isdn_tty_check_esc(buf, m->mdmreg[REG_ESC], c,
1155 &(m->pluscount),
1156 &(m->lastplus));
1157 memcpy(&(info->xmit_buf[info->xmit_count]), buf, c);
1158#ifdef CONFIG_ISDN_AUDIO
1159 if (info->vonline) {
1160 int cc = isdn_tty_handleDLEdown(info, m, c);
1161 if (info->vonline & 2) {
1162 if (!cc) {
1163 /* If DLE decoding results in zero-transmit, but
1164 * c originally was non-zero, do a wakeup.
1165 */
1166 tty_wakeup(tty);
1167 info->msr |= UART_MSR_CTS;
1168 info->lsr |= UART_LSR_TEMT;
1169 }
1170 info->xmit_count += cc;
1171 }
1172 if ((info->vonline & 3) == 1) {
1173 /* Do NOT handle Ctrl-Q or Ctrl-S
1174 * when in full-duplex audio mode.
1175 */
1176 if (isdn_tty_end_vrx(buf, c)) {
1177 info->vonline &= ~1;
1178#ifdef ISDN_DEBUG_MODEM_VOICE
1179 printk(KERN_DEBUG
1180 "got !^Q/^S, send DLE-ETX,VCON on ttyI%d\n",
1181 info->line);
1182#endif
1183 isdn_tty_at_cout("\020\003\r\nVCON\r\n", info);
1184 }
1185 }
1186 } else
1187 if (TTY_IS_FCLASS1(info)) {
1188 int cc = isdn_tty_handleDLEdown(info, m, c);
1189
1190 if (info->vonline & 4) { /* ETX seen */
1191 isdn_ctrl c;
1192
1193 c.command = ISDN_CMD_FAXCMD;
1194 c.driver = info->isdn_driver;
1195 c.arg = info->isdn_channel;
1196 c.parm.aux.cmd = ISDN_FAX_CLASS1_CTRL;
1197 c.parm.aux.subcmd = ETX;
1198 isdn_command(&c);
1199 }
1200 info->vonline = 0;
1201#ifdef ISDN_DEBUG_MODEM_VOICE
1202 printk(KERN_DEBUG "fax dle cc/c %d/%d\n", cc, c);
1203#endif
1204 info->xmit_count += cc;
1205 } else
1206#endif
1207 info->xmit_count += c;
1208 } else {
1209 info->msr |= UART_MSR_CTS;
1210 info->lsr |= UART_LSR_TEMT;
1211 if (info->dialing) {
1212 info->dialing = 0;
1213#ifdef ISDN_DEBUG_MODEM_HUP
1214 printk(KERN_DEBUG "Mhup in isdn_tty_write\n");
1215#endif
1216 isdn_tty_modem_result(RESULT_NO_CARRIER, info);
1217 isdn_tty_modem_hup(info, 1);
1218 } else
1219 c = isdn_tty_edit_at(buf, c, info);
1220 }
1221 buf += c;
1222 count -= c;
1223 total += c;
1224 }
1225 atomic_dec(&info->xmit_lock);
1226 if ((info->xmit_count) || (skb_queue_len(&info->xmit_queue))) {
1227 if (m->mdmreg[REG_DXMT] & BIT_DXMT) {
1228 isdn_tty_senddown(info);
1229 isdn_tty_tint(info);
1230 }
1231 isdn_timer_ctrl(ISDN_TIMER_MODEMXMIT, 1);
1232 }
1233 return total;
1234}
1235
1236static int
1237isdn_tty_write_room(struct tty_struct *tty)
1238{
1239 modem_info *info = (modem_info *) tty->driver_data;
1240 int ret;
1241
1242 if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_write_room"))
1243 return 0;
1244 if (!info->online)
1245 return info->xmit_size;
1246 ret = info->xmit_size - info->xmit_count;
1247 return (ret < 0) ? 0 : ret;
1248}
1249
1250static int
1251isdn_tty_chars_in_buffer(struct tty_struct *tty)
1252{
1253 modem_info *info = (modem_info *) tty->driver_data;
1254
1255 if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_chars_in_buffer"))
1256 return 0;
1257 if (!info->online)
1258 return 0;
1259 return (info->xmit_count);
1260}
1261
1262static void
1263isdn_tty_flush_buffer(struct tty_struct *tty)
1264{
1265 modem_info *info;
1266
1267 if (!tty) {
1268 return;
1269 }
1270 info = (modem_info *) tty->driver_data;
1271 if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_flush_buffer")) {
1272 return;
1273 }
1274 isdn_tty_cleanup_xmit(info);
1275 info->xmit_count = 0;
1276 wake_up_interruptible(&tty->write_wait);
1277 tty_wakeup(tty);
1278}
1279
1280static void
1281isdn_tty_flush_chars(struct tty_struct *tty)
1282{
1283 modem_info *info = (modem_info *) tty->driver_data;
1284
1285 if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_flush_chars"))
1286 return;
1287 if ((info->xmit_count) || (skb_queue_len(&info->xmit_queue)))
1288 isdn_timer_ctrl(ISDN_TIMER_MODEMXMIT, 1);
1289}
1290
1291/*
1292 * ------------------------------------------------------------
1293 * isdn_tty_throttle()
1294 *
1295 * This routine is called by the upper-layer tty layer to signal that
1296 * incoming characters should be throttled.
1297 * ------------------------------------------------------------
1298 */
1299static void
1300isdn_tty_throttle(struct tty_struct *tty)
1301{
1302 modem_info *info = (modem_info *) tty->driver_data;
1303
1304 if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_throttle"))
1305 return;
1306 if (I_IXOFF(tty))
1307 info->x_char = STOP_CHAR(tty);
1308 info->mcr &= ~UART_MCR_RTS;
1309}
1310
1311static void
1312isdn_tty_unthrottle(struct tty_struct *tty)
1313{
1314 modem_info *info = (modem_info *) tty->driver_data;
1315
1316 if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_unthrottle"))
1317 return;
1318 if (I_IXOFF(tty)) {
1319 if (info->x_char)
1320 info->x_char = 0;
1321 else
1322 info->x_char = START_CHAR(tty);
1323 }
1324 info->mcr |= UART_MCR_RTS;
1325}
1326
1327/*
1328 * ------------------------------------------------------------
1329 * isdn_tty_ioctl() and friends
1330 * ------------------------------------------------------------
1331 */
1332
1333/*
1334 * isdn_tty_get_lsr_info - get line status register info
1335 *
1336 * Purpose: Let user call ioctl() to get info when the UART physically
1337 * is emptied. On bus types like RS485, the transmitter must
1338 * release the bus after transmitting. This must be done when
1339 * the transmit shift register is empty, not be done when the
1340 * transmit holding register is empty. This functionality
1341 * allows RS485 driver to be written in user space.
1342 */
1343static int
1344isdn_tty_get_lsr_info(modem_info * info, uint __user * value)
1345{
1346 u_char status;
1347 uint result;
1348
1349 status = info->lsr;
1350 result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
1351 return put_user(result, value);
1352}
1353
1354
1355static int
1356isdn_tty_tiocmget(struct tty_struct *tty, struct file *file)
1357{
1358 modem_info *info = (modem_info *) tty->driver_data;
1359 u_char control, status;
1360
1361 if (isdn_tty_paranoia_check(info, tty->name, __FUNCTION__))
1362 return -ENODEV;
1363 if (tty->flags & (1 << TTY_IO_ERROR))
1364 return -EIO;
1365
1366#ifdef ISDN_DEBUG_MODEM_IOCTL
1367 printk(KERN_DEBUG "ttyI%d ioctl TIOCMGET\n", info->line);
1368#endif
1369
1370 control = info->mcr;
1371 status = info->msr;
1372 return ((control & UART_MCR_RTS) ? TIOCM_RTS : 0)
1373 | ((control & UART_MCR_DTR) ? TIOCM_DTR : 0)
1374 | ((status & UART_MSR_DCD) ? TIOCM_CAR : 0)
1375 | ((status & UART_MSR_RI) ? TIOCM_RNG : 0)
1376 | ((status & UART_MSR_DSR) ? TIOCM_DSR : 0)
1377 | ((status & UART_MSR_CTS) ? TIOCM_CTS : 0);
1378}
1379
1380static int
1381isdn_tty_tiocmset(struct tty_struct *tty, struct file *file,
1382 unsigned int set, unsigned int clear)
1383{
1384 modem_info *info = (modem_info *) tty->driver_data;
1385
1386 if (isdn_tty_paranoia_check(info, tty->name, __FUNCTION__))
1387 return -ENODEV;
1388 if (tty->flags & (1 << TTY_IO_ERROR))
1389 return -EIO;
1390
1391#ifdef ISDN_DEBUG_MODEM_IOCTL
1392 printk(KERN_DEBUG "ttyI%d ioctl TIOCMxxx: %x %x\n", info->line, set, clear);
1393#endif
1394
1395 if (set & TIOCM_RTS)
1396 info->mcr |= UART_MCR_RTS;
1397 if (set & TIOCM_DTR) {
1398 info->mcr |= UART_MCR_DTR;
1399 isdn_tty_modem_ncarrier(info);
1400 }
1401
1402 if (clear & TIOCM_RTS)
1403 info->mcr &= ~UART_MCR_RTS;
1404 if (clear & TIOCM_DTR) {
1405 info->mcr &= ~UART_MCR_DTR;
1406 if (info->emu.mdmreg[REG_DTRHUP] & BIT_DTRHUP) {
1407 isdn_tty_modem_reset_regs(info, 0);
1408#ifdef ISDN_DEBUG_MODEM_HUP
1409 printk(KERN_DEBUG "Mhup in TIOCMSET\n");
1410#endif
1411 if (info->online)
1412 info->ncarrier = 1;
1413 isdn_tty_modem_hup(info, 1);
1414 }
1415 }
1416 return 0;
1417}
1418
1419static int
1420isdn_tty_ioctl(struct tty_struct *tty, struct file *file,
1421 uint cmd, ulong arg)
1422{
1423 modem_info *info = (modem_info *) tty->driver_data;
1424 int retval;
1425
1426 if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_ioctl"))
1427 return -ENODEV;
1428 if (tty->flags & (1 << TTY_IO_ERROR))
1429 return -EIO;
1430 switch (cmd) {
1431 case TCSBRK: /* SVID version: non-zero arg --> no break */
1432#ifdef ISDN_DEBUG_MODEM_IOCTL
1433 printk(KERN_DEBUG "ttyI%d ioctl TCSBRK\n", info->line);
1434#endif
1435 retval = tty_check_change(tty);
1436 if (retval)
1437 return retval;
1438 tty_wait_until_sent(tty, 0);
1439 return 0;
1440 case TCSBRKP: /* support for POSIX tcsendbreak() */
1441#ifdef ISDN_DEBUG_MODEM_IOCTL
1442 printk(KERN_DEBUG "ttyI%d ioctl TCSBRKP\n", info->line);
1443#endif
1444 retval = tty_check_change(tty);
1445 if (retval)
1446 return retval;
1447 tty_wait_until_sent(tty, 0);
1448 return 0;
1449 case TIOCGSOFTCAR:
1450#ifdef ISDN_DEBUG_MODEM_IOCTL
1451 printk(KERN_DEBUG "ttyI%d ioctl TIOCGSOFTCAR\n", info->line);
1452#endif
1453 return put_user(C_CLOCAL(tty) ? 1 : 0, (ulong __user *) arg);
1454 case TIOCSSOFTCAR:
1455#ifdef ISDN_DEBUG_MODEM_IOCTL
1456 printk(KERN_DEBUG "ttyI%d ioctl TIOCSSOFTCAR\n", info->line);
1457#endif
1458 if (get_user(arg, (ulong __user *) arg))
1459 return -EFAULT;
1460 tty->termios->c_cflag =
1461 ((tty->termios->c_cflag & ~CLOCAL) |
1462 (arg ? CLOCAL : 0));
1463 return 0;
1464 case TIOCSERGETLSR: /* Get line status register */
1465#ifdef ISDN_DEBUG_MODEM_IOCTL
1466 printk(KERN_DEBUG "ttyI%d ioctl TIOCSERGETLSR\n", info->line);
1467#endif
1468 return isdn_tty_get_lsr_info(info, (uint __user *) arg);
1469 default:
1470#ifdef ISDN_DEBUG_MODEM_IOCTL
1471 printk(KERN_DEBUG "UNKNOWN ioctl 0x%08x on ttyi%d\n", cmd, info->line);
1472#endif
1473 return -ENOIOCTLCMD;
1474 }
1475 return 0;
1476}
1477
1478static void
1479isdn_tty_set_termios(struct tty_struct *tty, struct termios *old_termios)
1480{
1481 modem_info *info = (modem_info *) tty->driver_data;
1482
1483 if (!old_termios)
1484 isdn_tty_change_speed(info);
1485 else {
1486 if (tty->termios->c_cflag == old_termios->c_cflag)
1487 return;
1488 isdn_tty_change_speed(info);
1489 if ((old_termios->c_cflag & CRTSCTS) &&
1490 !(tty->termios->c_cflag & CRTSCTS)) {
1491 tty->hw_stopped = 0;
1492 }
1493 }
1494}
1495
1496/*
1497 * ------------------------------------------------------------
1498 * isdn_tty_open() and friends
1499 * ------------------------------------------------------------
1500 */
1501static int
1502isdn_tty_block_til_ready(struct tty_struct *tty, struct file *filp, modem_info * info)
1503{
1504 DECLARE_WAITQUEUE(wait, NULL);
1505 int do_clocal = 0;
1506 int retval;
1507
1508 /*
1509 * If the device is in the middle of being closed, then block
1510 * until it's done, and then try again.
1511 */
1512 if (tty_hung_up_p(filp) ||
1513 (info->flags & ISDN_ASYNC_CLOSING)) {
1514 if (info->flags & ISDN_ASYNC_CLOSING)
1515 interruptible_sleep_on(&info->close_wait);
1516#ifdef MODEM_DO_RESTART
1517 if (info->flags & ISDN_ASYNC_HUP_NOTIFY)
1518 return -EAGAIN;
1519 else
1520 return -ERESTARTSYS;
1521#else
1522 return -EAGAIN;
1523#endif
1524 }
1525 /*
1526 * If non-blocking mode is set, then make the check up front
1527 * and then exit.
1528 */
1529 if ((filp->f_flags & O_NONBLOCK) ||
1530 (tty->flags & (1 << TTY_IO_ERROR))) {
1531 if (info->flags & ISDN_ASYNC_CALLOUT_ACTIVE)
1532 return -EBUSY;
1533 info->flags |= ISDN_ASYNC_NORMAL_ACTIVE;
1534 return 0;
1535 }
1536 if (info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) {
1537 if (info->normal_termios.c_cflag & CLOCAL)
1538 do_clocal = 1;
1539 } else {
1540 if (tty->termios->c_cflag & CLOCAL)
1541 do_clocal = 1;
1542 }
1543 /*
1544 * Block waiting for the carrier detect and the line to become
1545 * free (i.e., not in use by the callout). While we are in
1546 * this loop, info->count is dropped by one, so that
1547 * isdn_tty_close() knows when to free things. We restore it upon
1548 * exit, either normal or abnormal.
1549 */
1550 retval = 0;
1551 add_wait_queue(&info->open_wait, &wait);
1552#ifdef ISDN_DEBUG_MODEM_OPEN
1553 printk(KERN_DEBUG "isdn_tty_block_til_ready before block: ttyi%d, count = %d\n",
1554 info->line, info->count);
1555#endif
1556 if (!(tty_hung_up_p(filp)))
1557 info->count--;
1558 info->blocked_open++;
1559 while (1) {
1560 set_current_state(TASK_INTERRUPTIBLE);
1561 if (tty_hung_up_p(filp) ||
1562 !(info->flags & ISDN_ASYNC_INITIALIZED)) {
1563#ifdef MODEM_DO_RESTART
1564 if (info->flags & ISDN_ASYNC_HUP_NOTIFY)
1565 retval = -EAGAIN;
1566 else
1567 retval = -ERESTARTSYS;
1568#else
1569 retval = -EAGAIN;
1570#endif
1571 break;
1572 }
1573 if (!(info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) &&
1574 !(info->flags & ISDN_ASYNC_CLOSING) &&
1575 (do_clocal || (info->msr & UART_MSR_DCD))) {
1576 break;
1577 }
1578 if (signal_pending(current)) {
1579 retval = -ERESTARTSYS;
1580 break;
1581 }
1582#ifdef ISDN_DEBUG_MODEM_OPEN
1583 printk(KERN_DEBUG "isdn_tty_block_til_ready blocking: ttyi%d, count = %d\n",
1584 info->line, info->count);
1585#endif
1586 schedule();
1587 }
1588 current->state = TASK_RUNNING;
1589 remove_wait_queue(&info->open_wait, &wait);
1590 if (!tty_hung_up_p(filp))
1591 info->count++;
1592 info->blocked_open--;
1593#ifdef ISDN_DEBUG_MODEM_OPEN
1594 printk(KERN_DEBUG "isdn_tty_block_til_ready after blocking: ttyi%d, count = %d\n",
1595 info->line, info->count);
1596#endif
1597 if (retval)
1598 return retval;
1599 info->flags |= ISDN_ASYNC_NORMAL_ACTIVE;
1600 return 0;
1601}
1602
1603/*
1604 * This routine is called whenever a serial port is opened. It
1605 * enables interrupts for a serial port, linking in its async structure into
1606 * the IRQ chain. It also performs the serial-specific
1607 * initialization for the tty structure.
1608 */
1609static int
1610isdn_tty_open(struct tty_struct *tty, struct file *filp)
1611{
1612 modem_info *info;
1613 int retval, line;
1614
1615 line = tty->index;
1616 if (line < 0 || line > ISDN_MAX_CHANNELS)
1617 return -ENODEV;
1618 info = &dev->mdm.info[line];
1619 if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_open"))
1620 return -ENODEV;
1621 if (!try_module_get(info->owner)) {
1622 printk(KERN_WARNING "%s: cannot reserve module\n", __FUNCTION__);
1623 return -ENODEV;
1624 }
1625#ifdef ISDN_DEBUG_MODEM_OPEN
1626 printk(KERN_DEBUG "isdn_tty_open %s, count = %d\n", tty->name,
1627 info->count);
1628#endif
1629 info->count++;
1630 tty->driver_data = info;
1631 info->tty = tty;
1632 /*
1633 * Start up serial port
1634 */
1635 retval = isdn_tty_startup(info);
1636 if (retval) {
1637#ifdef ISDN_DEBUG_MODEM_OPEN
1638 printk(KERN_DEBUG "isdn_tty_open return after startup\n");
1639#endif
1640 module_put(info->owner);
1641 return retval;
1642 }
1643 retval = isdn_tty_block_til_ready(tty, filp, info);
1644 if (retval) {
1645#ifdef ISDN_DEBUG_MODEM_OPEN
1646 printk(KERN_DEBUG "isdn_tty_open return after isdn_tty_block_til_ready \n");
1647#endif
1648 module_put(info->owner);
1649 return retval;
1650 }
1651#ifdef ISDN_DEBUG_MODEM_OPEN
1652 printk(KERN_DEBUG "isdn_tty_open ttyi%d successful...\n", info->line);
1653#endif
1654 dev->modempoll++;
1655#ifdef ISDN_DEBUG_MODEM_OPEN
1656 printk(KERN_DEBUG "isdn_tty_open normal exit\n");
1657#endif
1658 return 0;
1659}
1660
1661static void
1662isdn_tty_close(struct tty_struct *tty, struct file *filp)
1663{
1664 modem_info *info = (modem_info *) tty->driver_data;
1665 ulong timeout;
1666
1667 if (!info || isdn_tty_paranoia_check(info, tty->name, "isdn_tty_close"))
1668 return;
1669 if (tty_hung_up_p(filp)) {
1670#ifdef ISDN_DEBUG_MODEM_OPEN
1671 printk(KERN_DEBUG "isdn_tty_close return after tty_hung_up_p\n");
1672#endif
1673 return;
1674 }
1675 if ((tty->count == 1) && (info->count != 1)) {
1676 /*
1677 * Uh, oh. tty->count is 1, which means that the tty
1678 * structure will be freed. Info->count should always
1679 * be one in these conditions. If it's greater than
1680 * one, we've got real problems, since it means the
1681 * serial port won't be shutdown.
1682 */
1683 printk(KERN_ERR "isdn_tty_close: bad port count; tty->count is 1, "
1684 "info->count is %d\n", info->count);
1685 info->count = 1;
1686 }
1687 if (--info->count < 0) {
1688 printk(KERN_ERR "isdn_tty_close: bad port count for ttyi%d: %d\n",
1689 info->line, info->count);
1690 info->count = 0;
1691 }
1692 if (info->count) {
1693#ifdef ISDN_DEBUG_MODEM_OPEN
1694 printk(KERN_DEBUG "isdn_tty_close after info->count != 0\n");
1695#endif
1696 return;
1697 }
1698 info->flags |= ISDN_ASYNC_CLOSING;
1699 /*
1700 * Save the termios structure, since this port may have
1701 * separate termios for callout and dialin.
1702 */
1703 if (info->flags & ISDN_ASYNC_NORMAL_ACTIVE)
1704 info->normal_termios = *tty->termios;
1705 if (info->flags & ISDN_ASYNC_CALLOUT_ACTIVE)
1706 info->callout_termios = *tty->termios;
1707
1708 tty->closing = 1;
1709 /*
1710 * At this point we stop accepting input. To do this, we
1711 * disable the receive line status interrupts, and tell the
1712 * interrupt driver to stop checking the data ready bit in the
1713 * line status register.
1714 */
1715 if (info->flags & ISDN_ASYNC_INITIALIZED) {
1716 tty_wait_until_sent(tty, 3000); /* 30 seconds timeout */
1717 /*
1718 * Before we drop DTR, make sure the UART transmitter
1719 * has completely drained; this is especially
1720 * important if there is a transmit FIFO!
1721 */
1722 timeout = jiffies + HZ;
1723 while (!(info->lsr & UART_LSR_TEMT)) {
1724 set_current_state(TASK_INTERRUPTIBLE);
1725 schedule_timeout(20);
1726 if (time_after(jiffies,timeout))
1727 break;
1728 }
1729 }
1730 dev->modempoll--;
1731 isdn_tty_shutdown(info);
1732
1733 if (tty->driver->flush_buffer)
1734 tty->driver->flush_buffer(tty);
1735 tty_ldisc_flush(tty);
1736 info->tty = NULL;
1737 info->ncarrier = 0;
1738 tty->closing = 0;
1739 module_put(info->owner);
1740 if (info->blocked_open) {
1741 msleep_interruptible(500);
1742 wake_up_interruptible(&info->open_wait);
1743 }
1744 info->flags &= ~(ISDN_ASYNC_NORMAL_ACTIVE | ISDN_ASYNC_CLOSING);
1745 wake_up_interruptible(&info->close_wait);
1746#ifdef ISDN_DEBUG_MODEM_OPEN
1747 printk(KERN_DEBUG "isdn_tty_close normal exit\n");
1748#endif
1749}
1750
1751/*
1752 * isdn_tty_hangup() --- called by tty_hangup() when a hangup is signaled.
1753 */
1754static void
1755isdn_tty_hangup(struct tty_struct *tty)
1756{
1757 modem_info *info = (modem_info *) tty->driver_data;
1758
1759 if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_hangup"))
1760 return;
1761 isdn_tty_shutdown(info);
1762 info->count = 0;
1763 info->flags &= ~(ISDN_ASYNC_NORMAL_ACTIVE | ISDN_ASYNC_CALLOUT_ACTIVE);
1764 info->tty = NULL;
1765 wake_up_interruptible(&info->open_wait);
1766}
1767
1768/* This routine initializes all emulator-data.
1769 */
1770static void
1771isdn_tty_reset_profile(atemu * m)
1772{
1773 m->profile[0] = 0;
1774 m->profile[1] = 0;
1775 m->profile[2] = 43;
1776 m->profile[3] = 13;
1777 m->profile[4] = 10;
1778 m->profile[5] = 8;
1779 m->profile[6] = 3;
1780 m->profile[7] = 60;
1781 m->profile[8] = 2;
1782 m->profile[9] = 6;
1783 m->profile[10] = 7;
1784 m->profile[11] = 70;
1785 m->profile[12] = 0x45;
1786 m->profile[13] = 4;
1787 m->profile[14] = ISDN_PROTO_L2_X75I;
1788 m->profile[15] = ISDN_PROTO_L3_TRANS;
1789 m->profile[16] = ISDN_SERIAL_XMIT_SIZE / 16;
1790 m->profile[17] = ISDN_MODEM_WINSIZE;
1791 m->profile[18] = 4;
1792 m->profile[19] = 0;
1793 m->profile[20] = 0;
1794 m->profile[23] = 0;
1795 m->pmsn[0] = '\0';
1796 m->plmsn[0] = '\0';
1797}
1798
1799#ifdef CONFIG_ISDN_AUDIO
1800static void
1801isdn_tty_modem_reset_vpar(atemu * m)
1802{
1803 m->vpar[0] = 2; /* Voice-device (2 = phone line) */
1804 m->vpar[1] = 0; /* Silence detection level (0 = none ) */
1805 m->vpar[2] = 70; /* Silence interval (7 sec. ) */
1806 m->vpar[3] = 2; /* Compression type (1 = ADPCM-2 ) */
1807 m->vpar[4] = 0; /* DTMF detection level (0 = softcode ) */
1808 m->vpar[5] = 8; /* DTMF interval (8 * 5 ms. ) */
1809}
1810#endif
1811
1812#ifdef CONFIG_ISDN_TTY_FAX
1813static void
1814isdn_tty_modem_reset_faxpar(modem_info * info)
1815{
1816 T30_s *f = info->fax;
1817
1818 f->code = 0;
1819 f->phase = ISDN_FAX_PHASE_IDLE;
1820 f->direction = 0;
1821 f->resolution = 1; /* fine */
1822 f->rate = 5; /* 14400 bit/s */
1823 f->width = 0;
1824 f->length = 0;
1825 f->compression = 0;
1826 f->ecm = 0;
1827 f->binary = 0;
1828 f->scantime = 0;
1829 memset(&f->id[0], 32, FAXIDLEN - 1);
1830 f->id[FAXIDLEN - 1] = 0;
1831 f->badlin = 0;
1832 f->badmul = 0;
1833 f->bor = 0;
1834 f->nbc = 0;
1835 f->cq = 0;
1836 f->cr = 0;
1837 f->ctcrty = 0;
1838 f->minsp = 0;
1839 f->phcto = 30;
1840 f->rel = 0;
1841 memset(&f->pollid[0], 32, FAXIDLEN - 1);
1842 f->pollid[FAXIDLEN - 1] = 0;
1843}
1844#endif
1845
1846static void
1847isdn_tty_modem_reset_regs(modem_info * info, int force)
1848{
1849 atemu *m = &info->emu;
1850 if ((m->mdmreg[REG_DTRR] & BIT_DTRR) || force) {
1851 memcpy(m->mdmreg, m->profile, ISDN_MODEM_NUMREG);
1852 memcpy(m->msn, m->pmsn, ISDN_MSNLEN);
1853 memcpy(m->lmsn, m->plmsn, ISDN_LMSNLEN);
1854 info->xmit_size = m->mdmreg[REG_PSIZE] * 16;
1855 }
1856#ifdef CONFIG_ISDN_AUDIO
1857 isdn_tty_modem_reset_vpar(m);
1858#endif
1859#ifdef CONFIG_ISDN_TTY_FAX
1860 isdn_tty_modem_reset_faxpar(info);
1861#endif
1862 m->mdmcmdl = 0;
1863}
1864
1865static void
1866modem_write_profile(atemu * m)
1867{
1868 memcpy(m->profile, m->mdmreg, ISDN_MODEM_NUMREG);
1869 memcpy(m->pmsn, m->msn, ISDN_MSNLEN);
1870 memcpy(m->plmsn, m->lmsn, ISDN_LMSNLEN);
1871 if (dev->profd)
1872 send_sig(SIGIO, dev->profd, 1);
1873}
1874
1875static struct tty_operations modem_ops = {
1876 .open = isdn_tty_open,
1877 .close = isdn_tty_close,
1878 .write = isdn_tty_write,
1879 .flush_chars = isdn_tty_flush_chars,
1880 .write_room = isdn_tty_write_room,
1881 .chars_in_buffer = isdn_tty_chars_in_buffer,
1882 .flush_buffer = isdn_tty_flush_buffer,
1883 .ioctl = isdn_tty_ioctl,
1884 .throttle = isdn_tty_throttle,
1885 .unthrottle = isdn_tty_unthrottle,
1886 .set_termios = isdn_tty_set_termios,
1887 .hangup = isdn_tty_hangup,
1888 .tiocmget = isdn_tty_tiocmget,
1889 .tiocmset = isdn_tty_tiocmset,
1890};
1891
1892int
1893isdn_tty_modem_init(void)
1894{
1895 isdn_modem_t *m;
1896 int i, retval;
1897 modem_info *info;
1898
1899 m = &dev->mdm;
1900 m->tty_modem = alloc_tty_driver(ISDN_MAX_CHANNELS);
1901 if (!m->tty_modem)
1902 return -ENOMEM;
1903 m->tty_modem->name = "ttyI";
1904 m->tty_modem->devfs_name = "isdn/ttyI";
1905 m->tty_modem->major = ISDN_TTY_MAJOR;
1906 m->tty_modem->minor_start = 0;
1907 m->tty_modem->type = TTY_DRIVER_TYPE_SERIAL;
1908 m->tty_modem->subtype = SERIAL_TYPE_NORMAL;
1909 m->tty_modem->init_termios = tty_std_termios;
1910 m->tty_modem->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
1911 m->tty_modem->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
1912 m->tty_modem->driver_name = "isdn_tty";
1913 tty_set_operations(m->tty_modem, &modem_ops);
1914 retval = tty_register_driver(m->tty_modem);
1915 if (retval) {
1916 printk(KERN_WARNING "isdn_tty: Couldn't register modem-device\n");
1917 goto err;
1918 }
1919 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
1920 info = &m->info[i];
1921#ifdef CONFIG_ISDN_TTY_FAX
1922 if (!(info->fax = kmalloc(sizeof(T30_s), GFP_KERNEL))) {
1923 printk(KERN_ERR "Could not allocate fax t30-buffer\n");
1924 retval = -ENOMEM;
1925 goto err_unregister;
1926 }
1927#endif
1928#ifdef MODULE
1929 info->owner = THIS_MODULE;
1930#endif
1931 spin_lock_init(&info->readlock);
1932 init_MUTEX(&info->write_sem);
1933 sprintf(info->last_cause, "0000");
1934 sprintf(info->last_num, "none");
1935 info->last_dir = 0;
1936 info->last_lhup = 1;
1937 info->last_l2 = -1;
1938 info->last_si = 0;
1939 isdn_tty_reset_profile(&info->emu);
1940 isdn_tty_modem_reset_regs(info, 1);
1941 info->magic = ISDN_ASYNC_MAGIC;
1942 info->line = i;
1943 info->tty = NULL;
1944 info->x_char = 0;
1945 info->count = 0;
1946 info->blocked_open = 0;
1947 init_waitqueue_head(&info->open_wait);
1948 init_waitqueue_head(&info->close_wait);
1949 info->isdn_driver = -1;
1950 info->isdn_channel = -1;
1951 info->drv_index = -1;
1952 info->xmit_size = ISDN_SERIAL_XMIT_SIZE;
1953 init_timer(&info->nc_timer);
1954 info->nc_timer.function = isdn_tty_modem_do_ncarrier;
1955 info->nc_timer.data = (unsigned long) info;
1956 skb_queue_head_init(&info->xmit_queue);
1957#ifdef CONFIG_ISDN_AUDIO
1958 skb_queue_head_init(&info->dtmf_queue);
1959#endif
1960 if (!(info->xmit_buf = kmalloc(ISDN_SERIAL_XMIT_MAX + 5, GFP_KERNEL))) {
1961 printk(KERN_ERR "Could not allocate modem xmit-buffer\n");
1962 retval = -ENOMEM;
1963 goto err_unregister;
1964 }
1965 /* Make room for T.70 header */
1966 info->xmit_buf += 4;
1967 }
1968 return 0;
1969err_unregister:
1970 for (i--; i >= 0; i--) {
1971 info = &m->info[i];
1972#ifdef CONFIG_ISDN_TTY_FAX
1973 kfree(info->fax);
1974#endif
1975 kfree(info->xmit_buf - 4);
1976 }
1977 tty_unregister_driver(m->tty_modem);
1978 err:
1979 put_tty_driver(m->tty_modem);
1980 m->tty_modem = NULL;
1981 return retval;
1982}
1983
1984void
1985isdn_tty_exit(void)
1986{
1987 modem_info *info;
1988 int i;
1989
1990 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
1991 info = &dev->mdm.info[i];
1992 isdn_tty_cleanup_xmit(info);
1993#ifdef CONFIG_ISDN_TTY_FAX
1994 kfree(info->fax);
1995#endif
1996 kfree(info->xmit_buf - 4);
1997 }
1998 tty_unregister_driver(dev->mdm.tty_modem);
1999 put_tty_driver(dev->mdm.tty_modem);
2000 dev->mdm.tty_modem = NULL;
2001}
2002
2003
2004/*
2005 * isdn_tty_match_icall(char *MSN, atemu *tty_emulator, int dev_idx)
2006 * match the MSN against the MSNs (glob patterns) defined for tty_emulator,
2007 * and return 0 for match, 1 for no match, 2 if MSN could match if longer.
2008 */
2009
2010static int
2011isdn_tty_match_icall(char *cid, atemu *emu, int di)
2012{
2013#ifdef ISDN_DEBUG_MODEM_ICALL
2014 printk(KERN_DEBUG "m_fi: msn=%s lmsn=%s mmsn=%s mreg[SI1]=%d mreg[SI2]=%d\n",
2015 emu->msn, emu->lmsn, isdn_map_eaz2msn(emu->msn, di),
2016 emu->mdmreg[REG_SI1], emu->mdmreg[REG_SI2]);
2017#endif
2018 if (strlen(emu->lmsn)) {
2019 char *p = emu->lmsn;
2020 char *q;
2021 int tmp;
2022 int ret = 0;
2023
2024 while (1) {
2025 if ((q = strchr(p, ';')))
2026 *q = '\0';
2027 if ((tmp = isdn_msncmp(cid, isdn_map_eaz2msn(p, di))) > ret)
2028 ret = tmp;
2029#ifdef ISDN_DEBUG_MODEM_ICALL
2030 printk(KERN_DEBUG "m_fi: lmsnX=%s mmsn=%s -> tmp=%d\n",
2031 p, isdn_map_eaz2msn(emu->msn, di), tmp);
2032#endif
2033 if (q) {
2034 *q = ';';
2035 p = q;
2036 p++;
2037 }
2038 if (!tmp)
2039 return 0;
2040 if (!q)
2041 break;
2042 }
2043 return ret;
2044 } else {
2045 int tmp;
2046 tmp = isdn_msncmp(cid, isdn_map_eaz2msn(emu->msn, di));
2047#ifdef ISDN_DEBUG_MODEM_ICALL
2048 printk(KERN_DEBUG "m_fi: mmsn=%s -> tmp=%d\n",
2049 isdn_map_eaz2msn(emu->msn, di), tmp);
2050#endif
2051 return tmp;
2052 }
2053}
2054
2055/*
2056 * An incoming call-request has arrived.
2057 * Search the tty-devices for an appropriate device and bind
2058 * it to the ISDN-Channel.
2059 * Return:
2060 *
2061 * 0 = No matching device found.
2062 * 1 = A matching device found.
2063 * 3 = No match found, but eventually would match, if
2064 * CID is longer.
2065 */
2066int
2067isdn_tty_find_icall(int di, int ch, setup_parm *setup)
2068{
2069 char *eaz;
2070 int i;
2071 int wret;
2072 int idx;
2073 int si1;
2074 int si2;
2075 char *nr;
2076 ulong flags;
2077
2078 if (!setup->phone[0]) {
2079 nr = "0";
2080 printk(KERN_INFO "isdn_tty: Incoming call without OAD, assuming '0'\n");
2081 } else
2082 nr = setup->phone;
2083 si1 = (int) setup->si1;
2084 si2 = (int) setup->si2;
2085 if (!setup->eazmsn[0]) {
2086 printk(KERN_WARNING "isdn_tty: Incoming call without CPN, assuming '0'\n");
2087 eaz = "0";
2088 } else
2089 eaz = setup->eazmsn;
2090#ifdef ISDN_DEBUG_MODEM_ICALL
2091 printk(KERN_DEBUG "m_fi: eaz=%s si1=%d si2=%d\n", eaz, si1, si2);
2092#endif
2093 wret = 0;
2094 spin_lock_irqsave(&dev->lock, flags);
2095 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
2096 modem_info *info = &dev->mdm.info[i];
2097
2098 if (info->count == 0)
2099 continue;
2100 if ((info->emu.mdmreg[REG_SI1] & si2bit[si1]) && /* SI1 is matching */
2101 (info->emu.mdmreg[REG_SI2] == si2)) { /* SI2 is matching */
2102 idx = isdn_dc2minor(di, ch);
2103#ifdef ISDN_DEBUG_MODEM_ICALL
2104 printk(KERN_DEBUG "m_fi: match1 wret=%d\n", wret);
2105 printk(KERN_DEBUG "m_fi: idx=%d flags=%08lx drv=%d ch=%d usg=%d\n", idx,
2106 info->flags, info->isdn_driver, info->isdn_channel,
2107 dev->usage[idx]);
2108#endif
2109 if (
2110#ifndef FIX_FILE_TRANSFER
2111 (info->flags & ISDN_ASYNC_NORMAL_ACTIVE) &&
2112#endif
2113 (info->isdn_driver == -1) &&
2114 (info->isdn_channel == -1) &&
2115 (USG_NONE(dev->usage[idx]))) {
2116 int matchret;
2117
2118 if ((matchret = isdn_tty_match_icall(eaz, &info->emu, di)) > wret)
2119 wret = matchret;
2120 if (!matchret) { /* EAZ is matching */
2121 info->isdn_driver = di;
2122 info->isdn_channel = ch;
2123 info->drv_index = idx;
2124 dev->m_idx[idx] = info->line;
2125 dev->usage[idx] &= ISDN_USAGE_EXCLUSIVE;
2126 dev->usage[idx] |= isdn_calc_usage(si1, info->emu.mdmreg[REG_L2PROT]);
2127 strcpy(dev->num[idx], nr);
2128 strcpy(info->emu.cpn, eaz);
2129 info->emu.mdmreg[REG_SI1I] = si2bit[si1];
2130 info->emu.mdmreg[REG_PLAN] = setup->plan;
2131 info->emu.mdmreg[REG_SCREEN] = setup->screen;
2132 isdn_info_update();
2133 spin_unlock_irqrestore(&dev->lock, flags);
2134 printk(KERN_INFO "isdn_tty: call from %s, -> RING on ttyI%d\n", nr,
2135 info->line);
2136 info->msr |= UART_MSR_RI;
2137 isdn_tty_modem_result(RESULT_RING, info);
2138 isdn_timer_ctrl(ISDN_TIMER_MODEMRING, 1);
2139 return 1;
2140 }
2141 }
2142 }
2143 }
2144 spin_unlock_irqrestore(&dev->lock, flags);
2145 printk(KERN_INFO "isdn_tty: call from %s -> %s %s\n", nr, eaz,
2146 ((dev->drv[di]->flags & DRV_FLAG_REJBUS) && (wret != 2))? "rejected" : "ignored");
2147 return (wret == 2)?3:0;
2148}
2149
2150#define TTY_IS_ACTIVE(info) \
2151 (info->flags & (ISDN_ASYNC_NORMAL_ACTIVE | ISDN_ASYNC_CALLOUT_ACTIVE))
2152
2153int
2154isdn_tty_stat_callback(int i, isdn_ctrl *c)
2155{
2156 int mi;
2157 modem_info *info;
2158 char *e;
2159
2160 if (i < 0)
2161 return 0;
2162 if ((mi = dev->m_idx[i]) >= 0) {
2163 info = &dev->mdm.info[mi];
2164 switch (c->command) {
2165 case ISDN_STAT_CINF:
2166 printk(KERN_DEBUG "CHARGEINFO on ttyI%d: %ld %s\n", info->line, c->arg, c->parm.num);
2167 info->emu.charge = (unsigned) simple_strtoul(c->parm.num, &e, 10);
2168 if (e == (char *)c->parm.num)
2169 info->emu.charge = 0;
2170
2171 break;
2172 case ISDN_STAT_BSENT:
2173#ifdef ISDN_TTY_STAT_DEBUG
2174 printk(KERN_DEBUG "tty_STAT_BSENT ttyI%d\n", info->line);
2175#endif
2176 if ((info->isdn_driver == c->driver) &&
2177 (info->isdn_channel == c->arg)) {
2178 info->msr |= UART_MSR_CTS;
2179 if (info->send_outstanding)
2180 if (!(--info->send_outstanding))
2181 info->lsr |= UART_LSR_TEMT;
2182 isdn_tty_tint(info);
2183 return 1;
2184 }
2185 break;
2186 case ISDN_STAT_CAUSE:
2187#ifdef ISDN_TTY_STAT_DEBUG
2188 printk(KERN_DEBUG "tty_STAT_CAUSE ttyI%d\n", info->line);
2189#endif
2190 /* Signal cause to tty-device */
2191 strncpy(info->last_cause, c->parm.num, 5);
2192 return 1;
2193 case ISDN_STAT_DISPLAY:
2194#ifdef ISDN_TTY_STAT_DEBUG
2195 printk(KERN_DEBUG "tty_STAT_DISPLAY ttyI%d\n", info->line);
2196#endif
2197 /* Signal display to tty-device */
2198 if ((info->emu.mdmreg[REG_DISPLAY] & BIT_DISPLAY) &&
2199 !(info->emu.mdmreg[REG_RESPNUM] & BIT_RESPNUM)) {
2200 isdn_tty_at_cout("\r\n", info);
2201 isdn_tty_at_cout("DISPLAY: ", info);
2202 isdn_tty_at_cout(c->parm.display, info);
2203 isdn_tty_at_cout("\r\n", info);
2204 }
2205 return 1;
2206 case ISDN_STAT_DCONN:
2207#ifdef ISDN_TTY_STAT_DEBUG
2208 printk(KERN_DEBUG "tty_STAT_DCONN ttyI%d\n", info->line);
2209#endif
2210 if (TTY_IS_ACTIVE(info)) {
2211 if (info->dialing == 1) {
2212 info->dialing = 2;
2213 return 1;
2214 }
2215 }
2216 break;
2217 case ISDN_STAT_DHUP:
2218#ifdef ISDN_TTY_STAT_DEBUG
2219 printk(KERN_DEBUG "tty_STAT_DHUP ttyI%d\n", info->line);
2220#endif
2221 if (TTY_IS_ACTIVE(info)) {
2222 if (info->dialing == 1)
2223 isdn_tty_modem_result(RESULT_BUSY, info);
2224 if (info->dialing > 1)
2225 isdn_tty_modem_result(RESULT_NO_CARRIER, info);
2226 info->dialing = 0;
2227#ifdef ISDN_DEBUG_MODEM_HUP
2228 printk(KERN_DEBUG "Mhup in ISDN_STAT_DHUP\n");
2229#endif
2230 isdn_tty_modem_hup(info, 0);
2231 return 1;
2232 }
2233 break;
2234 case ISDN_STAT_BCONN:
2235#ifdef ISDN_TTY_STAT_DEBUG
2236 printk(KERN_DEBUG "tty_STAT_BCONN ttyI%d\n", info->line);
2237#endif
2238 /* Wake up any processes waiting
2239 * for incoming call of this device when
2240 * DCD follow the state of incoming carrier
2241 */
2242 if (info->blocked_open &&
2243 (info->emu.mdmreg[REG_DCD] & BIT_DCD)) {
2244 wake_up_interruptible(&info->open_wait);
2245 }
2246
2247 /* Schedule CONNECT-Message to any tty
2248 * waiting for it and
2249 * set DCD-bit of its modem-status.
2250 */
2251 if (TTY_IS_ACTIVE(info) ||
2252 (info->blocked_open && (info->emu.mdmreg[REG_DCD] & BIT_DCD))) {
2253 info->msr |= UART_MSR_DCD;
2254 info->emu.charge = 0;
2255 if (info->dialing & 0xf)
2256 info->last_dir = 1;
2257 else
2258 info->last_dir = 0;
2259 info->dialing = 0;
2260 info->rcvsched = 1;
2261 if (USG_MODEM(dev->usage[i])) {
2262 if (info->emu.mdmreg[REG_L2PROT] == ISDN_PROTO_L2_MODEM) {
2263 strcpy(info->emu.connmsg, c->parm.num);
2264 isdn_tty_modem_result(RESULT_CONNECT, info);
2265 } else
2266 isdn_tty_modem_result(RESULT_CONNECT64000, info);
2267 }
2268 if (USG_VOICE(dev->usage[i]))
2269 isdn_tty_modem_result(RESULT_VCON, info);
2270 return 1;
2271 }
2272 break;
2273 case ISDN_STAT_BHUP:
2274#ifdef ISDN_TTY_STAT_DEBUG
2275 printk(KERN_DEBUG "tty_STAT_BHUP ttyI%d\n", info->line);
2276#endif
2277 if (TTY_IS_ACTIVE(info)) {
2278#ifdef ISDN_DEBUG_MODEM_HUP
2279 printk(KERN_DEBUG "Mhup in ISDN_STAT_BHUP\n");
2280#endif
2281 isdn_tty_modem_hup(info, 0);
2282 return 1;
2283 }
2284 break;
2285 case ISDN_STAT_NODCH:
2286#ifdef ISDN_TTY_STAT_DEBUG
2287 printk(KERN_DEBUG "tty_STAT_NODCH ttyI%d\n", info->line);
2288#endif
2289 if (TTY_IS_ACTIVE(info)) {
2290 if (info->dialing) {
2291 info->dialing = 0;
2292 info->last_l2 = -1;
2293 info->last_si = 0;
2294 sprintf(info->last_cause, "0000");
2295 isdn_tty_modem_result(RESULT_NO_DIALTONE, info);
2296 }
2297 isdn_tty_modem_hup(info, 0);
2298 return 1;
2299 }
2300 break;
2301 case ISDN_STAT_UNLOAD:
2302#ifdef ISDN_TTY_STAT_DEBUG
2303 printk(KERN_DEBUG "tty_STAT_UNLOAD ttyI%d\n", info->line);
2304#endif
2305 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
2306 info = &dev->mdm.info[i];
2307 if (info->isdn_driver == c->driver) {
2308 if (info->online)
2309 isdn_tty_modem_hup(info, 1);
2310 }
2311 }
2312 return 1;
2313#ifdef CONFIG_ISDN_TTY_FAX
2314 case ISDN_STAT_FAXIND:
2315 if (TTY_IS_ACTIVE(info)) {
2316 isdn_tty_fax_command(info, c);
2317 }
2318 break;
2319#endif
2320#ifdef CONFIG_ISDN_AUDIO
2321 case ISDN_STAT_AUDIO:
2322 if (TTY_IS_ACTIVE(info)) {
2323 switch(c->parm.num[0]) {
2324 case ISDN_AUDIO_DTMF:
2325 if (info->vonline) {
2326 isdn_audio_put_dle_code(info,
2327 c->parm.num[1]);
2328 }
2329 break;
2330 }
2331 }
2332 break;
2333#endif
2334 }
2335 }
2336 return 0;
2337}
2338
2339/*********************************************************************
2340 Modem-Emulator-Routines
2341 *********************************************************************/
2342
2343#define cmdchar(c) ((c>=' ')&&(c<=0x7f))
2344
2345/*
2346 * Put a message from the AT-emulator into receive-buffer of tty,
2347 * convert CR, LF, and BS to values in modem-registers 3, 4 and 5.
2348 */
2349void
2350isdn_tty_at_cout(char *msg, modem_info * info)
2351{
2352 struct tty_struct *tty;
2353 atemu *m = &info->emu;
2354 char *p;
2355 char c;
2356 u_long flags;
2357 struct sk_buff *skb = NULL;
2358 char *sp = NULL;
2359
2360 if (!msg) {
2361 printk(KERN_WARNING "isdn_tty: Null-Message in isdn_tty_at_cout\n");
2362 return;
2363 }
2364 spin_lock_irqsave(&info->readlock, flags);
2365 tty = info->tty;
2366 if ((info->flags & ISDN_ASYNC_CLOSING) || (!tty)) {
2367 spin_unlock_irqrestore(&info->readlock, flags);
2368 return;
2369 }
2370
2371 /* use queue instead of direct flip, if online and */
2372 /* data is in queue or flip buffer is full */
2373 if ((info->online) && (((tty->flip.count + strlen(msg)) >= TTY_FLIPBUF_SIZE) ||
2374 (!skb_queue_empty(&dev->drv[info->isdn_driver]->rpqueue[info->isdn_channel])))) {
2375 skb = alloc_skb(strlen(msg), GFP_ATOMIC);
2376 if (!skb) {
2377 spin_unlock_irqrestore(&info->readlock, flags);
2378 return;
2379 }
2380 sp = skb_put(skb, strlen(msg));
2381#ifdef CONFIG_ISDN_AUDIO
2382 ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;
2383 ISDN_AUDIO_SKB_LOCK(skb) = 0;
2384#endif
2385 }
2386
2387 for (p = msg; *p; p++) {
2388 switch (*p) {
2389 case '\r':
2390 c = m->mdmreg[REG_CR];
2391 break;
2392 case '\n':
2393 c = m->mdmreg[REG_LF];
2394 break;
2395 case '\b':
2396 c = m->mdmreg[REG_BS];
2397 break;
2398 default:
2399 c = *p;
2400 }
2401 if (skb) {
2402 *sp++ = c;
2403 } else {
2404 if (tty->flip.count >= TTY_FLIPBUF_SIZE)
2405 break;
2406 tty_insert_flip_char(tty, c, 0);
2407 }
2408 }
2409 if (skb) {
2410 __skb_queue_tail(&dev->drv[info->isdn_driver]->rpqueue[info->isdn_channel], skb);
2411 dev->drv[info->isdn_driver]->rcvcount[info->isdn_channel] += skb->len;
2412 spin_unlock_irqrestore(&info->readlock, flags);
2413 /* Schedule dequeuing */
2414 if ((dev->modempoll) && (info->rcvsched))
2415 isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
2416
2417 } else {
2418 spin_unlock_irqrestore(&info->readlock, flags);
2419 schedule_delayed_work(&tty->flip.work, 1);
2420 }
2421}
2422
2423/*
2424 * Perform ATH Hangup
2425 */
2426static void
2427isdn_tty_on_hook(modem_info * info)
2428{
2429 if (info->isdn_channel >= 0) {
2430#ifdef ISDN_DEBUG_MODEM_HUP
2431 printk(KERN_DEBUG "Mhup in isdn_tty_on_hook\n");
2432#endif
2433 isdn_tty_modem_hup(info, 1);
2434 }
2435}
2436
2437static void
2438isdn_tty_off_hook(void)
2439{
2440 printk(KERN_DEBUG "isdn_tty_off_hook\n");
2441}
2442
2443#define PLUSWAIT1 (HZ/2) /* 0.5 sec. */
2444#define PLUSWAIT2 (HZ*3/2) /* 1.5 sec */
2445
2446/*
2447 * Check Buffer for Modem-escape-sequence, activate timer-callback to
2448 * isdn_tty_modem_escape() if sequence found.
2449 *
2450 * Parameters:
2451 * p pointer to databuffer
2452 * plus escape-character
2453 * count length of buffer
2454 * pluscount count of valid escape-characters so far
2455 * lastplus timestamp of last character
2456 */
2457static void
2458isdn_tty_check_esc(const u_char * p, u_char plus, int count, int *pluscount,
2459 u_long *lastplus)
2460{
2461 if (plus > 127)
2462 return;
2463 if (count > 3) {
2464 p += count - 3;
2465 count = 3;
2466 *pluscount = 0;
2467 }
2468 while (count > 0) {
2469 if (*(p++) == plus) {
2470 if ((*pluscount)++) {
2471 /* Time since last '+' > 0.5 sec. ? */
2472 if (time_after(jiffies, *lastplus + PLUSWAIT1))
2473 *pluscount = 1;
2474 } else {
2475 /* Time since last non-'+' < 1.5 sec. ? */
2476 if (time_before(jiffies, *lastplus + PLUSWAIT2))
2477 *pluscount = 0;
2478 }
2479 if ((*pluscount == 3) && (count == 1))
2480 isdn_timer_ctrl(ISDN_TIMER_MODEMPLUS, 1);
2481 if (*pluscount > 3)
2482 *pluscount = 1;
2483 } else
2484 *pluscount = 0;
2485 *lastplus = jiffies;
2486 count--;
2487 }
2488}
2489
2490/*
2491 * Return result of AT-emulator to tty-receive-buffer, depending on
2492 * modem-register 12, bit 0 and 1.
2493 * For CONNECT-messages also switch to online-mode.
2494 * For RING-message handle auto-ATA if register 0 != 0
2495 */
2496
2497static void
2498isdn_tty_modem_result(int code, modem_info * info)
2499{
2500 atemu *m = &info->emu;
2501 static char *msg[] =
2502 {"OK", "CONNECT", "RING", "NO CARRIER", "ERROR",
2503 "CONNECT 64000", "NO DIALTONE", "BUSY", "NO ANSWER",
2504 "RINGING", "NO MSN/EAZ", "VCON", "RUNG"};
2505 char s[ISDN_MSNLEN+10];
2506
2507 switch (code) {
2508 case RESULT_RING:
2509 m->mdmreg[REG_RINGCNT]++;
2510 if (m->mdmreg[REG_RINGCNT] == m->mdmreg[REG_RINGATA])
2511 /* Automatically accept incoming call */
2512 isdn_tty_cmd_ATA(info);
2513 break;
2514 case RESULT_NO_CARRIER:
2515#ifdef ISDN_DEBUG_MODEM_HUP
2516 printk(KERN_DEBUG "modem_result: NO CARRIER %d %d\n",
2517 (info->flags & ISDN_ASYNC_CLOSING),
2518 (!info->tty));
2519#endif
2520 m->mdmreg[REG_RINGCNT] = 0;
2521 del_timer(&info->nc_timer);
2522 info->ncarrier = 0;
2523 if ((info->flags & ISDN_ASYNC_CLOSING) || (!info->tty)) {
2524 return;
2525 }
2526#ifdef CONFIG_ISDN_AUDIO
2527 if (info->vonline & 1) {
2528#ifdef ISDN_DEBUG_MODEM_VOICE
2529 printk(KERN_DEBUG "res3: send DLE-ETX on ttyI%d\n",
2530 info->line);
2531#endif
2532 /* voice-recording, add DLE-ETX */
2533 isdn_tty_at_cout("\020\003", info);
2534 }
2535 if (info->vonline & 2) {
2536#ifdef ISDN_DEBUG_MODEM_VOICE
2537 printk(KERN_DEBUG "res3: send DLE-DC4 on ttyI%d\n",
2538 info->line);
2539#endif
2540 /* voice-playing, add DLE-DC4 */
2541 isdn_tty_at_cout("\020\024", info);
2542 }
2543#endif
2544 break;
2545 case RESULT_CONNECT:
2546 case RESULT_CONNECT64000:
2547 sprintf(info->last_cause, "0000");
2548 if (!info->online)
2549 info->online = 2;
2550 break;
2551 case RESULT_VCON:
2552#ifdef ISDN_DEBUG_MODEM_VOICE
2553 printk(KERN_DEBUG "res3: send VCON on ttyI%d\n",
2554 info->line);
2555#endif
2556 sprintf(info->last_cause, "0000");
2557 if (!info->online)
2558 info->online = 1;
2559 break;
2560 } /* switch(code) */
2561
2562 if (m->mdmreg[REG_RESP] & BIT_RESP) {
2563 /* Show results */
2564 if (m->mdmreg[REG_RESPNUM] & BIT_RESPNUM) {
2565 /* Show numeric results only */
2566 sprintf(s, "\r\n%d\r\n", code);
2567 isdn_tty_at_cout(s, info);
2568 } else {
2569 if (code == RESULT_RING) {
2570 /* return if "show RUNG" and ringcounter>1 */
2571 if ((m->mdmreg[REG_RUNG] & BIT_RUNG) &&
2572 (m->mdmreg[REG_RINGCNT] > 1))
2573 return;
2574 /* print CID, _before_ _every_ ring */
2575 if (!(m->mdmreg[REG_CIDONCE] & BIT_CIDONCE)) {
2576 isdn_tty_at_cout("\r\nCALLER NUMBER: ", info);
2577 isdn_tty_at_cout(dev->num[info->drv_index], info);
2578 if (m->mdmreg[REG_CDN] & BIT_CDN) {
2579 isdn_tty_at_cout("\r\nCALLED NUMBER: ", info);
2580 isdn_tty_at_cout(info->emu.cpn, info);
2581 }
2582 }
2583 }
2584 isdn_tty_at_cout("\r\n", info);
2585 isdn_tty_at_cout(msg[code], info);
2586 switch (code) {
2587 case RESULT_CONNECT:
2588 switch (m->mdmreg[REG_L2PROT]) {
2589 case ISDN_PROTO_L2_MODEM:
2590 isdn_tty_at_cout(" ", info);
2591 isdn_tty_at_cout(m->connmsg, info);
2592 break;
2593 }
2594 break;
2595 case RESULT_RING:
2596 /* Append CPN, if enabled */
2597 if ((m->mdmreg[REG_CPN] & BIT_CPN)) {
2598 sprintf(s, "/%s", m->cpn);
2599 isdn_tty_at_cout(s, info);
2600 }
2601 /* Print CID only once, _after_ 1st RING */
2602 if ((m->mdmreg[REG_CIDONCE] & BIT_CIDONCE) &&
2603 (m->mdmreg[REG_RINGCNT] == 1)) {
2604 isdn_tty_at_cout("\r\n", info);
2605 isdn_tty_at_cout("CALLER NUMBER: ", info);
2606 isdn_tty_at_cout(dev->num[info->drv_index], info);
2607 if (m->mdmreg[REG_CDN] & BIT_CDN) {
2608 isdn_tty_at_cout("\r\nCALLED NUMBER: ", info);
2609 isdn_tty_at_cout(info->emu.cpn, info);
2610 }
2611 }
2612 break;
2613 case RESULT_NO_CARRIER:
2614 case RESULT_NO_DIALTONE:
2615 case RESULT_BUSY:
2616 case RESULT_NO_ANSWER:
2617 m->mdmreg[REG_RINGCNT] = 0;
2618 /* Append Cause-Message if enabled */
2619 if (m->mdmreg[REG_RESPXT] & BIT_RESPXT) {
2620 sprintf(s, "/%s", info->last_cause);
2621 isdn_tty_at_cout(s, info);
2622 }
2623 break;
2624 case RESULT_CONNECT64000:
2625 /* Append Protocol to CONNECT message */
2626 switch (m->mdmreg[REG_L2PROT]) {
2627 case ISDN_PROTO_L2_X75I:
2628 case ISDN_PROTO_L2_X75UI:
2629 case ISDN_PROTO_L2_X75BUI:
2630 isdn_tty_at_cout("/X.75", info);
2631 break;
2632 case ISDN_PROTO_L2_HDLC:
2633 isdn_tty_at_cout("/HDLC", info);
2634 break;
2635 case ISDN_PROTO_L2_V11096:
2636 isdn_tty_at_cout("/V110/9600", info);
2637 break;
2638 case ISDN_PROTO_L2_V11019:
2639 isdn_tty_at_cout("/V110/19200", info);
2640 break;
2641 case ISDN_PROTO_L2_V11038:
2642 isdn_tty_at_cout("/V110/38400", info);
2643 break;
2644 }
2645 if (m->mdmreg[REG_T70] & BIT_T70) {
2646 isdn_tty_at_cout("/T.70", info);
2647 if (m->mdmreg[REG_T70] & BIT_T70_EXT)
2648 isdn_tty_at_cout("+", info);
2649 }
2650 break;
2651 }
2652 isdn_tty_at_cout("\r\n", info);
2653 }
2654 }
2655 if (code == RESULT_NO_CARRIER) {
2656 if ((info->flags & ISDN_ASYNC_CLOSING) || (!info->tty)) {
2657 return;
2658 }
2659 tty_ldisc_flush(info->tty);
2660 if ((info->flags & ISDN_ASYNC_CHECK_CD) &&
2661 (!((info->flags & ISDN_ASYNC_CALLOUT_ACTIVE) &&
2662 (info->flags & ISDN_ASYNC_CALLOUT_NOHUP)))) {
2663 tty_hangup(info->tty);
2664 }
2665 }
2666}
2667
2668
2669/*
2670 * Display a modem-register-value.
2671 */
2672static void
2673isdn_tty_show_profile(int ridx, modem_info * info)
2674{
2675 char v[6];
2676
2677 sprintf(v, "\r\n%d", info->emu.mdmreg[ridx]);
2678 isdn_tty_at_cout(v, info);
2679}
2680
2681/*
2682 * Get MSN-string from char-pointer, set pointer to end of number
2683 */
2684static void
2685isdn_tty_get_msnstr(char *n, char **p)
2686{
2687 int limit = ISDN_MSNLEN - 1;
2688
2689 while (((*p[0] >= '0' && *p[0] <= '9') ||
2690 /* Why a comma ??? */
2691 (*p[0] == ',') || (*p[0] == ':')) &&
2692 (limit--))
2693 *n++ = *p[0]++;
2694 *n = '\0';
2695}
2696
2697/*
2698 * Get phone-number from modem-commandbuffer
2699 */
2700static void
2701isdn_tty_getdial(char *p, char *q,int cnt)
2702{
2703 int first = 1;
2704 int limit = ISDN_MSNLEN - 1; /* MUST match the size of interface var to avoid
2705 buffer overflow */
2706
2707 while (strchr(" 0123456789,#.*WPTS-", *p) && *p && --cnt>0) {
2708 if ((*p >= '0' && *p <= '9') || ((*p == 'S') && first) ||
2709 (*p == '*') || (*p == '#')) {
2710 *q++ = *p;
2711 limit--;
2712 }
2713 if(!limit)
2714 break;
2715 p++;
2716 first = 0;
2717 }
2718 *q = 0;
2719}
2720
2721#define PARSE_ERROR { isdn_tty_modem_result(RESULT_ERROR, info); return; }
2722#define PARSE_ERROR1 { isdn_tty_modem_result(RESULT_ERROR, info); return 1; }
2723
2724static void
2725isdn_tty_report(modem_info * info)
2726{
2727 atemu *m = &info->emu;
2728 char s[80];
2729
2730 isdn_tty_at_cout("\r\nStatistics of last connection:\r\n\r\n", info);
2731 sprintf(s, " Remote Number: %s\r\n", info->last_num);
2732 isdn_tty_at_cout(s, info);
2733 sprintf(s, " Direction: %s\r\n", info->last_dir ? "outgoing" : "incoming");
2734 isdn_tty_at_cout(s, info);
2735 isdn_tty_at_cout(" Layer-2 Protocol: ", info);
2736 switch (info->last_l2) {
2737 case ISDN_PROTO_L2_X75I:
2738 isdn_tty_at_cout("X.75i", info);
2739 break;
2740 case ISDN_PROTO_L2_X75UI:
2741 isdn_tty_at_cout("X.75ui", info);
2742 break;
2743 case ISDN_PROTO_L2_X75BUI:
2744 isdn_tty_at_cout("X.75bui", info);
2745 break;
2746 case ISDN_PROTO_L2_HDLC:
2747 isdn_tty_at_cout("HDLC", info);
2748 break;
2749 case ISDN_PROTO_L2_V11096:
2750 isdn_tty_at_cout("V.110 9600 Baud", info);
2751 break;
2752 case ISDN_PROTO_L2_V11019:
2753 isdn_tty_at_cout("V.110 19200 Baud", info);
2754 break;
2755 case ISDN_PROTO_L2_V11038:
2756 isdn_tty_at_cout("V.110 38400 Baud", info);
2757 break;
2758 case ISDN_PROTO_L2_TRANS:
2759 isdn_tty_at_cout("transparent", info);
2760 break;
2761 case ISDN_PROTO_L2_MODEM:
2762 isdn_tty_at_cout("modem", info);
2763 break;
2764 case ISDN_PROTO_L2_FAX:
2765 isdn_tty_at_cout("fax", info);
2766 break;
2767 default:
2768 isdn_tty_at_cout("unknown", info);
2769 break;
2770 }
2771 if (m->mdmreg[REG_T70] & BIT_T70) {
2772 isdn_tty_at_cout("/T.70", info);
2773 if (m->mdmreg[REG_T70] & BIT_T70_EXT)
2774 isdn_tty_at_cout("+", info);
2775 }
2776 isdn_tty_at_cout("\r\n", info);
2777 isdn_tty_at_cout(" Service: ", info);
2778 switch (info->last_si) {
2779 case 1:
2780 isdn_tty_at_cout("audio\r\n", info);
2781 break;
2782 case 5:
2783 isdn_tty_at_cout("btx\r\n", info);
2784 break;
2785 case 7:
2786 isdn_tty_at_cout("data\r\n", info);
2787 break;
2788 default:
2789 sprintf(s, "%d\r\n", info->last_si);
2790 isdn_tty_at_cout(s, info);
2791 break;
2792 }
2793 sprintf(s, " Hangup location: %s\r\n", info->last_lhup ? "local" : "remote");
2794 isdn_tty_at_cout(s, info);
2795 sprintf(s, " Last cause: %s\r\n", info->last_cause);
2796 isdn_tty_at_cout(s, info);
2797}
2798
2799/*
2800 * Parse AT&.. commands.
2801 */
2802static int
2803isdn_tty_cmd_ATand(char **p, modem_info * info)
2804{
2805 atemu *m = &info->emu;
2806 int i;
2807 char rb[100];
2808
2809#define MAXRB (sizeof(rb) - 1)
2810
2811 switch (*p[0]) {
2812 case 'B':
2813 /* &B - Set Buffersize */
2814 p[0]++;
2815 i = isdn_getnum(p);
2816 if ((i < 0) || (i > ISDN_SERIAL_XMIT_MAX))
2817 PARSE_ERROR1;
2818#ifdef CONFIG_ISDN_AUDIO
2819 if ((m->mdmreg[REG_SI1] & 1) && (i > VBUF))
2820 PARSE_ERROR1;
2821#endif
2822 m->mdmreg[REG_PSIZE] = i / 16;
2823 info->xmit_size = m->mdmreg[REG_PSIZE] * 16;
2824 switch (m->mdmreg[REG_L2PROT]) {
2825 case ISDN_PROTO_L2_V11096:
2826 case ISDN_PROTO_L2_V11019:
2827 case ISDN_PROTO_L2_V11038:
2828 info->xmit_size /= 10;
2829 }
2830 break;
2831 case 'C':
2832 /* &C - DCD Status */
2833 p[0]++;
2834 switch (isdn_getnum(p)) {
2835 case 0:
2836 m->mdmreg[REG_DCD] &= ~BIT_DCD;
2837 break;
2838 case 1:
2839 m->mdmreg[REG_DCD] |= BIT_DCD;
2840 break;
2841 default:
2842 PARSE_ERROR1
2843 }
2844 break;
2845 case 'D':
2846 /* &D - Set DTR-Low-behavior */
2847 p[0]++;
2848 switch (isdn_getnum(p)) {
2849 case 0:
2850 m->mdmreg[REG_DTRHUP] &= ~BIT_DTRHUP;
2851 m->mdmreg[REG_DTRR] &= ~BIT_DTRR;
2852 break;
2853 case 2:
2854 m->mdmreg[REG_DTRHUP] |= BIT_DTRHUP;
2855 m->mdmreg[REG_DTRR] &= ~BIT_DTRR;
2856 break;
2857 case 3:
2858 m->mdmreg[REG_DTRHUP] |= BIT_DTRHUP;
2859 m->mdmreg[REG_DTRR] |= BIT_DTRR;
2860 break;
2861 default:
2862 PARSE_ERROR1
2863 }
2864 break;
2865 case 'E':
2866 /* &E -Set EAZ/MSN */
2867 p[0]++;
2868 isdn_tty_get_msnstr(m->msn, p);
2869 break;
2870 case 'F':
2871 /* &F -Set Factory-Defaults */
2872 p[0]++;
2873 if (info->msr & UART_MSR_DCD)
2874 PARSE_ERROR1;
2875 isdn_tty_reset_profile(m);
2876 isdn_tty_modem_reset_regs(info, 1);
2877 break;
2878#ifdef DUMMY_HAYES_AT
2879 case 'K':
2880 /* only for be compilant with common scripts */
2881 /* &K Flowcontrol - no function */
2882 p[0]++;
2883 isdn_getnum(p);
2884 break;
2885#endif
2886 case 'L':
2887 /* &L -Set Numbers to listen on */
2888 p[0]++;
2889 i = 0;
2890 while (*p[0] && (strchr("0123456789,-*[]?;", *p[0])) &&
2891 (i < ISDN_LMSNLEN))
2892 m->lmsn[i++] = *p[0]++;
2893 m->lmsn[i] = '\0';
2894 break;
2895 case 'R':
2896 /* &R - Set V.110 bitrate adaption */
2897 p[0]++;
2898 i = isdn_getnum(p);
2899 switch (i) {
2900 case 0:
2901 /* Switch off V.110, back to X.75 */
2902 m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_X75I;
2903 m->mdmreg[REG_SI2] = 0;
2904 info->xmit_size = m->mdmreg[REG_PSIZE] * 16;
2905 break;
2906 case 9600:
2907 m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_V11096;
2908 m->mdmreg[REG_SI2] = 197;
2909 info->xmit_size = m->mdmreg[REG_PSIZE] * 16 / 10;
2910 break;
2911 case 19200:
2912 m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_V11019;
2913 m->mdmreg[REG_SI2] = 199;
2914 info->xmit_size = m->mdmreg[REG_PSIZE] * 16 / 10;
2915 break;
2916 case 38400:
2917 m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_V11038;
2918 m->mdmreg[REG_SI2] = 198; /* no existing standard for this */
2919 info->xmit_size = m->mdmreg[REG_PSIZE] * 16 / 10;
2920 break;
2921 default:
2922 PARSE_ERROR1;
2923 }
2924 /* Switch off T.70 */
2925 m->mdmreg[REG_T70] &= ~(BIT_T70 | BIT_T70_EXT);
2926 /* Set Service 7 */
2927 m->mdmreg[REG_SI1] |= 4;
2928 break;
2929 case 'S':
2930 /* &S - Set Windowsize */
2931 p[0]++;
2932 i = isdn_getnum(p);
2933 if ((i > 0) && (i < 9))
2934 m->mdmreg[REG_WSIZE] = i;
2935 else
2936 PARSE_ERROR1;
2937 break;
2938 case 'V':
2939 /* &V - Show registers */
2940 p[0]++;
2941 isdn_tty_at_cout("\r\n", info);
2942 for (i = 0; i < ISDN_MODEM_NUMREG; i++) {
2943 sprintf(rb, "S%02d=%03d%s", i,
2944 m->mdmreg[i], ((i + 1) % 10) ? " " : "\r\n");
2945 isdn_tty_at_cout(rb, info);
2946 }
2947 sprintf(rb, "\r\nEAZ/MSN: %.50s\r\n",
2948 strlen(m->msn) ? m->msn : "None");
2949 isdn_tty_at_cout(rb, info);
2950 if (strlen(m->lmsn)) {
2951 isdn_tty_at_cout("\r\nListen: ", info);
2952 isdn_tty_at_cout(m->lmsn, info);
2953 isdn_tty_at_cout("\r\n", info);
2954 }
2955 break;
2956 case 'W':
2957 /* &W - Write Profile */
2958 p[0]++;
2959 switch (*p[0]) {
2960 case '0':
2961 p[0]++;
2962 modem_write_profile(m);
2963 break;
2964 default:
2965 PARSE_ERROR1;
2966 }
2967 break;
2968 case 'X':
2969 /* &X - Switch to BTX-Mode and T.70 */
2970 p[0]++;
2971 switch (isdn_getnum(p)) {
2972 case 0:
2973 m->mdmreg[REG_T70] &= ~(BIT_T70 | BIT_T70_EXT);
2974 info->xmit_size = m->mdmreg[REG_PSIZE] * 16;
2975 break;
2976 case 1:
2977 m->mdmreg[REG_T70] |= BIT_T70;
2978 m->mdmreg[REG_T70] &= ~BIT_T70_EXT;
2979 m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_X75I;
2980 info->xmit_size = 112;
2981 m->mdmreg[REG_SI1] = 4;
2982 m->mdmreg[REG_SI2] = 0;
2983 break;
2984 case 2:
2985 m->mdmreg[REG_T70] |= (BIT_T70 | BIT_T70_EXT);
2986 m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_X75I;
2987 info->xmit_size = 112;
2988 m->mdmreg[REG_SI1] = 4;
2989 m->mdmreg[REG_SI2] = 0;
2990 break;
2991 default:
2992 PARSE_ERROR1;
2993 }
2994 break;
2995 default:
2996 PARSE_ERROR1;
2997 }
2998 return 0;
2999}
3000
3001static int
3002isdn_tty_check_ats(int mreg, int mval, modem_info * info, atemu * m)
3003{
3004 /* Some plausibility checks */
3005 switch (mreg) {
3006 case REG_L2PROT:
3007 if (mval > ISDN_PROTO_L2_MAX)
3008 return 1;
3009 break;
3010 case REG_PSIZE:
3011 if ((mval * 16) > ISDN_SERIAL_XMIT_MAX)
3012 return 1;
3013#ifdef CONFIG_ISDN_AUDIO
3014 if ((m->mdmreg[REG_SI1] & 1) && (mval > VBUFX))
3015 return 1;
3016#endif
3017 info->xmit_size = mval * 16;
3018 switch (m->mdmreg[REG_L2PROT]) {
3019 case ISDN_PROTO_L2_V11096:
3020 case ISDN_PROTO_L2_V11019:
3021 case ISDN_PROTO_L2_V11038:
3022 info->xmit_size /= 10;
3023 }
3024 break;
3025 case REG_SI1I:
3026 case REG_PLAN:
3027 case REG_SCREEN:
3028 /* readonly registers */
3029 return 1;
3030 }
3031 return 0;
3032}
3033
3034/*
3035 * Perform ATS command
3036 */
3037static int
3038isdn_tty_cmd_ATS(char **p, modem_info * info)
3039{
3040 atemu *m = &info->emu;
3041 int bitpos;
3042 int mreg;
3043 int mval;
3044 int bval;
3045
3046 mreg = isdn_getnum(p);
3047 if (mreg < 0 || mreg >= ISDN_MODEM_NUMREG)
3048 PARSE_ERROR1;
3049 switch (*p[0]) {
3050 case '=':
3051 p[0]++;
3052 mval = isdn_getnum(p);
3053 if (mval < 0 || mval > 255)
3054 PARSE_ERROR1;
3055 if (isdn_tty_check_ats(mreg, mval, info, m))
3056 PARSE_ERROR1;
3057 m->mdmreg[mreg] = mval;
3058 break;
3059 case '.':
3060 /* Set/Clear a single bit */
3061 p[0]++;
3062 bitpos = isdn_getnum(p);
3063 if ((bitpos < 0) || (bitpos > 7))
3064 PARSE_ERROR1;
3065 switch (*p[0]) {
3066 case '=':
3067 p[0]++;
3068 bval = isdn_getnum(p);
3069 if (bval < 0 || bval > 1)
3070 PARSE_ERROR1;
3071 if (bval)
3072 mval = m->mdmreg[mreg] | (1 << bitpos);
3073 else
3074 mval = m->mdmreg[mreg] & ~(1 << bitpos);
3075 if (isdn_tty_check_ats(mreg, mval, info, m))
3076 PARSE_ERROR1;
3077 m->mdmreg[mreg] = mval;
3078 break;
3079 case '?':
3080 p[0]++;
3081 isdn_tty_at_cout("\r\n", info);
3082 isdn_tty_at_cout((m->mdmreg[mreg] & (1 << bitpos)) ? "1" : "0",
3083 info);
3084 break;
3085 default:
3086 PARSE_ERROR1;
3087 }
3088 break;
3089 case '?':
3090 p[0]++;
3091 isdn_tty_show_profile(mreg, info);
3092 break;
3093 default:
3094 PARSE_ERROR1;
3095 break;
3096 }
3097 return 0;
3098}
3099
3100/*
3101 * Perform ATA command
3102 */
3103static void
3104isdn_tty_cmd_ATA(modem_info * info)
3105{
3106 atemu *m = &info->emu;
3107 isdn_ctrl cmd;
3108 int l2;
3109
3110 if (info->msr & UART_MSR_RI) {
3111 /* Accept incoming call */
3112 info->last_dir = 0;
3113 strcpy(info->last_num, dev->num[info->drv_index]);
3114 m->mdmreg[REG_RINGCNT] = 0;
3115 info->msr &= ~UART_MSR_RI;
3116 l2 = m->mdmreg[REG_L2PROT];
3117#ifdef CONFIG_ISDN_AUDIO
3118 /* If more than one bit set in reg18, autoselect Layer2 */
3119 if ((m->mdmreg[REG_SI1] & m->mdmreg[REG_SI1I]) != m->mdmreg[REG_SI1]) {
3120 if (m->mdmreg[REG_SI1I] == 1) {
3121 if ((l2 != ISDN_PROTO_L2_MODEM) && (l2 != ISDN_PROTO_L2_FAX))
3122 l2 = ISDN_PROTO_L2_TRANS;
3123 } else
3124 l2 = ISDN_PROTO_L2_X75I;
3125 }
3126#endif
3127 cmd.driver = info->isdn_driver;
3128 cmd.command = ISDN_CMD_SETL2;
3129 cmd.arg = info->isdn_channel + (l2 << 8);
3130 info->last_l2 = l2;
3131 isdn_command(&cmd);
3132 cmd.driver = info->isdn_driver;
3133 cmd.command = ISDN_CMD_SETL3;
3134 cmd.arg = info->isdn_channel + (m->mdmreg[REG_L3PROT] << 8);
3135#ifdef CONFIG_ISDN_TTY_FAX
3136 if (l2 == ISDN_PROTO_L2_FAX) {
3137 cmd.parm.fax = info->fax;
3138 info->fax->direction = ISDN_TTY_FAX_CONN_IN;
3139 }
3140#endif
3141 isdn_command(&cmd);
3142 cmd.driver = info->isdn_driver;
3143 cmd.arg = info->isdn_channel;
3144 cmd.command = ISDN_CMD_ACCEPTD;
3145 info->dialing = 16;
3146 info->emu.carrierwait = 0;
3147 isdn_command(&cmd);
3148 isdn_timer_ctrl(ISDN_TIMER_CARRIER, 1);
3149 } else
3150 isdn_tty_modem_result(RESULT_NO_ANSWER, info);
3151}
3152
3153#ifdef CONFIG_ISDN_AUDIO
3154/*
3155 * Parse AT+F.. commands
3156 */
3157static int
3158isdn_tty_cmd_PLUSF(char **p, modem_info * info)
3159{
3160 atemu *m = &info->emu;
3161 char rs[20];
3162
3163 if (!strncmp(p[0], "CLASS", 5)) {
3164 p[0] += 5;
3165 switch (*p[0]) {
3166 case '?':
3167 p[0]++;
3168 sprintf(rs, "\r\n%d",
3169 (m->mdmreg[REG_SI1] & 1) ? 8 : 0);
3170#ifdef CONFIG_ISDN_TTY_FAX
3171 if (TTY_IS_FCLASS2(info))
3172 sprintf(rs, "\r\n2");
3173 else if (TTY_IS_FCLASS1(info))
3174 sprintf(rs, "\r\n1");
3175#endif
3176 isdn_tty_at_cout(rs, info);
3177 break;
3178 case '=':
3179 p[0]++;
3180 switch (*p[0]) {
3181 case '0':
3182 p[0]++;
3183 m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_X75I;
3184 m->mdmreg[REG_L3PROT] = ISDN_PROTO_L3_TRANS;
3185 m->mdmreg[REG_SI1] = 4;
3186 info->xmit_size =
3187 m->mdmreg[REG_PSIZE] * 16;
3188 break;
3189#ifdef CONFIG_ISDN_TTY_FAX
3190 case '1':
3191 p[0]++;
3192 if (!(dev->global_features &
3193 ISDN_FEATURE_L3_FCLASS1))
3194 PARSE_ERROR1;
3195 m->mdmreg[REG_SI1] = 1;
3196 m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_FAX;
3197 m->mdmreg[REG_L3PROT] = ISDN_PROTO_L3_FCLASS1;
3198 info->xmit_size =
3199 m->mdmreg[REG_PSIZE] * 16;
3200 break;
3201 case '2':
3202 p[0]++;
3203 if (!(dev->global_features &
3204 ISDN_FEATURE_L3_FCLASS2))
3205 PARSE_ERROR1;
3206 m->mdmreg[REG_SI1] = 1;
3207 m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_FAX;
3208 m->mdmreg[REG_L3PROT] = ISDN_PROTO_L3_FCLASS2;
3209 info->xmit_size =
3210 m->mdmreg[REG_PSIZE] * 16;
3211 break;
3212#endif
3213 case '8':
3214 p[0]++;
3215 /* L2 will change on dialout with si=1 */
3216 m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_X75I;
3217 m->mdmreg[REG_L3PROT] = ISDN_PROTO_L3_TRANS;
3218 m->mdmreg[REG_SI1] = 5;
3219 info->xmit_size = VBUF;
3220 break;
3221 case '?':
3222 p[0]++;
3223 strcpy(rs, "\r\n0,");
3224#ifdef CONFIG_ISDN_TTY_FAX
3225 if (dev->global_features &
3226 ISDN_FEATURE_L3_FCLASS1)
3227 strcat(rs, "1,");
3228 if (dev->global_features &
3229 ISDN_FEATURE_L3_FCLASS2)
3230 strcat(rs, "2,");
3231#endif
3232 strcat(rs, "8");
3233 isdn_tty_at_cout(rs, info);
3234 break;
3235 default:
3236 PARSE_ERROR1;
3237 }
3238 break;
3239 default:
3240 PARSE_ERROR1;
3241 }
3242 return 0;
3243 }
3244#ifdef CONFIG_ISDN_TTY_FAX
3245 return (isdn_tty_cmd_PLUSF_FAX(p, info));
3246#else
3247 PARSE_ERROR1;
3248#endif
3249}
3250
3251/*
3252 * Parse AT+V.. commands
3253 */
3254static int
3255isdn_tty_cmd_PLUSV(char **p, modem_info * info)
3256{
3257 atemu *m = &info->emu;
3258 isdn_ctrl cmd;
3259 static char *vcmd[] =
3260 {"NH", "IP", "LS", "RX", "SD", "SM", "TX", "DD", NULL};
3261 int i;
3262 int par1;
3263 int par2;
3264 char rs[20];
3265
3266 i = 0;
3267 while (vcmd[i]) {
3268 if (!strncmp(vcmd[i], p[0], 2)) {
3269 p[0] += 2;
3270 break;
3271 }
3272 i++;
3273 }
3274 switch (i) {
3275 case 0:
3276 /* AT+VNH - Auto hangup feature */
3277 switch (*p[0]) {
3278 case '?':
3279 p[0]++;
3280 isdn_tty_at_cout("\r\n1", info);
3281 break;
3282 case '=':
3283 p[0]++;
3284 switch (*p[0]) {
3285 case '1':
3286 p[0]++;
3287 break;
3288 case '?':
3289 p[0]++;
3290 isdn_tty_at_cout("\r\n1", info);
3291 break;
3292 default:
3293 PARSE_ERROR1;
3294 }
3295 break;
3296 default:
3297 PARSE_ERROR1;
3298 }
3299 break;
3300 case 1:
3301 /* AT+VIP - Reset all voice parameters */
3302 isdn_tty_modem_reset_vpar(m);
3303 break;
3304 case 2:
3305 /* AT+VLS - Select device, accept incoming call */
3306 switch (*p[0]) {
3307 case '?':
3308 p[0]++;
3309 sprintf(rs, "\r\n%d", m->vpar[0]);
3310 isdn_tty_at_cout(rs, info);
3311 break;
3312 case '=':
3313 p[0]++;
3314 switch (*p[0]) {
3315 case '0':
3316 p[0]++;
3317 m->vpar[0] = 0;
3318 break;
3319 case '2':
3320 p[0]++;
3321 m->vpar[0] = 2;
3322 break;
3323 case '?':
3324 p[0]++;
3325 isdn_tty_at_cout("\r\n0,2", info);
3326 break;
3327 default:
3328 PARSE_ERROR1;
3329 }
3330 break;
3331 default:
3332 PARSE_ERROR1;
3333 }
3334 break;
3335 case 3:
3336 /* AT+VRX - Start recording */
3337 if (!m->vpar[0])
3338 PARSE_ERROR1;
3339 if (info->online != 1) {
3340 isdn_tty_modem_result(RESULT_NO_ANSWER, info);
3341 return 1;
3342 }
3343 info->dtmf_state = isdn_audio_dtmf_init(info->dtmf_state);
3344 if (!info->dtmf_state) {
3345 printk(KERN_WARNING "isdn_tty: Couldn't malloc dtmf state\n");
3346 PARSE_ERROR1;
3347 }
3348 info->silence_state = isdn_audio_silence_init(info->silence_state);
3349 if (!info->silence_state) {
3350 printk(KERN_WARNING "isdn_tty: Couldn't malloc silence state\n");
3351 PARSE_ERROR1;
3352 }
3353 if (m->vpar[3] < 5) {
3354 info->adpcmr = isdn_audio_adpcm_init(info->adpcmr, m->vpar[3]);
3355 if (!info->adpcmr) {
3356 printk(KERN_WARNING "isdn_tty: Couldn't malloc adpcm state\n");
3357 PARSE_ERROR1;
3358 }
3359 }
3360#ifdef ISDN_DEBUG_AT
3361 printk(KERN_DEBUG "AT: +VRX\n");
3362#endif
3363 info->vonline |= 1;
3364 isdn_tty_modem_result(RESULT_CONNECT, info);
3365 return 0;
3366 break;
3367 case 4:
3368 /* AT+VSD - Silence detection */
3369 switch (*p[0]) {
3370 case '?':
3371 p[0]++;
3372 sprintf(rs, "\r\n<%d>,<%d>",
3373 m->vpar[1],
3374 m->vpar[2]);
3375 isdn_tty_at_cout(rs, info);
3376 break;
3377 case '=':
3378 p[0]++;
3379 if ((*p[0]>='0') && (*p[0]<='9')) {
3380 par1 = isdn_getnum(p);
3381 if ((par1 < 0) || (par1 > 31))
3382 PARSE_ERROR1;
3383 if (*p[0] != ',')
3384 PARSE_ERROR1;
3385 p[0]++;
3386 par2 = isdn_getnum(p);
3387 if ((par2 < 0) || (par2 > 255))
3388 PARSE_ERROR1;
3389 m->vpar[1] = par1;
3390 m->vpar[2] = par2;
3391 break;
3392 } else
3393 if (*p[0] == '?') {
3394 p[0]++;
3395 isdn_tty_at_cout("\r\n<0-31>,<0-255>",
3396 info);
3397 break;
3398 } else
3399 PARSE_ERROR1;
3400 break;
3401 default:
3402 PARSE_ERROR1;
3403 }
3404 break;
3405 case 5:
3406 /* AT+VSM - Select compression */
3407 switch (*p[0]) {
3408 case '?':
3409 p[0]++;
3410 sprintf(rs, "\r\n<%d>,<%d><8000>",
3411 m->vpar[3],
3412 m->vpar[1]);
3413 isdn_tty_at_cout(rs, info);
3414 break;
3415 case '=':
3416 p[0]++;
3417 switch (*p[0]) {
3418 case '2':
3419 case '3':
3420 case '4':
3421 case '5':
3422 case '6':
3423 par1 = isdn_getnum(p);
3424 if ((par1 < 2) || (par1 > 6))
3425 PARSE_ERROR1;
3426 m->vpar[3] = par1;
3427 break;
3428 case '?':
3429 p[0]++;
3430 isdn_tty_at_cout("\r\n2;ADPCM;2;0;(8000)\r\n",
3431 info);
3432 isdn_tty_at_cout("3;ADPCM;3;0;(8000)\r\n",
3433 info);
3434 isdn_tty_at_cout("4;ADPCM;4;0;(8000)\r\n",
3435 info);
3436 isdn_tty_at_cout("5;ALAW;8;0;(8000)\r\n",
3437 info);
3438 isdn_tty_at_cout("6;ULAW;8;0;(8000)\r\n",
3439 info);
3440 break;
3441 default:
3442 PARSE_ERROR1;
3443 }
3444 break;
3445 default:
3446 PARSE_ERROR1;
3447 }
3448 break;
3449 case 6:
3450 /* AT+VTX - Start sending */
3451 if (!m->vpar[0])
3452 PARSE_ERROR1;
3453 if (info->online != 1) {
3454 isdn_tty_modem_result(RESULT_NO_ANSWER, info);
3455 return 1;
3456 }
3457 info->dtmf_state = isdn_audio_dtmf_init(info->dtmf_state);
3458 if (!info->dtmf_state) {
3459 printk(KERN_WARNING "isdn_tty: Couldn't malloc dtmf state\n");
3460 PARSE_ERROR1;
3461 }
3462 if (m->vpar[3] < 5) {
3463 info->adpcms = isdn_audio_adpcm_init(info->adpcms, m->vpar[3]);
3464 if (!info->adpcms) {
3465 printk(KERN_WARNING "isdn_tty: Couldn't malloc adpcm state\n");
3466 PARSE_ERROR1;
3467 }
3468 }
3469#ifdef ISDN_DEBUG_AT
3470 printk(KERN_DEBUG "AT: +VTX\n");
3471#endif
3472 m->lastDLE = 0;
3473 info->vonline |= 2;
3474 isdn_tty_modem_result(RESULT_CONNECT, info);
3475 return 0;
3476 break;
3477 case 7:
3478 /* AT+VDD - DTMF detection */
3479 switch (*p[0]) {
3480 case '?':
3481 p[0]++;
3482 sprintf(rs, "\r\n<%d>,<%d>",
3483 m->vpar[4],
3484 m->vpar[5]);
3485 isdn_tty_at_cout(rs, info);
3486 break;
3487 case '=':
3488 p[0]++;
3489 if ((*p[0]>='0') && (*p[0]<='9')) {
3490 if (info->online != 1)
3491 PARSE_ERROR1;
3492 par1 = isdn_getnum(p);
3493 if ((par1 < 0) || (par1 > 15))
3494 PARSE_ERROR1;
3495 if (*p[0] != ',')
3496 PARSE_ERROR1;
3497 p[0]++;
3498 par2 = isdn_getnum(p);
3499 if ((par2 < 0) || (par2 > 255))
3500 PARSE_ERROR1;
3501 m->vpar[4] = par1;
3502 m->vpar[5] = par2;
3503 cmd.driver = info->isdn_driver;
3504 cmd.command = ISDN_CMD_AUDIO;
3505 cmd.arg = info->isdn_channel + (ISDN_AUDIO_SETDD << 8);
3506 cmd.parm.num[0] = par1;
3507 cmd.parm.num[1] = par2;
3508 isdn_command(&cmd);
3509 break;
3510 } else
3511 if (*p[0] == '?') {
3512 p[0]++;
3513 isdn_tty_at_cout("\r\n<0-15>,<0-255>",
3514 info);
3515 break;
3516 } else
3517 PARSE_ERROR1;
3518 break;
3519 default:
3520 PARSE_ERROR1;
3521 }
3522 break;
3523 default:
3524 PARSE_ERROR1;
3525 }
3526 return 0;
3527}
3528#endif /* CONFIG_ISDN_AUDIO */
3529
3530/*
3531 * Parse and perform an AT-command-line.
3532 */
3533static void
3534isdn_tty_parse_at(modem_info * info)
3535{
3536 atemu *m = &info->emu;
3537 char *p;
3538 char ds[40];
3539
3540#ifdef ISDN_DEBUG_AT
3541 printk(KERN_DEBUG "AT: '%s'\n", m->mdmcmd);
3542#endif
3543 for (p = &m->mdmcmd[2]; *p;) {
3544 switch (*p) {
3545 case ' ':
3546 p++;
3547 break;
3548 case 'A':
3549 /* A - Accept incoming call */
3550 p++;
3551 isdn_tty_cmd_ATA(info);
3552 return;
3553 break;
3554 case 'D':
3555 /* D - Dial */
3556 if (info->msr & UART_MSR_DCD)
3557 PARSE_ERROR;
3558 if (info->msr & UART_MSR_RI) {
3559 isdn_tty_modem_result(RESULT_NO_CARRIER, info);
3560 return;
3561 }
3562 isdn_tty_getdial(++p, ds, sizeof ds);
3563 p += strlen(p);
3564 if (!strlen(m->msn))
3565 isdn_tty_modem_result(RESULT_NO_MSN_EAZ, info);
3566 else if (strlen(ds))
3567 isdn_tty_dial(ds, info, m);
3568 else
3569 PARSE_ERROR;
3570 return;
3571 case 'E':
3572 /* E - Turn Echo on/off */
3573 p++;
3574 switch (isdn_getnum(&p)) {
3575 case 0:
3576 m->mdmreg[REG_ECHO] &= ~BIT_ECHO;
3577 break;
3578 case 1:
3579 m->mdmreg[REG_ECHO] |= BIT_ECHO;
3580 break;
3581 default:
3582 PARSE_ERROR;
3583 }
3584 break;
3585 case 'H':
3586 /* H - On/Off-hook */
3587 p++;
3588 switch (*p) {
3589 case '0':
3590 p++;
3591 isdn_tty_on_hook(info);
3592 break;
3593 case '1':
3594 p++;
3595 isdn_tty_off_hook();
3596 break;
3597 default:
3598 isdn_tty_on_hook(info);
3599 break;
3600 }
3601 break;
3602 case 'I':
3603 /* I - Information */
3604 p++;
3605 isdn_tty_at_cout("\r\nLinux ISDN", info);
3606 switch (*p) {
3607 case '0':
3608 case '1':
3609 p++;
3610 break;
3611 case '2':
3612 p++;
3613 isdn_tty_report(info);
3614 break;
3615 case '3':
3616 p++;
3617 sprintf(ds, "\r\n%d", info->emu.charge);
3618 isdn_tty_at_cout(ds, info);
3619 break;
3620 default:;
3621 }
3622 break;
3623#ifdef DUMMY_HAYES_AT
3624 case 'L':
3625 case 'M':
3626 /* only for be compilant with common scripts */
3627 /* no function */
3628 p++;
3629 isdn_getnum(&p);
3630 break;
3631#endif
3632 case 'O':
3633 /* O - Go online */
3634 p++;
3635 if (info->msr & UART_MSR_DCD)
3636 /* if B-Channel is up */
3637 isdn_tty_modem_result((m->mdmreg[REG_L2PROT] == ISDN_PROTO_L2_MODEM) ? RESULT_CONNECT:RESULT_CONNECT64000, info);
3638 else
3639 isdn_tty_modem_result(RESULT_NO_CARRIER, info);
3640 return;
3641 case 'Q':
3642 /* Q - Turn Emulator messages on/off */
3643 p++;
3644 switch (isdn_getnum(&p)) {
3645 case 0:
3646 m->mdmreg[REG_RESP] |= BIT_RESP;
3647 break;
3648 case 1:
3649 m->mdmreg[REG_RESP] &= ~BIT_RESP;
3650 break;
3651 default:
3652 PARSE_ERROR;
3653 }
3654 break;
3655 case 'S':
3656 /* S - Set/Get Register */
3657 p++;
3658 if (isdn_tty_cmd_ATS(&p, info))
3659 return;
3660 break;
3661 case 'V':
3662 /* V - Numeric or ASCII Emulator-messages */
3663 p++;
3664 switch (isdn_getnum(&p)) {
3665 case 0:
3666 m->mdmreg[REG_RESP] |= BIT_RESPNUM;
3667 break;
3668 case 1:
3669 m->mdmreg[REG_RESP] &= ~BIT_RESPNUM;
3670 break;
3671 default:
3672 PARSE_ERROR;
3673 }
3674 break;
3675 case 'Z':
3676 /* Z - Load Registers from Profile */
3677 p++;
3678 if (info->msr & UART_MSR_DCD) {
3679 info->online = 0;
3680 isdn_tty_on_hook(info);
3681 }
3682 isdn_tty_modem_reset_regs(info, 1);
3683 break;
3684 case '+':
3685 p++;
3686 switch (*p) {
3687#ifdef CONFIG_ISDN_AUDIO
3688 case 'F':
3689 p++;
3690 if (isdn_tty_cmd_PLUSF(&p, info))
3691 return;
3692 break;
3693 case 'V':
3694 if ((!(m->mdmreg[REG_SI1] & 1)) ||
3695 (m->mdmreg[REG_L2PROT] == ISDN_PROTO_L2_MODEM))
3696 PARSE_ERROR;
3697 p++;
3698 if (isdn_tty_cmd_PLUSV(&p, info))
3699 return;
3700 break;
3701#endif /* CONFIG_ISDN_AUDIO */
3702 case 'S': /* SUSPEND */
3703 p++;
3704 isdn_tty_get_msnstr(ds, &p);
3705 isdn_tty_suspend(ds, info, m);
3706 break;
3707 case 'R': /* RESUME */
3708 p++;
3709 isdn_tty_get_msnstr(ds, &p);
3710 isdn_tty_resume(ds, info, m);
3711 break;
3712 case 'M': /* MESSAGE */
3713 p++;
3714 isdn_tty_send_msg(info, m, p);
3715 break;
3716 default:
3717 PARSE_ERROR;
3718 }
3719 break;
3720 case '&':
3721 p++;
3722 if (isdn_tty_cmd_ATand(&p, info))
3723 return;
3724 break;
3725 default:
3726 PARSE_ERROR;
3727 }
3728 }
3729#ifdef CONFIG_ISDN_AUDIO
3730 if (!info->vonline)
3731#endif
3732 isdn_tty_modem_result(RESULT_OK, info);
3733}
3734
3735/* Need own toupper() because standard-toupper is not available
3736 * within modules.
3737 */
3738#define my_toupper(c) (((c>='a')&&(c<='z'))?(c&0xdf):c)
3739
3740/*
3741 * Perform line-editing of AT-commands
3742 *
3743 * Parameters:
3744 * p inputbuffer
3745 * count length of buffer
3746 * channel index to line (minor-device)
3747 */
3748static int
3749isdn_tty_edit_at(const char *p, int count, modem_info * info)
3750{
3751 atemu *m = &info->emu;
3752 int total = 0;
3753 u_char c;
3754 char eb[2];
3755 int cnt;
3756
3757 for (cnt = count; cnt > 0; p++, cnt--) {
3758 c = *p;
3759 total++;
3760 if (c == m->mdmreg[REG_CR] || c == m->mdmreg[REG_LF]) {
3761 /* Separator (CR or LF) */
3762 m->mdmcmd[m->mdmcmdl] = 0;
3763 if (m->mdmreg[REG_ECHO] & BIT_ECHO) {
3764 eb[0] = c;
3765 eb[1] = 0;
3766 isdn_tty_at_cout(eb, info);
3767 }
3768 if ((m->mdmcmdl >= 2) && (!(strncmp(m->mdmcmd, "AT", 2))))
3769 isdn_tty_parse_at(info);
3770 m->mdmcmdl = 0;
3771 continue;
3772 }
3773 if (c == m->mdmreg[REG_BS] && m->mdmreg[REG_BS] < 128) {
3774 /* Backspace-Function */
3775 if ((m->mdmcmdl > 2) || (!m->mdmcmdl)) {
3776 if (m->mdmcmdl)
3777 m->mdmcmdl--;
3778 if (m->mdmreg[REG_ECHO] & BIT_ECHO)
3779 isdn_tty_at_cout("\b", info);
3780 }
3781 continue;
3782 }
3783 if (cmdchar(c)) {
3784 if (m->mdmreg[REG_ECHO] & BIT_ECHO) {
3785 eb[0] = c;
3786 eb[1] = 0;
3787 isdn_tty_at_cout(eb, info);
3788 }
3789 if (m->mdmcmdl < 255) {
3790 c = my_toupper(c);
3791 switch (m->mdmcmdl) {
3792 case 1:
3793 if (c == 'T') {
3794 m->mdmcmd[m->mdmcmdl] = c;
3795 m->mdmcmd[++m->mdmcmdl] = 0;
3796 break;
3797 } else
3798 m->mdmcmdl = 0;
3799 /* Fall through, check for 'A' */
3800 case 0:
3801 if (c == 'A') {
3802 m->mdmcmd[m->mdmcmdl] = c;
3803 m->mdmcmd[++m->mdmcmdl] = 0;
3804 }
3805 break;
3806 default:
3807 m->mdmcmd[m->mdmcmdl] = c;
3808 m->mdmcmd[++m->mdmcmdl] = 0;
3809 }
3810 }
3811 }
3812 }
3813 return total;
3814}
3815
3816/*
3817 * Switch all modem-channels who are online and got a valid
3818 * escape-sequence 1.5 seconds ago, to command-mode.
3819 * This function is called every second via timer-interrupt from within
3820 * timer-dispatcher isdn_timer_function()
3821 */
3822void
3823isdn_tty_modem_escape(void)
3824{
3825 int ton = 0;
3826 int i;
3827 int midx;
3828
3829 for (i = 0; i < ISDN_MAX_CHANNELS; i++)
3830 if (USG_MODEM(dev->usage[i]))
3831 if ((midx = dev->m_idx[i]) >= 0) {
3832 modem_info *info = &dev->mdm.info[midx];
3833 if (info->online) {
3834 ton = 1;
3835 if ((info->emu.pluscount == 3) &&
3836 time_after(jiffies , info->emu.lastplus + PLUSWAIT2)) {
3837 info->emu.pluscount = 0;
3838 info->online = 0;
3839 isdn_tty_modem_result(RESULT_OK, info);
3840 }
3841 }
3842 }
3843 isdn_timer_ctrl(ISDN_TIMER_MODEMPLUS, ton);
3844}
3845
3846/*
3847 * Put a RING-message to all modem-channels who have the RI-bit set.
3848 * This function is called every second via timer-interrupt from within
3849 * timer-dispatcher isdn_timer_function()
3850 */
3851void
3852isdn_tty_modem_ring(void)
3853{
3854 int ton = 0;
3855 int i;
3856
3857 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
3858 modem_info *info = &dev->mdm.info[i];
3859 if (info->msr & UART_MSR_RI) {
3860 ton = 1;
3861 isdn_tty_modem_result(RESULT_RING, info);
3862 }
3863 }
3864 isdn_timer_ctrl(ISDN_TIMER_MODEMRING, ton);
3865}
3866
3867/*
3868 * For all online tty's, try sending data to
3869 * the lower levels.
3870 */
3871void
3872isdn_tty_modem_xmit(void)
3873{
3874 int ton = 1;
3875 int i;
3876
3877 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
3878 modem_info *info = &dev->mdm.info[i];
3879 if (info->online) {
3880 ton = 1;
3881 isdn_tty_senddown(info);
3882 isdn_tty_tint(info);
3883 }
3884 }
3885 isdn_timer_ctrl(ISDN_TIMER_MODEMXMIT, ton);
3886}
3887
3888/*
3889 * Check all channels if we have a 'no carrier' timeout.
3890 * Timeout value is set by Register S7.
3891 */
3892void
3893isdn_tty_carrier_timeout(void)
3894{
3895 int ton = 0;
3896 int i;
3897
3898 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
3899 modem_info *info = &dev->mdm.info[i];
3900 if (info->dialing) {
3901 if (info->emu.carrierwait++ > info->emu.mdmreg[REG_WAITC]) {
3902 info->dialing = 0;
3903 isdn_tty_modem_result(RESULT_NO_CARRIER, info);
3904 isdn_tty_modem_hup(info, 1);
3905 }
3906 else
3907 ton = 1;
3908 }
3909 }
3910 isdn_timer_ctrl(ISDN_TIMER_CARRIER, ton);
3911}
diff --git a/drivers/isdn/i4l/isdn_tty.h b/drivers/isdn/i4l/isdn_tty.h
new file mode 100644
index 000000000000..2423a7ff0cc3
--- /dev/null
+++ b/drivers/isdn/i4l/isdn_tty.h
@@ -0,0 +1,122 @@
1/* $Id: isdn_tty.h,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $
2 *
3 * header for Linux ISDN subsystem, tty related functions (linklevel).
4 *
5 * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de)
6 * Copyright 1995,96 by Thinking Objects Software GmbH Wuerzburg
7 *
8 * This software may be used and distributed according to the terms
9 * of the GNU General Public License, incorporated herein by reference.
10 *
11 */
12
13#include <linux/config.h>
14
15#define DLE 0x10
16#define ETX 0x03
17#define DC4 0x14
18
19
20/*
21 * Definition of some special Registers of AT-Emulator
22 */
23#define REG_RINGATA 0
24#define REG_RINGCNT 1 /* ring counter register */
25#define REG_ESC 2
26#define REG_CR 3
27#define REG_LF 4
28#define REG_BS 5
29
30#define REG_WAITC 7
31
32#define REG_RESP 12 /* show response messages register */
33#define BIT_RESP 1 /* show response messages bit */
34#define REG_RESPNUM 12 /* show numeric responses register */
35#define BIT_RESPNUM 2 /* show numeric responses bit */
36#define REG_ECHO 12
37#define BIT_ECHO 4
38#define REG_DCD 12
39#define BIT_DCD 8
40#define REG_CTS 12
41#define BIT_CTS 16
42#define REG_DTRR 12
43#define BIT_DTRR 32
44#define REG_DSR 12
45#define BIT_DSR 64
46#define REG_CPPP 12
47#define BIT_CPPP 128
48
49#define REG_DXMT 13
50#define BIT_DXMT 1
51#define REG_T70 13
52#define BIT_T70 2
53#define BIT_T70_EXT 32
54#define REG_DTRHUP 13
55#define BIT_DTRHUP 4
56#define REG_RESPXT 13
57#define BIT_RESPXT 8
58#define REG_CIDONCE 13
59#define BIT_CIDONCE 16
60#define REG_RUNG 13 /* show RUNG message register */
61#define BIT_RUNG 64 /* show RUNG message bit */
62#define REG_DISPLAY 13
63#define BIT_DISPLAY 128
64
65#define REG_L2PROT 14
66#define REG_L3PROT 15
67#define REG_PSIZE 16
68#define REG_WSIZE 17
69#define REG_SI1 18
70#define REG_SI2 19
71#define REG_SI1I 20
72#define REG_PLAN 21
73#define REG_SCREEN 22
74
75#define REG_CPN 23
76#define BIT_CPN 1
77#define REG_CPNFCON 23
78#define BIT_CPNFCON 2
79#define REG_CDN 23
80#define BIT_CDN 4
81
82/* defines for result codes */
83#define RESULT_OK 0
84#define RESULT_CONNECT 1
85#define RESULT_RING 2
86#define RESULT_NO_CARRIER 3
87#define RESULT_ERROR 4
88#define RESULT_CONNECT64000 5
89#define RESULT_NO_DIALTONE 6
90#define RESULT_BUSY 7
91#define RESULT_NO_ANSWER 8
92#define RESULT_RINGING 9
93#define RESULT_NO_MSN_EAZ 10
94#define RESULT_VCON 11
95#define RESULT_RUNG 12
96
97#define TTY_IS_FCLASS1(info) \
98 ((info->emu.mdmreg[REG_L2PROT] == ISDN_PROTO_L2_FAX) && \
99 (info->emu.mdmreg[REG_L3PROT] == ISDN_PROTO_L3_FCLASS1))
100#define TTY_IS_FCLASS2(info) \
101 ((info->emu.mdmreg[REG_L2PROT] == ISDN_PROTO_L2_FAX) && \
102 (info->emu.mdmreg[REG_L3PROT] == ISDN_PROTO_L3_FCLASS2))
103
104extern void isdn_tty_modem_escape(void);
105extern void isdn_tty_modem_ring(void);
106extern void isdn_tty_carrier_timeout(void);
107extern void isdn_tty_modem_xmit(void);
108extern int isdn_tty_modem_init(void);
109extern void isdn_tty_exit(void);
110extern void isdn_tty_readmodem(void);
111extern int isdn_tty_find_icall(int, int, setup_parm *);
112extern void isdn_tty_cleanup_xmit(modem_info *);
113extern int isdn_tty_stat_callback(int, isdn_ctrl *);
114extern int isdn_tty_rcv_skb(int, int, int, struct sk_buff *);
115extern int isdn_tty_capi_facility(capi_msg *cm);
116extern void isdn_tty_at_cout(char *, modem_info *);
117extern void isdn_tty_modem_hup(modem_info *, int);
118#ifdef CONFIG_ISDN_TTY_FAX
119extern int isdn_tty_cmd_PLUSF_FAX(char **, modem_info *);
120extern int isdn_tty_fax_command(modem_info *, isdn_ctrl *);
121extern void isdn_tty_fax_bitorder(modem_info *, struct sk_buff *);
122#endif
diff --git a/drivers/isdn/i4l/isdn_ttyfax.c b/drivers/isdn/i4l/isdn_ttyfax.c
new file mode 100644
index 000000000000..ce2c3ef92e46
--- /dev/null
+++ b/drivers/isdn/i4l/isdn_ttyfax.c
@@ -0,0 +1,1122 @@
1/* $Id: isdn_ttyfax.c,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $
2 *
3 * Linux ISDN subsystem, tty_fax AT-command emulator (linklevel).
4 *
5 * Copyright 1999 by Armin Schindler (mac@melware.de)
6 * Copyright 1999 by Ralf Spachmann (mel@melware.de)
7 * Copyright 1999 by Cytronics & Melware
8 *
9 * This software may be used and distributed according to the terms
10 * of the GNU General Public License, incorporated herein by reference.
11 *
12 */
13
14#undef ISDN_TTY_FAX_STAT_DEBUG
15#undef ISDN_TTY_FAX_CMD_DEBUG
16
17#include <linux/isdn.h>
18#include "isdn_common.h"
19#include "isdn_tty.h"
20#include "isdn_ttyfax.h"
21
22
23static char *isdn_tty_fax_revision = "$Revision: 1.1.2.2 $";
24
25#define PARSE_ERROR1 { isdn_tty_fax_modem_result(1, info); return 1; }
26
27static char *
28isdn_getrev(const char *revision)
29{
30 char *rev;
31 char *p;
32
33 if ((p = strchr(revision, ':'))) {
34 rev = p + 2;
35 p = strchr(rev, '$');
36 *--p = 0;
37 } else
38 rev = "???";
39 return rev;
40}
41
42/*
43 * Fax Class 2 Modem results
44 *
45 */
46
47static void
48isdn_tty_fax_modem_result(int code, modem_info * info)
49{
50 atemu *m = &info->emu;
51 T30_s *f = info->fax;
52 char rs[50];
53 char rss[50];
54 char *rp;
55 int i;
56 static char *msg[] =
57 {"OK", "ERROR", "+FCON", "+FCSI:", "+FDIS:",
58 "+FHNG:", "+FDCS:", "CONNECT", "+FTSI:",
59 "+FCFR", "+FPTS:", "+FET:"};
60
61
62 isdn_tty_at_cout("\r\n", info);
63 isdn_tty_at_cout(msg[code], info);
64
65#ifdef ISDN_TTY_FAX_CMD_DEBUG
66 printk(KERN_DEBUG "isdn_tty: Fax send %s on ttyI%d\n",
67 msg[code], info->line);
68#endif
69 switch (code) {
70 case 0: /* OK */
71 break;
72 case 1: /* ERROR */
73 break;
74 case 2: /* +FCON */
75 /* Append CPN, if enabled */
76 if ((m->mdmreg[REG_CPNFCON] & BIT_CPNFCON) &&
77 (!(dev->usage[info->isdn_channel] & ISDN_USAGE_OUTGOING))) {
78 sprintf(rs, "/%s", m->cpn);
79 isdn_tty_at_cout(rs, info);
80 }
81 info->online = 1;
82 f->fet = 0;
83 if (f->phase == ISDN_FAX_PHASE_A)
84 f->phase = ISDN_FAX_PHASE_B;
85 break;
86 case 3: /* +FCSI */
87 case 8: /* +FTSI */
88 sprintf(rs, "\"%s\"", f->r_id);
89 isdn_tty_at_cout(rs, info);
90 break;
91 case 4: /* +FDIS */
92 rs[0] = 0;
93 rp = &f->r_resolution;
94 for (i = 0; i < 8; i++) {
95 sprintf(rss, "%c%s", rp[i] + 48,
96 (i < 7) ? "," : "");
97 strcat(rs, rss);
98 }
99 isdn_tty_at_cout(rs, info);
100#ifdef ISDN_TTY_FAX_CMD_DEBUG
101 printk(KERN_DEBUG "isdn_tty: Fax DIS=%s on ttyI%d\n",
102 rs, info->line);
103#endif
104 break;
105 case 5: /* +FHNG */
106 sprintf(rs, "%d", f->code);
107 isdn_tty_at_cout(rs, info);
108 info->faxonline = 0;
109 break;
110 case 6: /* +FDCS */
111 rs[0] = 0;
112 rp = &f->r_resolution;
113 for (i = 0; i < 8; i++) {
114 sprintf(rss, "%c%s", rp[i] + 48,
115 (i < 7) ? "," : "");
116 strcat(rs, rss);
117 }
118 isdn_tty_at_cout(rs, info);
119#ifdef ISDN_TTY_FAX_CMD_DEBUG
120 printk(KERN_DEBUG "isdn_tty: Fax DCS=%s on ttyI%d\n",
121 rs, info->line);
122#endif
123 break;
124 case 7: /* CONNECT */
125 info->faxonline |= 2;
126 break;
127 case 9: /* FCFR */
128 break;
129 case 10: /* FPTS */
130 isdn_tty_at_cout("1", info);
131 break;
132 case 11: /* FET */
133 sprintf(rs, "%d", f->fet);
134 isdn_tty_at_cout(rs, info);
135 break;
136 }
137
138 isdn_tty_at_cout("\r\n", info);
139
140 switch (code) {
141 case 7: /* CONNECT */
142 info->online = 2;
143 if (info->faxonline & 1) {
144 sprintf(rs, "%c", XON);
145 isdn_tty_at_cout(rs, info);
146 }
147 break;
148 }
149}
150
151int
152isdn_tty_fax_command1(modem_info * info, isdn_ctrl * c)
153{
154 static char *msg[] =
155 {"OK", "CONNECT", "NO CARRIER", "ERROR", "FCERROR"};
156
157#ifdef ISDN_TTY_FAX_CMD_DEBUG
158 printk(KERN_DEBUG "isdn_tty: FCLASS1 cmd(%d)\n", c->parm.aux.cmd);
159#endif
160 if (c->parm.aux.cmd < ISDN_FAX_CLASS1_QUERY) {
161 if (info->online)
162 info->online = 1;
163 isdn_tty_at_cout("\r\n", info);
164 isdn_tty_at_cout(msg[c->parm.aux.cmd], info);
165 isdn_tty_at_cout("\r\n", info);
166 }
167 switch (c->parm.aux.cmd) {
168 case ISDN_FAX_CLASS1_CONNECT:
169 info->online = 2;
170 break;
171 case ISDN_FAX_CLASS1_OK:
172 case ISDN_FAX_CLASS1_FCERROR:
173 case ISDN_FAX_CLASS1_ERROR:
174 case ISDN_FAX_CLASS1_NOCARR:
175 break;
176 case ISDN_FAX_CLASS1_QUERY:
177 isdn_tty_at_cout("\r\n", info);
178 if (!c->parm.aux.para[0]) {
179 isdn_tty_at_cout(msg[ISDN_FAX_CLASS1_ERROR], info);
180 isdn_tty_at_cout("\r\n", info);
181 } else {
182 isdn_tty_at_cout(c->parm.aux.para, info);
183 isdn_tty_at_cout("\r\nOK\r\n", info);
184 }
185 break;
186 }
187 return (0);
188}
189
190int
191isdn_tty_fax_command(modem_info * info, isdn_ctrl * c)
192{
193 T30_s *f = info->fax;
194 char rs[10];
195
196 if (TTY_IS_FCLASS1(info))
197 return (isdn_tty_fax_command1(info, c));
198
199#ifdef ISDN_TTY_FAX_CMD_DEBUG
200 printk(KERN_DEBUG "isdn_tty: Fax cmd %d on ttyI%d\n",
201 f->r_code, info->line);
202#endif
203 switch (f->r_code) {
204 case ISDN_TTY_FAX_FCON:
205 info->faxonline = 1;
206 isdn_tty_fax_modem_result(2, info); /* +FCON */
207 return (0);
208 case ISDN_TTY_FAX_FCON_I:
209 info->faxonline = 16;
210 isdn_tty_fax_modem_result(2, info); /* +FCON */
211 return (0);
212 case ISDN_TTY_FAX_RID:
213 if (info->faxonline & 1)
214 isdn_tty_fax_modem_result(3, info); /* +FCSI */
215 if (info->faxonline & 16)
216 isdn_tty_fax_modem_result(8, info); /* +FTSI */
217 return (0);
218 case ISDN_TTY_FAX_DIS:
219 isdn_tty_fax_modem_result(4, info); /* +FDIS */
220 return (0);
221 case ISDN_TTY_FAX_HNG:
222 if (f->phase == ISDN_FAX_PHASE_C) {
223 if (f->direction == ISDN_TTY_FAX_CONN_IN) {
224 sprintf(rs, "%c%c", DLE, ETX);
225 isdn_tty_at_cout(rs, info);
226 } else {
227 sprintf(rs, "%c", 0x18);
228 isdn_tty_at_cout(rs, info);
229 }
230 info->faxonline &= ~2; /* leave data mode */
231 info->online = 1;
232 }
233 f->phase = ISDN_FAX_PHASE_E;
234 isdn_tty_fax_modem_result(5, info); /* +FHNG */
235 isdn_tty_fax_modem_result(0, info); /* OK */
236 return (0);
237 case ISDN_TTY_FAX_DCS:
238 isdn_tty_fax_modem_result(6, info); /* +FDCS */
239 isdn_tty_fax_modem_result(7, info); /* CONNECT */
240 f->phase = ISDN_FAX_PHASE_C;
241 return (0);
242 case ISDN_TTY_FAX_TRAIN_OK:
243 isdn_tty_fax_modem_result(6, info); /* +FDCS */
244 isdn_tty_fax_modem_result(0, info); /* OK */
245 return (0);
246 case ISDN_TTY_FAX_SENT:
247 isdn_tty_fax_modem_result(0, info); /* OK */
248 return (0);
249 case ISDN_TTY_FAX_CFR:
250 isdn_tty_fax_modem_result(9, info); /* +FCFR */
251 return (0);
252 case ISDN_TTY_FAX_ET:
253 sprintf(rs, "%c%c", DLE, ETX);
254 isdn_tty_at_cout(rs, info);
255 isdn_tty_fax_modem_result(10, info); /* +FPTS */
256 isdn_tty_fax_modem_result(11, info); /* +FET */
257 isdn_tty_fax_modem_result(0, info); /* OK */
258 info->faxonline &= ~2; /* leave data mode */
259 info->online = 1;
260 f->phase = ISDN_FAX_PHASE_D;
261 return (0);
262 case ISDN_TTY_FAX_PTS:
263 isdn_tty_fax_modem_result(10, info); /* +FPTS */
264 if (f->direction == ISDN_TTY_FAX_CONN_OUT) {
265 if (f->fet == 1)
266 f->phase = ISDN_FAX_PHASE_B;
267 if (f->fet == 0)
268 isdn_tty_fax_modem_result(0, info); /* OK */
269 }
270 return (0);
271 case ISDN_TTY_FAX_EOP:
272 info->faxonline &= ~2; /* leave data mode */
273 info->online = 1;
274 f->phase = ISDN_FAX_PHASE_D;
275 return (0);
276
277 }
278 return (-1);
279}
280
281
282void
283isdn_tty_fax_bitorder(modem_info * info, struct sk_buff *skb)
284{
285 __u8 LeftMask;
286 __u8 RightMask;
287 __u8 fBit;
288 __u8 Data;
289 int i;
290
291 if (!info->fax->bor) {
292 for (i = 0; i < skb->len; i++) {
293 Data = skb->data[i];
294 for (
295 LeftMask = 0x80, RightMask = 0x01;
296 LeftMask > RightMask;
297 LeftMask >>= 1, RightMask <<= 1
298 ) {
299 fBit = (Data & LeftMask);
300 if (Data & RightMask)
301 Data |= LeftMask;
302 else
303 Data &= ~LeftMask;
304 if (fBit)
305 Data |= RightMask;
306 else
307 Data &= ~RightMask;
308
309 }
310 skb->data[i] = Data;
311 }
312 }
313}
314
315/*
316 * Parse AT+F.. FAX class 1 commands
317 */
318
319int
320isdn_tty_cmd_FCLASS1(char **p, modem_info * info)
321{
322 static char *cmd[] =
323 {"AE", "TS", "RS", "TM", "RM", "TH", "RH"};
324 isdn_ctrl c;
325 int par, i;
326 u_long flags;
327
328 for (c.parm.aux.cmd = 0; c.parm.aux.cmd < 7; c.parm.aux.cmd++)
329 if (!strncmp(p[0], cmd[c.parm.aux.cmd], 2))
330 break;
331
332#ifdef ISDN_TTY_FAX_CMD_DEBUG
333 printk(KERN_DEBUG "isdn_tty_cmd_FCLASS1 (%s,%d)\n", p[0], c.parm.aux.cmd);
334#endif
335 if (c.parm.aux.cmd == 7)
336 PARSE_ERROR1;
337
338 p[0] += 2;
339 switch (*p[0]) {
340 case '?':
341 p[0]++;
342 c.parm.aux.subcmd = AT_QUERY;
343 break;
344 case '=':
345 p[0]++;
346 if (*p[0] == '?') {
347 p[0]++;
348 c.parm.aux.subcmd = AT_EQ_QUERY;
349 } else {
350 par = isdn_getnum(p);
351 if ((par < 0) || (par > 255))
352 PARSE_ERROR1;
353 c.parm.aux.subcmd = AT_EQ_VALUE;
354 c.parm.aux.para[0] = par;
355 }
356 break;
357 case 0:
358 c.parm.aux.subcmd = AT_COMMAND;
359 break;
360 default:
361 PARSE_ERROR1;
362 }
363 c.command = ISDN_CMD_FAXCMD;
364#ifdef ISDN_TTY_FAX_CMD_DEBUG
365 printk(KERN_DEBUG "isdn_tty_cmd_FCLASS1 %d/%d/%d)\n",
366 c.parm.aux.cmd, c.parm.aux.subcmd, c.parm.aux.para[0]);
367#endif
368 if (info->isdn_driver < 0) {
369 if ((c.parm.aux.subcmd == AT_EQ_VALUE) ||
370 (c.parm.aux.subcmd == AT_COMMAND)) {
371 PARSE_ERROR1;
372 }
373 spin_lock_irqsave(&dev->lock, flags);
374 /* get a temporary connection to the first free fax driver */
375 i = isdn_get_free_channel(ISDN_USAGE_FAX, ISDN_PROTO_L2_FAX,
376 ISDN_PROTO_L3_FCLASS1, -1, -1, "00");
377 if (i < 0) {
378 spin_unlock_irqrestore(&dev->lock, flags);
379 PARSE_ERROR1;
380 }
381 info->isdn_driver = dev->drvmap[i];
382 info->isdn_channel = dev->chanmap[i];
383 info->drv_index = i;
384 dev->m_idx[i] = info->line;
385 spin_unlock_irqrestore(&dev->lock, flags);
386 c.driver = info->isdn_driver;
387 c.arg = info->isdn_channel;
388 isdn_command(&c);
389 spin_lock_irqsave(&dev->lock, flags);
390 isdn_free_channel(info->isdn_driver, info->isdn_channel,
391 ISDN_USAGE_FAX);
392 info->isdn_driver = -1;
393 info->isdn_channel = -1;
394 if (info->drv_index >= 0) {
395 dev->m_idx[info->drv_index] = -1;
396 info->drv_index = -1;
397 }
398 spin_unlock_irqrestore(&dev->lock, flags);
399 } else {
400 c.driver = info->isdn_driver;
401 c.arg = info->isdn_channel;
402 isdn_command(&c);
403 }
404 return 1;
405}
406
407/*
408 * Parse AT+F.. FAX class 2 commands
409 */
410
411int
412isdn_tty_cmd_FCLASS2(char **p, modem_info * info)
413{
414 atemu *m = &info->emu;
415 T30_s *f = info->fax;
416 isdn_ctrl cmd;
417 int par;
418 char rs[50];
419 char rss[50];
420 int maxdccval[] =
421 {1, 5, 2, 2, 3, 2, 0, 7};
422
423 /* FAA still unchanged */
424 if (!strncmp(p[0], "AA", 2)) { /* TODO */
425 p[0] += 2;
426 switch (*p[0]) {
427 case '?':
428 p[0]++;
429 sprintf(rs, "\r\n%d", 0);
430 isdn_tty_at_cout(rs, info);
431 break;
432 case '=':
433 p[0]++;
434 par = isdn_getnum(p);
435 if ((par < 0) || (par > 255))
436 PARSE_ERROR1;
437 break;
438 default:
439 PARSE_ERROR1;
440 }
441 return 0;
442 }
443 /* BADLIN=value - dummy 0=disable errorchk disabled, 1-255 nr. of lines for making page bad */
444 if (!strncmp(p[0], "BADLIN", 6)) {
445 p[0] += 6;
446 switch (*p[0]) {
447 case '?':
448 p[0]++;
449 sprintf(rs, "\r\n%d", f->badlin);
450 isdn_tty_at_cout(rs, info);
451 break;
452 case '=':
453 p[0]++;
454 if (*p[0] == '?') {
455 p[0]++;
456 sprintf(rs, "\r\n0-255");
457 isdn_tty_at_cout(rs, info);
458 } else {
459 par = isdn_getnum(p);
460 if ((par < 0) || (par > 255))
461 PARSE_ERROR1;
462 f->badlin = par;
463#ifdef ISDN_TTY_FAX_STAT_DEBUG
464 printk(KERN_DEBUG "isdn_tty: Fax FBADLIN=%d\n", par);
465#endif
466 }
467 break;
468 default:
469 PARSE_ERROR1;
470 }
471 return 0;
472 }
473 /* BADMUL=value - dummy 0=disable errorchk disabled (treshold multiplier) */
474 if (!strncmp(p[0], "BADMUL", 6)) {
475 p[0] += 6;
476 switch (*p[0]) {
477 case '?':
478 p[0]++;
479 sprintf(rs, "\r\n%d", f->badmul);
480 isdn_tty_at_cout(rs, info);
481 break;
482 case '=':
483 p[0]++;
484 if (*p[0] == '?') {
485 p[0]++;
486 sprintf(rs, "\r\n0-255");
487 isdn_tty_at_cout(rs, info);
488 } else {
489 par = isdn_getnum(p);
490 if ((par < 0) || (par > 255))
491 PARSE_ERROR1;
492 f->badmul = par;
493#ifdef ISDN_TTY_FAX_STAT_DEBUG
494 printk(KERN_DEBUG "isdn_tty: Fax FBADMUL=%d\n", par);
495#endif
496 }
497 break;
498 default:
499 PARSE_ERROR1;
500 }
501 return 0;
502 }
503 /* BOR=n - Phase C bit order, 0=direct, 1=reverse */
504 if (!strncmp(p[0], "BOR", 3)) {
505 p[0] += 3;
506 switch (*p[0]) {
507 case '?':
508 p[0]++;
509 sprintf(rs, "\r\n%d", f->bor);
510 isdn_tty_at_cout(rs, info);
511 break;
512 case '=':
513 p[0]++;
514 if (*p[0] == '?') {
515 p[0]++;
516 sprintf(rs, "\r\n0,1");
517 isdn_tty_at_cout(rs, info);
518 } else {
519 par = isdn_getnum(p);
520 if ((par < 0) || (par > 1))
521 PARSE_ERROR1;
522 f->bor = par;
523#ifdef ISDN_TTY_FAX_STAT_DEBUG
524 printk(KERN_DEBUG "isdn_tty: Fax FBOR=%d\n", par);
525#endif
526 }
527 break;
528 default:
529 PARSE_ERROR1;
530 }
531 return 0;
532 }
533 /* NBC=n - No Best Capabilities */
534 if (!strncmp(p[0], "NBC", 3)) {
535 p[0] += 3;
536 switch (*p[0]) {
537 case '?':
538 p[0]++;
539 sprintf(rs, "\r\n%d", f->nbc);
540 isdn_tty_at_cout(rs, info);
541 break;
542 case '=':
543 p[0]++;
544 if (*p[0] == '?') {
545 p[0]++;
546 sprintf(rs, "\r\n0,1");
547 isdn_tty_at_cout(rs, info);
548 } else {
549 par = isdn_getnum(p);
550 if ((par < 0) || (par > 1))
551 PARSE_ERROR1;
552 f->nbc = par;
553#ifdef ISDN_TTY_FAX_STAT_DEBUG
554 printk(KERN_DEBUG "isdn_tty: Fax FNBC=%d\n", par);
555#endif
556 }
557 break;
558 default:
559 PARSE_ERROR1;
560 }
561 return 0;
562 }
563 /* BUF? - Readonly buffersize readout */
564 if (!strncmp(p[0], "BUF?", 4)) {
565 p[0] += 4;
566#ifdef ISDN_TTY_FAX_STAT_DEBUG
567 printk(KERN_DEBUG "isdn_tty: Fax FBUF? (%d) \n", (16 * m->mdmreg[REG_PSIZE]));
568#endif
569 p[0]++;
570 sprintf(rs, "\r\n %d ", (16 * m->mdmreg[REG_PSIZE]));
571 isdn_tty_at_cout(rs, info);
572 return 0;
573 }
574 /* CIG=string - local fax station id string for polling rx */
575 if (!strncmp(p[0], "CIG", 3)) {
576 int i, r;
577 p[0] += 3;
578 switch (*p[0]) {
579 case '?':
580 p[0]++;
581 sprintf(rs, "\r\n\"%s\"", f->pollid);
582 isdn_tty_at_cout(rs, info);
583 break;
584 case '=':
585 p[0]++;
586 if (*p[0] == '?') {
587 p[0]++;
588 sprintf(rs, "\r\n\"STRING\"");
589 isdn_tty_at_cout(rs, info);
590 } else {
591 if (*p[0] == '"')
592 p[0]++;
593 for (i = 0; (*p[0]) && i < (FAXIDLEN - 1) && (*p[0] != '"'); i++) {
594 f->pollid[i] = *p[0]++;
595 }
596 if (*p[0] == '"')
597 p[0]++;
598 for (r = i; r < FAXIDLEN; r++) {
599 f->pollid[r] = 32;
600 }
601 f->pollid[FAXIDLEN - 1] = 0;
602#ifdef ISDN_TTY_FAX_STAT_DEBUG
603 printk(KERN_DEBUG "isdn_tty: Fax local poll ID rx \"%s\"\n", f->pollid);
604#endif
605 }
606 break;
607 default:
608 PARSE_ERROR1;
609 }
610 return 0;
611 }
612 /* CQ=n - copy qlty chk, 0= no chk, 1=only 1D chk, 2=1D+2D chk */
613 if (!strncmp(p[0], "CQ", 2)) {
614 p[0] += 2;
615 switch (*p[0]) {
616 case '?':
617 p[0]++;
618 sprintf(rs, "\r\n%d", f->cq);
619 isdn_tty_at_cout(rs, info);
620 break;
621 case '=':
622 p[0]++;
623 if (*p[0] == '?') {
624 p[0]++;
625 sprintf(rs, "\r\n0,1,2");
626 isdn_tty_at_cout(rs, info);
627 } else {
628 par = isdn_getnum(p);
629 if ((par < 0) || (par > 2))
630 PARSE_ERROR1;
631 f->cq = par;
632#ifdef ISDN_TTY_FAX_STAT_DEBUG
633 printk(KERN_DEBUG "isdn_tty: Fax FCQ=%d\n", par);
634#endif
635 }
636 break;
637 default:
638 PARSE_ERROR1;
639 }
640 return 0;
641 }
642 /* CR=n - can receive? 0= no data rx or poll remote dev, 1=do receive data or poll remote dev */
643 if (!strncmp(p[0], "CR", 2)) {
644 p[0] += 2;
645 switch (*p[0]) {
646 case '?':
647 p[0]++;
648 sprintf(rs, "\r\n%d", f->cr); /* read actual value from struct and print */
649 isdn_tty_at_cout(rs, info);
650 break;
651 case '=':
652 p[0]++;
653 if (*p[0] == '?') {
654 p[0]++;
655 sprintf(rs, "\r\n0,1"); /* display online help */
656 isdn_tty_at_cout(rs, info);
657 } else {
658 par = isdn_getnum(p);
659 if ((par < 0) || (par > 1))
660 PARSE_ERROR1;
661 f->cr = par;
662#ifdef ISDN_TTY_FAX_STAT_DEBUG
663 printk(KERN_DEBUG "isdn_tty: Fax FCR=%d\n", par);
664#endif
665 }
666 break;
667 default:
668 PARSE_ERROR1;
669 }
670 return 0;
671 }
672 /* CTCRTY=value - ECM retry count */
673 if (!strncmp(p[0], "CTCRTY", 6)) {
674 p[0] += 6;
675 switch (*p[0]) {
676 case '?':
677 p[0]++;
678 sprintf(rs, "\r\n%d", f->ctcrty);
679 isdn_tty_at_cout(rs, info);
680 break;
681 case '=':
682 p[0]++;
683 if (*p[0] == '?') {
684 p[0]++;
685 sprintf(rs, "\r\n0-255");
686 isdn_tty_at_cout(rs, info);
687 } else {
688 par = isdn_getnum(p);
689 if ((par < 0) || (par > 255))
690 PARSE_ERROR1;
691 f->ctcrty = par;
692#ifdef ISDN_TTY_FAX_STAT_DEBUG
693 printk(KERN_DEBUG "isdn_tty: Fax FCTCRTY=%d\n", par);
694#endif
695 }
696 break;
697 default:
698 PARSE_ERROR1;
699 }
700 return 0;
701 }
702 /* DCC=vr,br,wd,ln,df,ec,bf,st - DCE capabilities parms */
703 if (!strncmp(p[0], "DCC", 3)) {
704 char *rp = &f->resolution;
705 int i;
706
707 p[0] += 3;
708 switch (*p[0]) {
709 case '?':
710 p[0]++;
711 strcpy(rs, "\r\n");
712 for (i = 0; i < 8; i++) {
713 sprintf(rss, "%c%s", rp[i] + 48,
714 (i < 7) ? "," : "");
715 strcat(rs, rss);
716 }
717 isdn_tty_at_cout(rs, info);
718 break;
719 case '=':
720 p[0]++;
721 if (*p[0] == '?') {
722 isdn_tty_at_cout("\r\n(0,1),(0-5),(0-2),(0-2),(0-3),(0-2),(0),(0-7)", info);
723 p[0]++;
724 } else {
725 for (i = 0; (((*p[0] >= '0') && (*p[0] <= '9')) || (*p[0] == ',')) && (i < 8); i++) {
726 if (*p[0] != ',') {
727 if ((*p[0] - 48) > maxdccval[i]) {
728 PARSE_ERROR1;
729 }
730 rp[i] = *p[0] - 48;
731 p[0]++;
732 if (*p[0] == ',')
733 p[0]++;
734 } else
735 p[0]++;
736 }
737#ifdef ISDN_TTY_FAX_STAT_DEBUG
738 printk(KERN_DEBUG "isdn_tty: Fax FDCC capabilities DCE=%d,%d,%d,%d,%d,%d,%d,%d\n",
739 rp[0], rp[1], rp[2], rp[3], rp[4], rp[5], rp[6], rp[7]);
740#endif
741 }
742 break;
743 default:
744 PARSE_ERROR1;
745 }
746 return 0;
747 }
748 /* DIS=vr,br,wd,ln,df,ec,bf,st - current session parms */
749 if (!strncmp(p[0], "DIS", 3)) {
750 char *rp = &f->resolution;
751 int i;
752
753 p[0] += 3;
754 switch (*p[0]) {
755 case '?':
756 p[0]++;
757 strcpy(rs, "\r\n");
758 for (i = 0; i < 8; i++) {
759 sprintf(rss, "%c%s", rp[i] + 48,
760 (i < 7) ? "," : "");
761 strcat(rs, rss);
762 }
763 isdn_tty_at_cout(rs, info);
764 break;
765 case '=':
766 p[0]++;
767 if (*p[0] == '?') {
768 isdn_tty_at_cout("\r\n(0,1),(0-5),(0-2),(0-2),(0-3),(0-2),(0),(0-7)", info);
769 p[0]++;
770 } else {
771 for (i = 0; (((*p[0] >= '0') && (*p[0] <= '9')) || (*p[0] == ',')) && (i < 8); i++) {
772 if (*p[0] != ',') {
773 if ((*p[0] - 48) > maxdccval[i]) {
774 PARSE_ERROR1;
775 }
776 rp[i] = *p[0] - 48;
777 p[0]++;
778 if (*p[0] == ',')
779 p[0]++;
780 } else
781 p[0]++;
782 }
783#ifdef ISDN_TTY_FAX_STAT_DEBUG
784 printk(KERN_DEBUG "isdn_tty: Fax FDIS session parms=%d,%d,%d,%d,%d,%d,%d,%d\n",
785 rp[0], rp[1], rp[2], rp[3], rp[4], rp[5], rp[6], rp[7]);
786#endif
787 }
788 break;
789 default:
790 PARSE_ERROR1;
791 }
792 return 0;
793 }
794 /* DR - Receive Phase C data command, initiates document reception */
795 if (!strncmp(p[0], "DR", 2)) {
796 p[0] += 2;
797 if ((info->faxonline & 16) && /* incoming connection */
798 ((f->phase == ISDN_FAX_PHASE_B) || (f->phase == ISDN_FAX_PHASE_D))) {
799#ifdef ISDN_TTY_FAX_STAT_DEBUG
800 printk(KERN_DEBUG "isdn_tty: Fax FDR\n");
801#endif
802 f->code = ISDN_TTY_FAX_DR;
803 cmd.driver = info->isdn_driver;
804 cmd.arg = info->isdn_channel;
805 cmd.command = ISDN_CMD_FAXCMD;
806 isdn_command(&cmd);
807 if (f->phase == ISDN_FAX_PHASE_B) {
808 f->phase = ISDN_FAX_PHASE_C;
809 } else if (f->phase == ISDN_FAX_PHASE_D) {
810 switch (f->fet) {
811 case 0: /* next page will be received */
812 f->phase = ISDN_FAX_PHASE_C;
813 isdn_tty_fax_modem_result(7, info); /* CONNECT */
814 break;
815 case 1: /* next doc will be received */
816 f->phase = ISDN_FAX_PHASE_B;
817 break;
818 case 2: /* fax session is terminating */
819 f->phase = ISDN_FAX_PHASE_E;
820 break;
821 default:
822 PARSE_ERROR1;
823 }
824 }
825 } else {
826 PARSE_ERROR1;
827 }
828 return 1;
829 }
830 /* DT=df,vr,wd,ln - TX phase C data command (release DCE to proceed with negotiation) */
831 if (!strncmp(p[0], "DT", 2)) {
832 int i, val[] =
833 {4, 0, 2, 3};
834 char *rp = &f->resolution;
835
836 p[0] += 2;
837 if (!info->faxonline & 1) /* not outgoing connection */
838 PARSE_ERROR1;
839
840 for (i = 0; (((*p[0] >= '0') && (*p[0] <= '9')) || (*p[0] == ',')) && (i < 4); i++) {
841 if (*p[0] != ',') {
842 if ((*p[0] - 48) > maxdccval[val[i]]) {
843 PARSE_ERROR1;
844 }
845 rp[val[i]] = *p[0] - 48;
846 p[0]++;
847 if (*p[0] == ',')
848 p[0]++;
849 } else
850 p[0]++;
851 }
852#ifdef ISDN_TTY_FAX_STAT_DEBUG
853 printk(KERN_DEBUG "isdn_tty: Fax FDT tx data command parms=%d,%d,%d,%d\n",
854 rp[4], rp[0], rp[2], rp[3]);
855#endif
856 if ((f->phase == ISDN_FAX_PHASE_B) || (f->phase == ISDN_FAX_PHASE_D)) {
857 f->code = ISDN_TTY_FAX_DT;
858 cmd.driver = info->isdn_driver;
859 cmd.arg = info->isdn_channel;
860 cmd.command = ISDN_CMD_FAXCMD;
861 isdn_command(&cmd);
862 if (f->phase == ISDN_FAX_PHASE_D) {
863 f->phase = ISDN_FAX_PHASE_C;
864 isdn_tty_fax_modem_result(7, info); /* CONNECT */
865 }
866 } else {
867 PARSE_ERROR1;
868 }
869 return 1;
870 }
871 /* ECM=n - Error mode control 0=disabled, 2=enabled, handled by DCE alone incl. buff of partial pages */
872 if (!strncmp(p[0], "ECM", 3)) {
873 p[0] += 3;
874 switch (*p[0]) {
875 case '?':
876 p[0]++;
877 sprintf(rs, "\r\n%d", f->ecm);
878 isdn_tty_at_cout(rs, info);
879 break;
880 case '=':
881 p[0]++;
882 if (*p[0] == '?') {
883 p[0]++;
884 sprintf(rs, "\r\n0,2");
885 isdn_tty_at_cout(rs, info);
886 } else {
887 par = isdn_getnum(p);
888 if ((par != 0) && (par != 2))
889 PARSE_ERROR1;
890 f->ecm = par;
891#ifdef ISDN_TTY_FAX_STAT_DEBUG
892 printk(KERN_DEBUG "isdn_tty: Fax FECM=%d\n", par);
893#endif
894 }
895 break;
896 default:
897 PARSE_ERROR1;
898 }
899 return 0;
900 }
901 /* ET=n - End of page or document */
902 if (!strncmp(p[0], "ET=", 3)) {
903 p[0] += 3;
904 if (*p[0] == '?') {
905 p[0]++;
906 sprintf(rs, "\r\n0-2");
907 isdn_tty_at_cout(rs, info);
908 } else {
909 if ((f->phase != ISDN_FAX_PHASE_D) || (!info->faxonline & 1))
910 PARSE_ERROR1;
911 par = isdn_getnum(p);
912 if ((par < 0) || (par > 2))
913 PARSE_ERROR1;
914 f->fet = par;
915 f->code = ISDN_TTY_FAX_ET;
916 cmd.driver = info->isdn_driver;
917 cmd.arg = info->isdn_channel;
918 cmd.command = ISDN_CMD_FAXCMD;
919 isdn_command(&cmd);
920#ifdef ISDN_TTY_FAX_STAT_DEBUG
921 printk(KERN_DEBUG "isdn_tty: Fax FET=%d\n", par);
922#endif
923 return 1;
924 }
925 return 0;
926 }
927 /* K - terminate */
928 if (!strncmp(p[0], "K", 1)) {
929 p[0] += 1;
930 if ((f->phase == ISDN_FAX_PHASE_IDLE) || (f->phase == ISDN_FAX_PHASE_E))
931 PARSE_ERROR1;
932 isdn_tty_modem_hup(info, 1);
933 return 1;
934 }
935 /* LID=string - local fax ID */
936 if (!strncmp(p[0], "LID", 3)) {
937 int i, r;
938 p[0] += 3;
939 switch (*p[0]) {
940 case '?':
941 p[0]++;
942 sprintf(rs, "\r\n\"%s\"", f->id);
943 isdn_tty_at_cout(rs, info);
944 break;
945 case '=':
946 p[0]++;
947 if (*p[0] == '?') {
948 p[0]++;
949 sprintf(rs, "\r\n\"STRING\"");
950 isdn_tty_at_cout(rs, info);
951 } else {
952 if (*p[0] == '"')
953 p[0]++;
954 for (i = 0; (*p[0]) && i < (FAXIDLEN - 1) && (*p[0] != '"'); i++) {
955 f->id[i] = *p[0]++;
956 }
957 if (*p[0] == '"')
958 p[0]++;
959 for (r = i; r < FAXIDLEN; r++) {
960 f->id[r] = 32;
961 }
962 f->id[FAXIDLEN - 1] = 0;
963#ifdef ISDN_TTY_FAX_STAT_DEBUG
964 printk(KERN_DEBUG "isdn_tty: Fax local ID \"%s\"\n", f->id);
965#endif
966 }
967 break;
968 default:
969 PARSE_ERROR1;
970 }
971 return 0;
972 }
973
974 /* MDL? - DCE Model */
975 if (!strncmp(p[0], "MDL?", 4)) {
976 p[0] += 4;
977#ifdef ISDN_TTY_FAX_STAT_DEBUG
978 printk(KERN_DEBUG "isdn_tty: FMDL?\n");
979#endif
980 isdn_tty_at_cout("\r\nisdn4linux", info);
981 return 0;
982 }
983 /* MFR? - DCE Manufacturer */
984 if (!strncmp(p[0], "MFR?", 4)) {
985 p[0] += 4;
986#ifdef ISDN_TTY_FAX_STAT_DEBUG
987 printk(KERN_DEBUG "isdn_tty: FMFR?\n");
988#endif
989 isdn_tty_at_cout("\r\nisdn4linux", info);
990 return 0;
991 }
992 /* MINSP=n - Minimum Speed for Phase C */
993 if (!strncmp(p[0], "MINSP", 5)) {
994 p[0] += 5;
995 switch (*p[0]) {
996 case '?':
997 p[0]++;
998 sprintf(rs, "\r\n%d", f->minsp);
999 isdn_tty_at_cout(rs, info);
1000 break;
1001 case '=':
1002 p[0]++;
1003 if (*p[0] == '?') {
1004 p[0]++;
1005 sprintf(rs, "\r\n0-5");
1006 isdn_tty_at_cout(rs, info);
1007 } else {
1008 par = isdn_getnum(p);
1009 if ((par < 0) || (par > 5))
1010 PARSE_ERROR1;
1011 f->minsp = par;
1012#ifdef ISDN_TTY_FAX_STAT_DEBUG
1013 printk(KERN_DEBUG "isdn_tty: Fax FMINSP=%d\n", par);
1014#endif
1015 }
1016 break;
1017 default:
1018 PARSE_ERROR1;
1019 }
1020 return 0;
1021 }
1022 /* PHCTO=value - DTE phase C timeout */
1023 if (!strncmp(p[0], "PHCTO", 5)) {
1024 p[0] += 5;
1025 switch (*p[0]) {
1026 case '?':
1027 p[0]++;
1028 sprintf(rs, "\r\n%d", f->phcto);
1029 isdn_tty_at_cout(rs, info);
1030 break;
1031 case '=':
1032 p[0]++;
1033 if (*p[0] == '?') {
1034 p[0]++;
1035 sprintf(rs, "\r\n0-255");
1036 isdn_tty_at_cout(rs, info);
1037 } else {
1038 par = isdn_getnum(p);
1039 if ((par < 0) || (par > 255))
1040 PARSE_ERROR1;
1041 f->phcto = par;
1042#ifdef ISDN_TTY_FAX_STAT_DEBUG
1043 printk(KERN_DEBUG "isdn_tty: Fax FPHCTO=%d\n", par);
1044#endif
1045 }
1046 break;
1047 default:
1048 PARSE_ERROR1;
1049 }
1050 return 0;
1051 }
1052
1053 /* REL=n - Phase C received EOL alignment */
1054 if (!strncmp(p[0], "REL", 3)) {
1055 p[0] += 3;
1056 switch (*p[0]) {
1057 case '?':
1058 p[0]++;
1059 sprintf(rs, "\r\n%d", f->rel);
1060 isdn_tty_at_cout(rs, info);
1061 break;
1062 case '=':
1063 p[0]++;
1064 if (*p[0] == '?') {
1065 p[0]++;
1066 sprintf(rs, "\r\n0,1");
1067 isdn_tty_at_cout(rs, info);
1068 } else {
1069 par = isdn_getnum(p);
1070 if ((par < 0) || (par > 1))
1071 PARSE_ERROR1;
1072 f->rel = par;
1073#ifdef ISDN_TTY_FAX_STAT_DEBUG
1074 printk(KERN_DEBUG "isdn_tty: Fax FREL=%d\n", par);
1075#endif
1076 }
1077 break;
1078 default:
1079 PARSE_ERROR1;
1080 }
1081 return 0;
1082 }
1083 /* REV? - DCE Revision */
1084 if (!strncmp(p[0], "REV?", 4)) {
1085 p[0] += 4;
1086#ifdef ISDN_TTY_FAX_STAT_DEBUG
1087 printk(KERN_DEBUG "isdn_tty: FREV?\n");
1088#endif
1089 strcpy(rss, isdn_tty_fax_revision);
1090 sprintf(rs, "\r\nRev: %s", isdn_getrev(rss));
1091 isdn_tty_at_cout(rs, info);
1092 return 0;
1093 }
1094
1095 /* Phase C Transmit Data Block Size */
1096 if (!strncmp(p[0], "TBC=", 4)) { /* dummy, not used */
1097 p[0] += 4;
1098#ifdef ISDN_TTY_FAX_STAT_DEBUG
1099 printk(KERN_DEBUG "isdn_tty: Fax FTBC=%c\n", *p[0]);
1100#endif
1101 switch (*p[0]) {
1102 case '0':
1103 p[0]++;
1104 break;
1105 default:
1106 PARSE_ERROR1;
1107 }
1108 return 0;
1109 }
1110 printk(KERN_DEBUG "isdn_tty: unknown token=>AT+F%s<\n", p[0]);
1111 PARSE_ERROR1;
1112}
1113
1114int
1115isdn_tty_cmd_PLUSF_FAX(char **p, modem_info * info)
1116{
1117 if (TTY_IS_FCLASS2(info))
1118 return (isdn_tty_cmd_FCLASS2(p, info));
1119 else if (TTY_IS_FCLASS1(info))
1120 return (isdn_tty_cmd_FCLASS1(p, info));
1121 PARSE_ERROR1;
1122}
diff --git a/drivers/isdn/i4l/isdn_ttyfax.h b/drivers/isdn/i4l/isdn_ttyfax.h
new file mode 100644
index 000000000000..757a89010020
--- /dev/null
+++ b/drivers/isdn/i4l/isdn_ttyfax.h
@@ -0,0 +1,18 @@
1/* $Id: isdn_ttyfax.h,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $
2 *
3 * header for Linux ISDN subsystem, tty_fax related functions (linklevel).
4 *
5 * Copyright 1999 by Armin Schindler (mac@melware.de)
6 * Copyright 1999 by Ralf Spachmann (mel@melware.de)
7 * Copyright 1999 by Cytronics & Melware
8 *
9 * This software may be used and distributed according to the terms
10 * of the GNU General Public License, incorporated herein by reference.
11 *
12 */
13
14
15#define XON 0x11
16#define XOFF 0x13
17#define DC2 0x12
18
diff --git a/drivers/isdn/i4l/isdn_v110.c b/drivers/isdn/i4l/isdn_v110.c
new file mode 100644
index 000000000000..f47f2b9846d8
--- /dev/null
+++ b/drivers/isdn/i4l/isdn_v110.c
@@ -0,0 +1,617 @@
1/* $Id: isdn_v110.c,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $
2 *
3 * Linux ISDN subsystem, V.110 related functions (linklevel).
4 *
5 * Copyright by Thomas Pfeiffer (pfeiffer@pds.de)
6 *
7 * This software may be used and distributed according to the terms
8 * of the GNU General Public License, incorporated herein by reference.
9 *
10 */
11
12#include <linux/string.h>
13#include <linux/kernel.h>
14#include <linux/slab.h>
15#include <linux/mm.h>
16#include <linux/delay.h>
17
18#include <linux/isdn.h>
19#include "isdn_v110.h"
20
21#undef ISDN_V110_DEBUG
22
23char *isdn_v110_revision = "$Revision: 1.1.2.2 $";
24
25#define V110_38400 255
26#define V110_19200 15
27#define V110_9600 3
28
29/*
30 * The following data are precoded matrices, online and offline matrix
31 * for 9600, 19200 und 38400, respectively
32 */
33static unsigned char V110_OnMatrix_9600[] =
34{0xfc, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff,
35 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfd,
36 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff,
37 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xfd};
38
39static unsigned char V110_OffMatrix_9600[] =
40{0xfc, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
41 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
42 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
43 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
44
45static unsigned char V110_OnMatrix_19200[] =
46{0xf0, 0xf0, 0xff, 0xf7, 0xff, 0xf7, 0xff, 0xf7, 0xff, 0xf7,
47 0xfd, 0xff, 0xff, 0xf7, 0xff, 0xf7, 0xff, 0xf7, 0xff, 0xf7};
48
49static unsigned char V110_OffMatrix_19200[] =
50{0xf0, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
51 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
52
53static unsigned char V110_OnMatrix_38400[] =
54{0x00, 0x7f, 0x7f, 0x7f, 0x7f, 0xfd, 0x7f, 0x7f, 0x7f, 0x7f};
55
56static unsigned char V110_OffMatrix_38400[] =
57{0x00, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff};
58
59/*
60 * FlipBits reorders sequences of keylen bits in one byte.
61 * E.g. source order 7654321 will be converted to 45670123 when keylen = 4,
62 * and to 67452301 when keylen = 2. This is necessary because ordering on
63 * the isdn line is the other way.
64 */
65static __inline unsigned char
66FlipBits(unsigned char c, int keylen)
67{
68 unsigned char b = c;
69 unsigned char bit = 128;
70 int i;
71 int j;
72 int hunks = (8 / keylen);
73
74 c = 0;
75 for (i = 0; i < hunks; i++) {
76 for (j = 0; j < keylen; j++) {
77 if (b & (bit >> j))
78 c |= bit >> (keylen - j - 1);
79 }
80 bit >>= keylen;
81 }
82 return c;
83}
84
85
86/* isdn_v110_open allocates and initializes private V.110 data
87 * structures and returns a pointer to these.
88 */
89static isdn_v110_stream *
90isdn_v110_open(unsigned char key, int hdrlen, int maxsize)
91{
92 int i;
93 isdn_v110_stream *v;
94
95 if ((v = kmalloc(sizeof(isdn_v110_stream), GFP_ATOMIC)) == NULL)
96 return NULL;
97 memset(v, 0, sizeof(isdn_v110_stream));
98 v->key = key;
99 v->nbits = 0;
100 for (i = 0; key & (1 << i); i++)
101 v->nbits++;
102
103 v->nbytes = 8 / v->nbits;
104 v->decodelen = 0;
105
106 switch (key) {
107 case V110_38400:
108 v->OnlineFrame = V110_OnMatrix_38400;
109 v->OfflineFrame = V110_OffMatrix_38400;
110 break;
111 case V110_19200:
112 v->OnlineFrame = V110_OnMatrix_19200;
113 v->OfflineFrame = V110_OffMatrix_19200;
114 break;
115 default:
116 v->OnlineFrame = V110_OnMatrix_9600;
117 v->OfflineFrame = V110_OffMatrix_9600;
118 break;
119 }
120 v->framelen = v->nbytes * 10;
121 v->SyncInit = 5;
122 v->introducer = 0;
123 v->dbit = 1;
124 v->b = 0;
125 v->skbres = hdrlen;
126 v->maxsize = maxsize - hdrlen;
127 if ((v->encodebuf = kmalloc(maxsize, GFP_ATOMIC)) == NULL) {
128 kfree(v);
129 return NULL;
130 }
131 return v;
132}
133
134/* isdn_v110_close frees private V.110 data structures */
135void
136isdn_v110_close(isdn_v110_stream * v)
137{
138 if (v == NULL)
139 return;
140#ifdef ISDN_V110_DEBUG
141 printk(KERN_DEBUG "v110 close\n");
142#endif
143 kfree(v->encodebuf);
144 kfree(v);
145}
146
147
148/*
149 * ValidHeaderBytes return the number of valid bytes in v->decodebuf
150 */
151static int
152ValidHeaderBytes(isdn_v110_stream * v)
153{
154 int i;
155 for (i = 0; (i < v->decodelen) && (i < v->nbytes); i++)
156 if ((v->decodebuf[i] & v->key) != 0)
157 break;
158 return i;
159}
160
161/*
162 * SyncHeader moves the decodebuf ptr to the next valid header
163 */
164static void
165SyncHeader(isdn_v110_stream * v)
166{
167 unsigned char *rbuf = v->decodebuf;
168 int len = v->decodelen;
169
170 if (len == 0)
171 return;
172 for (rbuf++, len--; len > 0; len--, rbuf++) /* such den SyncHeader in buf ! */
173 if ((*rbuf & v->key) == 0) /* erstes byte gefunden ? */
174 break; /* jupp! */
175 if (len)
176 memcpy(v->decodebuf, rbuf, len);
177
178 v->decodelen = len;
179#ifdef ISDN_V110_DEBUG
180 printk(KERN_DEBUG "isdn_v110: Header resync\n");
181#endif
182}
183
184/* DecodeMatrix takes n (n>=1) matrices (v110 frames, 10 bytes) where
185 len is the number of matrix-lines. len must be a multiple of 10, i.e.
186 only complete matices must be given.
187 From these, netto data is extracted and returned in buf. The return-value
188 is the bytecount of the decoded data.
189 */
190static int
191DecodeMatrix(isdn_v110_stream * v, unsigned char *m, int len, unsigned char *buf)
192{
193 int line = 0;
194 int buflen = 0;
195 int mbit = 64;
196 int introducer = v->introducer;
197 int dbit = v->dbit;
198 unsigned char b = v->b;
199
200 while (line < len) { /* Are we done with all lines of the matrix? */
201 if ((line % 10) == 0) { /* the 0. line of the matrix is always 0 ! */
202 if (m[line] != 0x00) { /* not 0 ? -> error! */
203#ifdef ISDN_V110_DEBUG
204 printk(KERN_DEBUG "isdn_v110: DecodeMatrix, V110 Bad Header\n");
205 /* returning now is not the right thing, though :-( */
206#endif
207 }
208 line++; /* next line of matrix */
209 continue;
210 } else if ((line % 10) == 5) { /* in line 5 there's only e-bits ! */
211 if ((m[line] & 0x70) != 0x30) { /* 011 has to be at the beginning! */
212#ifdef ISDN_V110_DEBUG
213 printk(KERN_DEBUG "isdn_v110: DecodeMatrix, V110 Bad 5th line\n");
214 /* returning now is not the right thing, though :-( */
215#endif
216 }
217 line++; /* next line */
218 continue;
219 } else if (!introducer) { /* every byte starts with 10 (stopbit, startbit) */
220 introducer = (m[line] & mbit) ? 0 : 1; /* current bit of the matrix */
221 next_byte:
222 if (mbit > 2) { /* was it the last bit in this line ? */
223 mbit >>= 1; /* no -> take next */
224 continue;
225 } /* otherwise start with leftmost bit in the next line */
226 mbit = 64;
227 line++;
228 continue;
229 } else { /* otherwise we need to set a data bit */
230 if (m[line] & mbit) /* was that bit set in the matrix ? */
231 b |= dbit; /* yes -> set it in the data byte */
232 else
233 b &= dbit - 1; /* no -> clear it in the data byte */
234 if (dbit < 128) /* is that data byte done ? */
235 dbit <<= 1; /* no, got the next bit */
236 else { /* data byte is done */
237 buf[buflen++] = b; /* copy byte into the output buffer */
238 introducer = b = 0; /* init of the intro sequence and of the data byte */
239 dbit = 1; /* next we look for the 0th bit */
240 }
241 goto next_byte; /* look for next bit in the matrix */
242 }
243 }
244 v->introducer = introducer;
245 v->dbit = dbit;
246 v->b = b;
247 return buflen; /* return number of bytes in the output buffer */
248}
249
250/*
251 * DecodeStream receives V.110 coded data from the input stream. It recovers the
252 * original frames.
253 * The input stream doesn't need to be framed
254 */
255struct sk_buff *
256isdn_v110_decode(isdn_v110_stream * v, struct sk_buff *skb)
257{
258 int i;
259 int j;
260 int len;
261 unsigned char *v110_buf;
262 unsigned char *rbuf;
263
264 if (!skb) {
265 printk(KERN_WARNING "isdn_v110_decode called with NULL skb!\n");
266 return NULL;
267 }
268 rbuf = skb->data;
269 len = skb->len;
270 if (v == NULL) {
271 /* invalid handle, no chance to proceed */
272 printk(KERN_WARNING "isdn_v110_decode called with NULL stream!\n");
273 dev_kfree_skb(skb);
274 return NULL;
275 }
276 if (v->decodelen == 0) /* cache empty? */
277 for (; len > 0; len--, rbuf++) /* scan for SyncHeader in buf */
278 if ((*rbuf & v->key) == 0)
279 break; /* found first byte */
280 if (len == 0) {
281 dev_kfree_skb(skb);
282 return NULL;
283 }
284 /* copy new data to decode-buffer */
285 memcpy(&(v->decodebuf[v->decodelen]), rbuf, len);
286 v->decodelen += len;
287 ReSync:
288 if (v->decodelen < v->nbytes) { /* got a new header ? */
289 dev_kfree_skb(skb);
290 return NULL; /* no, try later */
291 }
292 if (ValidHeaderBytes(v) != v->nbytes) { /* is that a valid header? */
293 SyncHeader(v); /* no -> look for header */
294 goto ReSync;
295 }
296 len = (v->decodelen - (v->decodelen % (10 * v->nbytes))) / v->nbytes;
297 if ((v110_buf = kmalloc(len, GFP_ATOMIC)) == NULL) {
298 printk(KERN_WARNING "isdn_v110_decode: Couldn't allocate v110_buf\n");
299 dev_kfree_skb(skb);
300 return NULL;
301 }
302 for (i = 0; i < len; i++) {
303 v110_buf[i] = 0;
304 for (j = 0; j < v->nbytes; j++)
305 v110_buf[i] |= (v->decodebuf[(i * v->nbytes) + j] & v->key) << (8 - ((j + 1) * v->nbits));
306 v110_buf[i] = FlipBits(v110_buf[i], v->nbits);
307 }
308 v->decodelen = (v->decodelen % (10 * v->nbytes));
309 memcpy(v->decodebuf, &(v->decodebuf[len * v->nbytes]), v->decodelen);
310
311 skb_trim(skb, DecodeMatrix(v, v110_buf, len, skb->data));
312 kfree(v110_buf);
313 if (skb->len)
314 return skb;
315 else {
316 kfree_skb(skb);
317 return NULL;
318 }
319}
320
321/* EncodeMatrix takes input data in buf, len is the bytecount.
322 Data is encoded into v110 frames in m. Return value is the number of
323 matrix-lines generated.
324 */
325static int
326EncodeMatrix(unsigned char *buf, int len, unsigned char *m, int mlen)
327{
328 int line = 0;
329 int i = 0;
330 int mbit = 128;
331 int dbit = 1;
332 int introducer = 3;
333 int ibit[] = {0, 1, 1};
334
335 while ((i < len) && (line < mlen)) { /* while we still have input data */
336 switch (line % 10) { /* in which line of the matrix are we? */
337 case 0:
338 m[line++] = 0x00; /* line 0 is always 0 */
339 mbit = 128; /* go on with the 7th bit */
340 break;
341 case 5:
342 m[line++] = 0xbf; /* line 5 is always 10111111 */
343 mbit = 128; /* go on with the 7th bit */
344 break;
345 }
346 if (line >= mlen) {
347 printk(KERN_WARNING "isdn_v110 (EncodeMatrix): buffer full!\n");
348 return line;
349 }
350 next_bit:
351 switch (mbit) { /* leftmost or rightmost bit ? */
352 case 1:
353 line++; /* rightmost -> go to next line */
354 if (line >= mlen) {
355 printk(KERN_WARNING "isdn_v110 (EncodeMatrix): buffer full!\n");
356 return line;
357 }
358 case 128:
359 m[line] = 128; /* leftmost -> set byte to 1000000 */
360 mbit = 64; /* current bit in the matrix line */
361 continue;
362 }
363 if (introducer) { /* set 110 sequence ? */
364 introducer--; /* set on digit less */
365 m[line] |= ibit[introducer] ? mbit : 0; /* set corresponding bit */
366 mbit >>= 1; /* bit of matrix line >> 1 */
367 goto next_bit; /* and go on there */
368 } /* else push data bits into the matrix! */
369 m[line] |= (buf[i] & dbit) ? mbit : 0; /* set data bit in matrix */
370 if (dbit == 128) { /* was it the last one? */
371 dbit = 1; /* then go on with first bit of */
372 i++; /* next byte in input buffer */
373 if (i < len) /* input buffer done ? */
374 introducer = 3; /* no, write introducer 110 */
375 else { /* input buffer done ! */
376 m[line] |= (mbit - 1) & 0xfe; /* set remaining bits in line to 1 */
377 break;
378 }
379 } else /* not the last data bit */
380 dbit <<= 1; /* then go to next data bit */
381 mbit >>= 1; /* go to next bit of matrix */
382 goto next_bit;
383
384 }
385 /* if necessary, generate remaining lines of the matrix... */
386 if ((line) && ((line + 10) < mlen))
387 switch (++line % 10) {
388 case 1:
389 m[line++] = 0xfe;
390 case 2:
391 m[line++] = 0xfe;
392 case 3:
393 m[line++] = 0xfe;
394 case 4:
395 m[line++] = 0xfe;
396 case 5:
397 m[line++] = 0xbf;
398 case 6:
399 m[line++] = 0xfe;
400 case 7:
401 m[line++] = 0xfe;
402 case 8:
403 m[line++] = 0xfe;
404 case 9:
405 m[line++] = 0xfe;
406 }
407 return line; /* that's how many lines we have */
408}
409
410/*
411 * Build a sync frame.
412 */
413static struct sk_buff *
414isdn_v110_sync(isdn_v110_stream *v)
415{
416 struct sk_buff *skb;
417
418 if (v == NULL) {
419 /* invalid handle, no chance to proceed */
420 printk(KERN_WARNING "isdn_v110_sync called with NULL stream!\n");
421 return NULL;
422 }
423 if ((skb = dev_alloc_skb(v->framelen + v->skbres))) {
424 skb_reserve(skb, v->skbres);
425 memcpy(skb_put(skb, v->framelen), v->OfflineFrame, v->framelen);
426 }
427 return skb;
428}
429
430/*
431 * Build an idle frame.
432 */
433static struct sk_buff *
434isdn_v110_idle(isdn_v110_stream *v)
435{
436 struct sk_buff *skb;
437
438 if (v == NULL) {
439 /* invalid handle, no chance to proceed */
440 printk(KERN_WARNING "isdn_v110_sync called with NULL stream!\n");
441 return NULL;
442 }
443 if ((skb = dev_alloc_skb(v->framelen + v->skbres))) {
444 skb_reserve(skb, v->skbres);
445 memcpy(skb_put(skb, v->framelen), v->OnlineFrame, v->framelen);
446 }
447 return skb;
448}
449
450struct sk_buff *
451isdn_v110_encode(isdn_v110_stream * v, struct sk_buff *skb)
452{
453 int i;
454 int j;
455 int rlen;
456 int mlen;
457 int olen;
458 int size;
459 int sval1;
460 int sval2;
461 int nframes;
462 unsigned char *v110buf;
463 unsigned char *rbuf;
464 struct sk_buff *nskb;
465
466 if (v == NULL) {
467 /* invalid handle, no chance to proceed */
468 printk(KERN_WARNING "isdn_v110_encode called with NULL stream!\n");
469 return NULL;
470 }
471 if (!skb) {
472 /* invalid skb, no chance to proceed */
473 printk(KERN_WARNING "isdn_v110_encode called with NULL skb!\n");
474 return NULL;
475 }
476 rlen = skb->len;
477 nframes = (rlen + 3) / 4;
478 v110buf = v->encodebuf;
479 if ((nframes * 40) > v->maxsize) {
480 size = v->maxsize;
481 rlen = v->maxsize / 40;
482 } else
483 size = nframes * 40;
484 if (!(nskb = dev_alloc_skb(size + v->skbres + sizeof(int)))) {
485 printk(KERN_WARNING "isdn_v110_encode: Couldn't alloc skb\n");
486 return NULL;
487 }
488 skb_reserve(nskb, v->skbres + sizeof(int));
489 if (skb->len == 0) {
490 memcpy(skb_put(nskb, v->framelen), v->OnlineFrame, v->framelen);
491 *((int *)skb_push(nskb, sizeof(int))) = 0;
492 return nskb;
493 }
494 mlen = EncodeMatrix(skb->data, rlen, v110buf, size);
495 /* now distribute 2 or 4 bits each to the output stream! */
496 rbuf = skb_put(nskb, size);
497 olen = 0;
498 sval1 = 8 - v->nbits;
499 sval2 = v->key << sval1;
500 for (i = 0; i < mlen; i++) {
501 v110buf[i] = FlipBits(v110buf[i], v->nbits);
502 for (j = 0; j < v->nbytes; j++) {
503 if (size--)
504 *rbuf++ = ~v->key | (((v110buf[i] << (j * v->nbits)) & sval2) >> sval1);
505 else {
506 printk(KERN_WARNING "isdn_v110_encode: buffers full!\n");
507 goto buffer_full;
508 }
509 olen++;
510 }
511 }
512buffer_full:
513 skb_trim(nskb, olen);
514 *((int *)skb_push(nskb, sizeof(int))) = rlen;
515 return nskb;
516}
517
518int
519isdn_v110_stat_callback(int idx, isdn_ctrl * c)
520{
521 isdn_v110_stream *v = NULL;
522 int i;
523 int ret;
524
525 if (idx < 0)
526 return 0;
527 switch (c->command) {
528 case ISDN_STAT_BSENT:
529 /* Keep the send-queue of the driver filled
530 * with frames:
531 * If number of outstanding frames < 3,
532 * send down an Idle-Frame (or an Sync-Frame, if
533 * v->SyncInit != 0).
534 */
535 if (!(v = dev->v110[idx]))
536 return 0;
537 atomic_inc(&dev->v110use[idx]);
538 for (i=0; i * v->framelen < c->parm.length; i++) {
539 if (v->skbidle > 0) {
540 v->skbidle--;
541 ret = 1;
542 } else {
543 if (v->skbuser > 0)
544 v->skbuser--;
545 ret = 0;
546 }
547 }
548 for (i = v->skbuser + v->skbidle; i < 2; i++) {
549 struct sk_buff *skb;
550 if (v->SyncInit > 0)
551 skb = isdn_v110_sync(v);
552 else
553 skb = isdn_v110_idle(v);
554 if (skb) {
555 if (dev->drv[c->driver]->interface->writebuf_skb(c->driver, c->arg, 1, skb) <= 0) {
556 dev_kfree_skb(skb);
557 break;
558 } else {
559 if (v->SyncInit)
560 v->SyncInit--;
561 v->skbidle++;
562 }
563 } else
564 break;
565 }
566 atomic_dec(&dev->v110use[idx]);
567 return ret;
568 case ISDN_STAT_DHUP:
569 case ISDN_STAT_BHUP:
570 while (1) {
571 atomic_inc(&dev->v110use[idx]);
572 if (atomic_dec_and_test(&dev->v110use[idx])) {
573 isdn_v110_close(dev->v110[idx]);
574 dev->v110[idx] = NULL;
575 break;
576 }
577 mdelay(1);
578 }
579 break;
580 case ISDN_STAT_BCONN:
581 if (dev->v110emu[idx] && (dev->v110[idx] == NULL)) {
582 int hdrlen = dev->drv[c->driver]->interface->hl_hdrlen;
583 int maxsize = dev->drv[c->driver]->interface->maxbufsize;
584 atomic_inc(&dev->v110use[idx]);
585 switch (dev->v110emu[idx]) {
586 case ISDN_PROTO_L2_V11096:
587 dev->v110[idx] = isdn_v110_open(V110_9600, hdrlen, maxsize);
588 break;
589 case ISDN_PROTO_L2_V11019:
590 dev->v110[idx] = isdn_v110_open(V110_19200, hdrlen, maxsize);
591 break;
592 case ISDN_PROTO_L2_V11038:
593 dev->v110[idx] = isdn_v110_open(V110_38400, hdrlen, maxsize);
594 break;
595 default:;
596 }
597 if ((v = dev->v110[idx])) {
598 while (v->SyncInit) {
599 struct sk_buff *skb = isdn_v110_sync(v);
600 if (dev->drv[c->driver]->interface->writebuf_skb(c->driver, c->arg, 1, skb) <= 0) {
601 dev_kfree_skb(skb);
602 /* Unable to send, try later */
603 break;
604 }
605 v->SyncInit--;
606 v->skbidle++;
607 }
608 } else
609 printk(KERN_WARNING "isdn_v110: Couldn't open stream for chan %d\n", idx);
610 atomic_dec(&dev->v110use[idx]);
611 }
612 break;
613 default:
614 return 0;
615 }
616 return 0;
617}
diff --git a/drivers/isdn/i4l/isdn_v110.h b/drivers/isdn/i4l/isdn_v110.h
new file mode 100644
index 000000000000..08f274bbc438
--- /dev/null
+++ b/drivers/isdn/i4l/isdn_v110.h
@@ -0,0 +1,29 @@
1/* $Id: isdn_v110.h,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $
2 *
3 * Linux ISDN subsystem, V.110 related functions (linklevel).
4 *
5 * Copyright by Thomas Pfeiffer (pfeiffer@pds.de)
6 *
7 * This software may be used and distributed according to the terms
8 * of the GNU General Public License, incorporated herein by reference.
9 *
10 */
11
12#ifndef _isdn_v110_h_
13#define _isdn_v110_h_
14
15/*
16 * isdn_v110_encode will take raw data and encode it using V.110
17 */
18extern struct sk_buff *isdn_v110_encode(isdn_v110_stream *, struct sk_buff *);
19
20/*
21 * isdn_v110_decode receives V.110 coded data from the stream and rebuilds
22 * frames from them. The source stream doesn't need to be framed.
23 */
24extern struct sk_buff *isdn_v110_decode(isdn_v110_stream *, struct sk_buff *);
25
26extern int isdn_v110_stat_callback(int, isdn_ctrl *);
27extern void isdn_v110_close(isdn_v110_stream * v);
28
29#endif
diff --git a/drivers/isdn/i4l/isdn_x25iface.c b/drivers/isdn/i4l/isdn_x25iface.c
new file mode 100644
index 000000000000..4ab7600cf9c1
--- /dev/null
+++ b/drivers/isdn/i4l/isdn_x25iface.c
@@ -0,0 +1,328 @@
1/* $Id: isdn_x25iface.c,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $
2 *
3 * Linux ISDN subsystem, X.25 related functions
4 *
5 * This software may be used and distributed according to the terms
6 * of the GNU General Public License, incorporated herein by reference.
7 *
8 * stuff needed to support the Linux X.25 PLP code on top of devices that
9 * can provide a lab_b service using the concap_proto mechanism.
10 * This module supports a network interface wich provides lapb_sematics
11 * -- as defined in Documentation/networking/x25-iface.txt -- to
12 * the upper layer and assumes that the lower layer provides a reliable
13 * data link service by means of the concap_device_ops callbacks.
14 *
15 * Only protocol specific stuff goes here. Device specific stuff
16 * goes to another -- device related -- concap_proto support source file.
17 *
18 */
19
20/* #include <linux/isdn.h> */
21#include <linux/netdevice.h>
22#include <linux/concap.h>
23#include <linux/wanrouter.h>
24#include <net/x25device.h>
25#include "isdn_x25iface.h"
26
27/* for debugging messages not to cause an oops when device pointer is NULL*/
28#define MY_DEVNAME(dev) ( (dev) ? (dev)->name : "DEVICE UNSPECIFIED" )
29
30
31typedef struct isdn_x25iface_proto_data {
32 int magic;
33 enum wan_states state;
34 /* Private stuff, not to be accessed via proto_data. We provide the
35 other storage for the concap_proto instance here as well,
36 enabling us to allocate both with just one kmalloc(): */
37 struct concap_proto priv;
38} ix25_pdata_t;
39
40
41
42/* is now in header file (extern): struct concap_proto * isdn_x25iface_proto_new(void); */
43void isdn_x25iface_proto_del( struct concap_proto * );
44int isdn_x25iface_proto_close( struct concap_proto * );
45int isdn_x25iface_proto_restart( struct concap_proto *,
46 struct net_device *,
47 struct concap_device_ops *);
48int isdn_x25iface_xmit( struct concap_proto *, struct sk_buff * );
49int isdn_x25iface_receive( struct concap_proto *, struct sk_buff * );
50int isdn_x25iface_connect_ind( struct concap_proto * );
51int isdn_x25iface_disconn_ind( struct concap_proto * );
52
53
54static struct concap_proto_ops ix25_pops = {
55 &isdn_x25iface_proto_new,
56 &isdn_x25iface_proto_del,
57 &isdn_x25iface_proto_restart,
58 &isdn_x25iface_proto_close,
59 &isdn_x25iface_xmit,
60 &isdn_x25iface_receive,
61 &isdn_x25iface_connect_ind,
62 &isdn_x25iface_disconn_ind
63};
64
65/* error message helper function */
66static void illegal_state_warn( unsigned state, unsigned char firstbyte)
67{
68 printk( KERN_WARNING "isdn_x25iface: firstbyte %x illegal in"
69 "current state %d\n",firstbyte, state );
70}
71
72/* check protocol data field for consistency */
73static int pdata_is_bad( ix25_pdata_t * pda ){
74
75 if( pda && pda -> magic == ISDN_X25IFACE_MAGIC ) return 0;
76 printk( KERN_WARNING
77 "isdn_x25iface_xxx: illegal pointer to proto data\n" );
78 return 1;
79}
80
81/* create a new x25 interface protocol instance
82 */
83struct concap_proto * isdn_x25iface_proto_new(void)
84{
85 ix25_pdata_t * tmp = kmalloc(sizeof(ix25_pdata_t),GFP_KERNEL);
86 IX25DEBUG("isdn_x25iface_proto_new\n");
87 if( tmp ){
88 tmp -> magic = ISDN_X25IFACE_MAGIC;
89 tmp -> state = WAN_UNCONFIGURED;
90 /* private data space used to hold the concap_proto data.
91 Only to be accessed via the returned pointer */
92 spin_lock_init(&tmp->priv.lock);
93 tmp -> priv.dops = NULL;
94 tmp -> priv.net_dev = NULL;
95 tmp -> priv.pops = &ix25_pops;
96 tmp -> priv.flags = 0;
97 tmp -> priv.proto_data = tmp;
98 return( &(tmp -> priv) );
99 }
100 return NULL;
101};
102
103/* close the x25iface encapsulation protocol
104 */
105int isdn_x25iface_proto_close(struct concap_proto *cprot){
106
107 ix25_pdata_t *tmp;
108 int ret = 0;
109 ulong flags;
110
111 if( ! cprot ){
112 printk( KERN_ERR "isdn_x25iface_proto_close: "
113 "invalid concap_proto pointer\n" );
114 return -1;
115 }
116 IX25DEBUG( "isdn_x25iface_proto_close %s \n", MY_DEVNAME(cprot -> net_dev) );
117 spin_lock_irqsave(&cprot->lock, flags);
118 cprot -> dops = NULL;
119 cprot -> net_dev = NULL;
120 tmp = cprot -> proto_data;
121 if( pdata_is_bad( tmp ) ){
122 ret = -1;
123 } else {
124 tmp -> state = WAN_UNCONFIGURED;
125 }
126 spin_unlock_irqrestore(&cprot->lock, flags);
127 return ret;
128}
129
130/* Delete the x25iface encapsulation protocol instance
131 */
132void isdn_x25iface_proto_del(struct concap_proto *cprot){
133
134 ix25_pdata_t * tmp;
135
136 IX25DEBUG( "isdn_x25iface_proto_del \n" );
137 if( ! cprot ){
138 printk( KERN_ERR "isdn_x25iface_proto_del: "
139 "concap_proto pointer is NULL\n" );
140 return;
141 }
142 tmp = cprot -> proto_data;
143 if( tmp == NULL ){
144 printk( KERN_ERR "isdn_x25iface_proto_del: inconsistent "
145 "proto_data pointer (maybe already deleted?)\n");
146 return;
147 }
148 /* close if the protocol is still open */
149 if( cprot -> dops ) isdn_x25iface_proto_close(cprot);
150 /* freeing the storage should be sufficient now. But some additional
151 settings might help to catch wild pointer bugs */
152 tmp -> magic = 0;
153 cprot -> proto_data = NULL;
154
155 kfree( tmp );
156 return;
157}
158
159/* (re-)initialize the data structures for x25iface encapsulation
160 */
161int isdn_x25iface_proto_restart(struct concap_proto *cprot,
162 struct net_device *ndev,
163 struct concap_device_ops *dops)
164{
165 ix25_pdata_t * pda = cprot -> proto_data ;
166 ulong flags;
167
168 IX25DEBUG( "isdn_x25iface_proto_restart %s \n", MY_DEVNAME(ndev) );
169
170 if ( pdata_is_bad( pda ) ) return -1;
171
172 if( !( dops && dops -> data_req && dops -> connect_req
173 && dops -> disconn_req ) ){
174 printk( KERN_WARNING "isdn_x25iface_restart: required dops"
175 " missing\n" );
176 isdn_x25iface_proto_close(cprot);
177 return -1;
178 }
179 spin_lock_irqsave(&cprot->lock, flags);
180 cprot -> net_dev = ndev;
181 cprot -> pops = &ix25_pops;
182 cprot -> dops = dops;
183 pda -> state = WAN_DISCONNECTED;
184 spin_unlock_irqrestore(&cprot->lock, flags);
185 return 0;
186}
187
188/* deliver a dl_data frame received from i4l HL driver to the network layer
189 */
190int isdn_x25iface_receive(struct concap_proto *cprot, struct sk_buff *skb)
191{
192 IX25DEBUG( "isdn_x25iface_receive %s \n", MY_DEVNAME(cprot->net_dev) );
193 if ( ( (ix25_pdata_t*) (cprot->proto_data) )
194 -> state == WAN_CONNECTED ){
195 if( skb_push(skb, 1)){
196 skb -> data[0]=0x00;
197 skb->protocol = x25_type_trans(skb, cprot->net_dev);
198 netif_rx(skb);
199 return 0;
200 }
201 }
202 printk(KERN_WARNING "isdn_x25iface_receive %s: not connected, skb dropped\n", MY_DEVNAME(cprot->net_dev) );
203 dev_kfree_skb(skb);
204 return -1;
205}
206
207/* a connection set up is indicated by lower layer
208 */
209int isdn_x25iface_connect_ind(struct concap_proto *cprot)
210{
211 struct sk_buff * skb = dev_alloc_skb(1);
212 enum wan_states *state_p
213 = &( ( (ix25_pdata_t*) (cprot->proto_data) ) -> state);
214 IX25DEBUG( "isdn_x25iface_connect_ind %s \n"
215 , MY_DEVNAME(cprot->net_dev) );
216 if( *state_p == WAN_UNCONFIGURED ){
217 printk(KERN_WARNING
218 "isdn_x25iface_connect_ind while unconfigured %s\n"
219 , MY_DEVNAME(cprot->net_dev) );
220 return -1;
221 }
222 *state_p = WAN_CONNECTED;
223 if( skb ){
224 *( skb_put(skb, 1) ) = 0x01;
225 skb->protocol = x25_type_trans(skb, cprot->net_dev);
226 netif_rx(skb);
227 return 0;
228 } else {
229 printk(KERN_WARNING "isdn_x25iface_connect_ind: "
230 " out of memory -- disconnecting\n");
231 cprot -> dops -> disconn_req(cprot);
232 return -1;
233 }
234}
235
236/* a disconnect is indicated by lower layer
237 */
238int isdn_x25iface_disconn_ind(struct concap_proto *cprot)
239{
240 struct sk_buff *skb;
241 enum wan_states *state_p
242 = &( ( (ix25_pdata_t*) (cprot->proto_data) ) -> state);
243 IX25DEBUG( "isdn_x25iface_disconn_ind %s \n", MY_DEVNAME(cprot -> net_dev) );
244 if( *state_p == WAN_UNCONFIGURED ){
245 printk(KERN_WARNING
246 "isdn_x25iface_disconn_ind while unconfigured\n");
247 return -1;
248 }
249 if(! cprot -> net_dev) return -1;
250 *state_p = WAN_DISCONNECTED;
251 skb = dev_alloc_skb(1);
252 if( skb ){
253 *( skb_put(skb, 1) ) = 0x02;
254 skb->protocol = x25_type_trans(skb, cprot->net_dev);
255 netif_rx(skb);
256 return 0;
257 } else {
258 printk(KERN_WARNING "isdn_x25iface_disconn_ind:"
259 " out of memory\n");
260 return -1;
261 }
262}
263
264/* process a frame handed over to us from linux network layer. First byte
265 semantics as defined in Documentation/networking/x25-iface.txt
266 */
267int isdn_x25iface_xmit(struct concap_proto *cprot, struct sk_buff *skb)
268{
269 unsigned char firstbyte = skb->data[0];
270 enum wan_states *state = &((ix25_pdata_t*)cprot->proto_data)->state;
271 int ret = 0;
272 IX25DEBUG( "isdn_x25iface_xmit: %s first=%x state=%d \n", MY_DEVNAME(cprot -> net_dev), firstbyte, *state );
273 switch ( firstbyte ){
274 case 0x00: /* dl_data request */
275 if( *state == WAN_CONNECTED ){
276 skb_pull(skb, 1);
277 cprot -> net_dev -> trans_start = jiffies;
278 ret = ( cprot -> dops -> data_req(cprot, skb) );
279 /* prepare for future retransmissions */
280 if( ret ) skb_push(skb,1);
281 return ret;
282 }
283 illegal_state_warn( *state, firstbyte );
284 break;
285 case 0x01: /* dl_connect request */
286 if( *state == WAN_DISCONNECTED ){
287 *state = WAN_CONNECTING;
288 ret = cprot -> dops -> connect_req(cprot);
289 if(ret){
290 /* reset state and notify upper layer about
291 * immidiatly failed attempts */
292 isdn_x25iface_disconn_ind(cprot);
293 }
294 } else {
295 illegal_state_warn( *state, firstbyte );
296 }
297 break;
298 case 0x02: /* dl_disconnect request */
299 switch ( *state ){
300 case WAN_DISCONNECTED:
301 /* Should not happen. However, give upper layer a
302 chance to recover from inconstistency but don't
303 trust the lower layer sending the disconn_confirm
304 when already disconnected */
305 printk(KERN_WARNING "isdn_x25iface_xmit: disconnect "
306 " requested while disconnected\n" );
307 isdn_x25iface_disconn_ind(cprot);
308 break; /* prevent infinite loops */
309 case WAN_CONNECTING:
310 case WAN_CONNECTED:
311 *state = WAN_DISCONNECTED;
312 cprot -> dops -> disconn_req(cprot);
313 break;
314 default:
315 illegal_state_warn( *state, firstbyte );
316 }
317 break;
318 case 0x03: /* changing lapb parameters requested */
319 printk(KERN_WARNING "isdn_x25iface_xmit: setting of lapb"
320 " options not yet supported\n");
321 break;
322 default:
323 printk(KERN_WARNING "isdn_x25iface_xmit: frame with illegal"
324 " first byte %x ignored:\n", firstbyte);
325 }
326 dev_kfree_skb(skb);
327 return 0;
328}
diff --git a/drivers/isdn/i4l/isdn_x25iface.h b/drivers/isdn/i4l/isdn_x25iface.h
new file mode 100644
index 000000000000..41a3d4977466
--- /dev/null
+++ b/drivers/isdn/i4l/isdn_x25iface.h
@@ -0,0 +1,39 @@
1/* $Id: isdn_x25iface.h,v 1.1.2.2 2004/01/12 22:37:19 keil Exp $
2 *
3 * header for Linux ISDN subsystem, x.25 related functions
4 *
5 * This software may be used and distributed according to the terms
6 * of the GNU General Public License, incorporated herein by reference.
7 *
8 */
9
10#ifndef _LINUX_ISDN_X25IFACE_H
11#define _LINUX_ISDN_X25IFACE_H
12
13#define ISDN_X25IFACE_MAGIC 0x1e75a2b9
14/* #define DEBUG_ISDN_X25 if you want isdn_x25 debugging messages */
15#ifdef DEBUG_ISDN_X25
16# define IX25DEBUG(fmt,args...) printk(KERN_DEBUG fmt , ## args)
17#else
18# define IX25DEBUG(fmt,args...)
19#endif
20
21#include <linux/skbuff.h>
22#include <linux/wanrouter.h>
23#include <linux/isdn.h>
24#include <linux/concap.h>
25
26extern struct concap_proto_ops * isdn_x25iface_concap_proto_ops_pt;
27extern struct concap_proto * isdn_x25iface_proto_new(void);
28
29
30
31#endif
32
33
34
35
36
37
38
39