summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/isdn/INTERFACE759
-rw-r--r--Documentation/isdn/INTERFACE.fax163
-rw-r--r--Documentation/isdn/README599
-rw-r--r--Documentation/isdn/README.FAQ26
-rw-r--r--Documentation/isdn/README.audio138
-rw-r--r--Documentation/isdn/README.concap259
-rw-r--r--Documentation/isdn/README.diversion127
-rw-r--r--Documentation/isdn/README.fax45
-rw-r--r--Documentation/isdn/README.hfc-pci41
-rw-r--r--Documentation/isdn/README.syncppp58
-rw-r--r--Documentation/isdn/README.x25184
-rw-r--r--Documentation/isdn/syncPPP.FAQ224
-rw-r--r--Documentation/process/changes.rst16
-rw-r--r--MAINTAINERS2
-rw-r--r--drivers/isdn/Kconfig26
-rw-r--r--drivers/isdn/Makefile2
-rw-r--r--drivers/isdn/capi/Kconfig9
-rw-r--r--drivers/isdn/capi/capidrv.c2525
-rw-r--r--drivers/isdn/capi/capidrv.h140
-rw-r--r--drivers/isdn/divert/Makefile10
-rw-r--r--drivers/isdn/divert/divert_init.c82
-rw-r--r--drivers/isdn/divert/divert_procfs.c336
-rw-r--r--drivers/isdn/divert/isdn_divert.c846
-rw-r--r--drivers/isdn/divert/isdn_divert.h132
-rw-r--r--drivers/isdn/i4l/Kconfig127
-rw-r--r--drivers/isdn/i4l/Makefile14
-rw-r--r--drivers/isdn/i4l/isdn_audio.c711
-rw-r--r--drivers/isdn/i4l/isdn_audio.h44
-rw-r--r--drivers/isdn/i4l/isdn_bsdcomp.c930
-rw-r--r--drivers/isdn/i4l/isdn_common.c2368
-rw-r--r--drivers/isdn/i4l/isdn_common.h47
-rw-r--r--drivers/isdn/i4l/isdn_concap.c99
-rw-r--r--drivers/isdn/i4l/isdn_concap.h11
-rw-r--r--drivers/isdn/i4l/isdn_net.c3198
-rw-r--r--drivers/isdn/i4l/isdn_net.h151
-rw-r--r--drivers/isdn/i4l/isdn_ppp.c3046
-rw-r--r--drivers/isdn/i4l/isdn_ppp.h41
-rw-r--r--drivers/isdn/i4l/isdn_tty.c3756
-rw-r--r--drivers/isdn/i4l/isdn_tty.h120
-rw-r--r--drivers/isdn/i4l/isdn_ttyfax.c1123
-rw-r--r--drivers/isdn/i4l/isdn_ttyfax.h17
-rw-r--r--drivers/isdn/i4l/isdn_v110.c625
-rw-r--r--drivers/isdn/i4l/isdn_v110.h29
-rw-r--r--drivers/isdn/i4l/isdn_x25iface.c332
-rw-r--r--drivers/isdn/i4l/isdn_x25iface.h30
-rw-r--r--drivers/isdn/isdnloop/Makefile6
-rw-r--r--drivers/isdn/isdnloop/isdnloop.c1528
-rw-r--r--drivers/isdn/isdnloop/isdnloop.h112
-rw-r--r--include/linux/concap.h112
-rw-r--r--include/linux/isdn.h473
-rw-r--r--include/linux/isdn_divertif.h35
-rw-r--r--include/linux/isdn_ppp.h194
-rw-r--r--include/linux/isdnif.h505
-rw-r--r--include/linux/wanrouter.h11
-rw-r--r--include/uapi/linux/isdn.h144
-rw-r--r--include/uapi/linux/isdn_divertif.h31
-rw-r--r--include/uapi/linux/isdn_ppp.h68
-rw-r--r--include/uapi/linux/isdnif.h57
-rw-r--r--include/uapi/linux/wanrouter.h18
59 files changed, 2 insertions, 26860 deletions
diff --git a/Documentation/isdn/INTERFACE b/Documentation/isdn/INTERFACE
deleted file mode 100644
index 5df17e5b25c8..000000000000
--- a/Documentation/isdn/INTERFACE
+++ /dev/null
@@ -1,759 +0,0 @@
1$Id: INTERFACE,v 1.15.8.2 2001/03/13 16:17:07 kai Exp $
2
3Description of the Interface between Linklevel and Hardwarelevel
4 of isdn4linux:
5
6
7 The Communication between Linklevel (LL) and Hardwarelevel (HL)
8 is based on the struct isdn_if (defined in isdnif.h).
9
10 An HL-driver can register itself at LL by calling the function
11 register_isdn() with a pointer to that struct. Prior to that, it has
12 to preset some of the fields of isdn_if. The LL sets the rest of
13 the fields. All further communication is done via callbacks using
14 the function-pointers defined in isdn_if.
15
16 Changes/Version numbering:
17
18 During development of the ISDN subsystem, several changes have been
19 made to the interface. Before it went into kernel, the package
20 had a unique version number. The last version, distributed separately
21 was 0.7.4. When the subsystem went into kernel, every functional unit
22 got a separate version number. These numbers are shown at initialization,
23 separated by slashes:
24
25 c.c/t.t/n.n/p.p/a.a/v.v
26
27 where
28
29 c.c is the revision of the common code.
30 t.t is the revision of the tty related code.
31 n.n is the revision of the network related code.
32 p.p is the revision of the ppp related code.
33 a.a is the revision of the audio related code.
34 v.v is the revision of the V.110 related code.
35
36 Changes in this document are marked with '***CHANGEx' where x representing
37 the version number. If that number starts with 0, it refers to the old,
38 separately distributed package. If it starts with one of the letters
39 above, it refers to the revision of the corresponding module.
40 ***CHANGEIx refers to the revision number of the isdnif.h
41
421. Description of the fields of isdn_if:
43
44 int channels;
45
46 This field has to be set by the HL-driver to the number of channels
47 supported prior to calling register_isdn(). Upon return of the call,
48 the LL puts an id there, which has to be used by the HL-driver when
49 invoking the other callbacks.
50
51 int maxbufsize;
52
53 ***CHANGE0.6: New since this version.
54
55 Also to be preset by the HL-driver. With this value the HL-driver
56 tells the LL the maximum size of a data-packet it will accept.
57
58 unsigned long features;
59
60 To be preset by the HL-driver. Using this field, the HL-driver
61 announces the features supported. At the moment this is limited to
62 report the supported layer2 and layer3-protocols. For setting this
63 field the constants ISDN_FEATURE..., declared in isdnif.h have to be
64 used.
65
66 ***CHANGE0.7.1: The line type (1TR6, EDSS1) has to be set.
67
68 unsigned short hl_hdrlen;
69
70 ***CHANGE0.7.4: New field.
71
72 To be preset by the HL-driver, if it supports sk_buff's. The driver
73 should put here the amount of additional space needed in sk_buff's for
74 its internal purposes. Drivers not supporting sk_buff's should
75 initialize this field to 0.
76
77 void (*rcvcallb_skb)(int, int, struct sk_buff *)
78
79 ***CHANGE0.7.4: New field.
80
81 This field will be set by LL. The HL-driver delivers received data-
82 packets by calling this function. Upon calling, the HL-driver must
83 already have its private data pulled off the head of the sk_buff.
84
85 Parameter:
86 int driver-Id
87 int Channel-number locally to the driver. (starting with 0)
88 struct sk_buff * Pointer to sk_buff, containing received data.
89
90 int (*statcallb)(isdn_ctrl*);
91
92 This field will be set by LL. This function has to be called by the
93 HL-driver for signaling status-changes or other events to the LL.
94
95 Parameter:
96 isdn_ctrl*
97
98 The struct isdn_ctrl also defined in isdn_if. The exact meanings of its
99 fields are described together with the descriptions of the possible
100 events. Here is only a short description of the fields:
101
102 driver = driver Id.
103 command = event-type. (one of the constants ISDN_STAT_...)
104 arg = depends on event-type.
105 num = depends on event-type.
106
107 Returnvalue:
108 0 on success, else -1
109
110 int (*command)(isdn_ctrl*);
111
112 This field has to be preset by the HL-driver. It points to a function,
113 to be called by LL to perform functions like dialing, B-channel
114 setup, etc. The exact meaning of the parameters is described with the
115 descriptions of the possible commands.
116
117 Parameter:
118 isdn_ctrl*
119 driver = driver-Id
120 command = command to perform. (one of the constants ISDN_CMD_...)
121 arg = depends on command.
122 num = depends on command.
123
124 Returnvalue:
125 >=0 on success, else error-code (-ENODEV etc.)
126
127 int (*writebuf_skb)(int, int, int, struct sk_buff *)
128
129 ***CHANGE0.7.4: New field.
130 ***CHANGEI.1.21: New field.
131
132 This field has to be preset by the HL-driver. The given function will
133 be called by the LL for delivering data to be send via B-Channel.
134
135
136 Parameter:
137 int driver-Id ***CHANGE0.7.4: New parameter.
138 int channel-number locally to the HL-driver. (starts with 0)
139 int ack ***ChangeI1.21: New parameter
140 If this is !0, the driver has to signal the delivery
141 by sending an ISDN_STAT_BSENT. If this is 0, the driver
142 MUST NOT send an ISDN_STAT_BSENT.
143 struct sk_buff * Pointer to sk_buff containing data to be send via
144 B-channel.
145
146 Returnvalue:
147 Length of data accepted on success, else error-code (-EINVAL on
148 oversized packets etc.)
149
150 int (*writecmd)(u_char*, int, int, int, int);
151
152 This field has to be preset by the HL-driver. The given function will be
153 called to perform write-requests on /dev/isdnctrl (i.e. sending commands
154 to the card) The data-format is hardware-specific. This function is
155 intended for debugging only. It is not necessary for normal operation
156 and never will be called by the tty-emulation- or network-code. If
157 this function is not supported, the driver has to set NULL here.
158
159 Parameter:
160 u_char* pointer to data.
161 int length of data.
162 int flag: 0 = call from within kernel-space. (HL-driver must use
163 memcpy, may NOT use schedule())
164 1 = call from user-space. (HL-driver must use
165 memcpy_fromfs, use of schedule() allowed)
166 int driver-Id.
167 int channel-number locally to the HL-driver. (starts with 0)
168
169***CHANGEI1.14: The driver-Id and channel-number are new since this revision.
170
171 Returnvalue:
172 Length of data accepted on success, else error-code (-EINVAL etc.)
173
174 int (*readstat)(u_char*, int, int, int, int);
175
176 This field has to be preset by the HL-driver. The given function will be
177 called to perform read-requests on /dev/isdnctrl (i.e. reading replies
178 from the card) The data-format is hardware-specific. This function is
179 intended for debugging only. It is not necessary for normal operation
180 and never will be called by the tty-emulation- or network-code. If
181 this function is not supported, the driver has to set NULL here.
182
183 Parameter:
184 u_char* pointer to data.
185 int length of data.
186 int flag: 0 = call from within kernel-space. (HL-driver must use
187 memcpy, may NOT use schedule())
188 1 = call from user-space. (HL-driver must use
189 memcpy_fromfs, use of schedule() allowed)
190 int driver-Id.
191 int channel-number locally to the HL-driver. (starts with 0)
192
193***CHANGEI1.14: The driver-Id and channel-number are new since this revision.
194
195 Returnvalue:
196 Length of data on success, else error-code (-EINVAL etc.)
197
198 char id[20];
199 ***CHANGE0.7: New since this version.
200
201 This string has to be preset by the HL-driver. Its purpose is for
202 identification of the driver by the user. Eg.: it is shown in the
203 status-info of /dev/isdninfo. Furthermore it is used as Id for binding
204 net-interfaces to a specific channel. If a string of length zero is
205 given, upon return, isdn4linux will replace it by a generic name. (line0,
206 line1 etc.) It is recommended to make this string configurable during
207 module-load-time. (copy a global variable to this string.) For doing that,
208 modules 1.2.8 or newer are necessary.
209
2102. Description of the commands, a HL-driver has to support:
211
212 All commands will be performed by calling the function command() described
213 above from within the LL. The field command of the struct-parameter will
214 contain the desired command, the field driver is always set to the
215 appropriate driver-Id.
216
217 Until now, the following commands are defined:
218
219***CHANGEI1.34: The parameter "num" has been replaced by a union "parm" containing
220 the old "num" and a new setup_type struct used for ISDN_CMD_DIAL
221 and ISDN_STAT_ICALL callback.
222
223 ISDN_CMD_IOCTL:
224
225 This command is intended for performing ioctl-calls for configuring
226 hardware or similar purposes (setting port-addresses, loading firmware
227 etc.) For this purpose, in the LL all ioctl-calls with an argument
228 >= IIOCDRVCTL (0x100) will be handed transparently to this
229 function after subtracting 0x100 and placing the result in arg.
230 Example:
231 If a userlevel-program calls ioctl(0x101,...) the function gets
232 called with the field command set to 1.
233
234 Parameter:
235 driver = driver-Id.
236 command = ISDN_CMD_IOCTL
237 arg = Original ioctl-cmd - IIOCDRVCTL
238 parm.num = first bytes filled with (unsigned long)arg
239
240 Returnvalue:
241 Depending on driver.
242
243
244 ISDN_CMD_DIAL:
245
246 This command is used to tell the HL-driver it should dial a given
247 number.
248
249 Parameter:
250 driver = driver-Id.
251 command = ISDN_CMD_DIAL
252 arg = channel-number locally to the driver. (starting with 0)
253
254 parm.setup.phone = An ASCII-String containing the number to dial.
255 parm.setup.eazmsn = An ASCII-Sting containing the own EAZ or MSN.
256 parm.setup.si1 = The Service-Indicator.
257 parm.setup.si2 = Additional Service-Indicator.
258
259 If the Line has been designed as SPV (a special german
260 feature, meaning semi-leased-line) the phone has to
261 start with an "S".
262 ***CHANGE0.6: In previous versions the EAZ has been given in the
263 highbyte of arg.
264 ***CHANGE0.7.1: New since this version: ServiceIndicator and AddInfo.
265
266 ISDN_CMD_ACCEPTD:
267
268 With this command, the HL-driver is told to accept a D-Channel-setup.
269 (Response to an incoming call)
270
271 Parameter:
272 driver = driver-Id.
273 command = ISDN_CMD_ACCEPTD
274 arg = channel-number locally to the driver. (starting with 0)
275 parm = unused.
276
277 ISDN_CMD_ACCEPTB:
278
279 With this command, the HL-driver is told to perform a B-Channel-setup.
280 (after establishing D-Channel-Connection)
281
282 Parameter:
283 driver = driver-Id.
284 command = ISDN_CMD_ACCEPTB
285 arg = channel-number locally to the driver. (starting with 0)
286 parm = unused.
287
288 ISDN_CMD_HANGUP:
289
290 With this command, the HL-driver is told to hangup (B-Channel if
291 established first, then D-Channel). This command is also used for
292 actively rejecting an incoming call.
293
294 Parameter:
295 driver = driver-Id.
296 command = ISDN_CMD_HANGUP
297 arg = channel-number locally to the driver. (starting with 0)
298 parm = unused.
299
300 ISDN_CMD_CLREAZ:
301
302 With this command, the HL-driver is told not to signal incoming
303 calls to the LL.
304
305 Parameter:
306 driver = driver-Id.
307 command = ISDN_CMD_CLREAZ
308 arg = channel-number locally to the driver. (starting with 0)
309 parm = unused.
310
311 ISDN_CMD_SETEAZ:
312
313 With this command, the HL-driver is told to signal incoming calls for
314 the given EAZs/MSNs to the LL.
315
316 Parameter:
317 driver = driver-Id.
318 command = ISDN_CMD_SETEAZ
319 arg = channel-number locally to the driver. (starting with 0)
320 parm.num = ASCII-String, containing the desired EAZ's/MSN's
321 (comma-separated). If an empty String is given, the
322 HL-driver should respond to ALL incoming calls,
323 regardless of the destination-address.
324 ***CHANGE0.6: New since this version the "empty-string"-feature.
325
326 ISDN_CMD_GETEAZ: (currently unused)
327
328 With this command, the HL-driver is told to report the current setting
329 given with ISDN_CMD_SETEAZ.
330
331 Parameter:
332 driver = driver-Id.
333 command = ISDN_CMD_GETEAZ
334 arg = channel-number locally to the driver. (starting with 0)
335 parm.num = ASCII-String, containing the current EAZ's/MSN's
336
337 ISDN_CMD_SETSIL: (currently unused)
338
339 With this command, the HL-driver is told to signal only incoming
340 calls with the given Service-Indicators.
341
342 Parameter:
343 driver = driver-Id.
344 command = ISDN_CMD_SETSIL
345 arg = channel-number locally to the driver. (starting with 0)
346 parm.num = ASCII-String, containing the desired Service-Indicators.
347
348 ISDN_CMD_GETSIL: (currently unused)
349
350 With this command, the HL-driver is told to return the current
351 Service-Indicators it will respond to.
352
353 Parameter:
354 driver = driver-Id.
355 command = ISDN_CMD_SETSIL
356 arg = channel-number locally to the driver. (starting with 0)
357 parm.num = ASCII-String, containing the current Service-Indicators.
358
359 ISDN_CMD_SETL2:
360
361 With this command, the HL-driver is told to select the given Layer-2-
362 protocol. This command is issued by the LL prior to ISDN_CMD_DIAL or
363 ISDN_CMD_ACCEPTD.
364
365
366 Parameter:
367 driver = driver-Id.
368 command = ISDN_CMD_SETL2
369 arg = channel-number locally to the driver. (starting with 0)
370 logical or'ed with (protocol-Id << 8)
371 protocol-Id is one of the constants ISDN_PROTO_L2...
372 parm = unused.
373
374 ISDN_CMD_GETL2: (currently unused)
375
376 With this command, the HL-driver is told to return the current
377 setting of the Layer-2-protocol.
378
379 Parameter:
380 driver = driver-Id.
381 command = ISDN_CMD_GETL2
382 arg = channel-number locally to the driver. (starting with 0)
383 parm = unused.
384 Returnvalue:
385 current protocol-Id (one of the constants ISDN_L2_PROTO)
386
387 ISDN_CMD_SETL3:
388
389 With this command, the HL-driver is told to select the given Layer-3-
390 protocol. This command is issued by the LL prior to ISDN_CMD_DIAL or
391 ISDN_CMD_ACCEPTD.
392
393
394 Parameter:
395 driver = driver-Id.
396 command = ISDN_CMD_SETL3
397 arg = channel-number locally to the driver. (starting with 0)
398 logical or'ed with (protocol-Id << 8)
399 protocol-Id is one of the constants ISDN_PROTO_L3...
400 parm.fax = Pointer to T30_s fax struct. (fax usage only)
401
402 ISDN_CMD_GETL2: (currently unused)
403
404 With this command, the HL-driver is told to return the current
405 setting of the Layer-3-protocol.
406
407 Parameter:
408 driver = driver-Id.
409 command = ISDN_CMD_GETL3
410 arg = channel-number locally to the driver. (starting with 0)
411 parm = unused.
412 Returnvalue:
413 current protocol-Id (one of the constants ISDN_L3_PROTO)
414
415 ISDN_CMD_PROCEED:
416
417 With this command, the HL-driver is told to proceed with a incoming call.
418
419 Parameter:
420 driver = driver-Id.
421 command = ISDN_CMD_PROCEED
422 arg = channel-number locally to the driver. (starting with 0)
423 setup.eazmsn= empty string or string send as uus1 in DSS1 with
424 PROCEED message
425
426 ISDN_CMD_ALERT:
427
428 With this command, the HL-driver is told to alert a proceeding call.
429
430 Parameter:
431 driver = driver-Id.
432 command = ISDN_CMD_ALERT
433 arg = channel-number locally to the driver. (starting with 0)
434 setup.eazmsn= empty string or string send as uus1 in DSS1 with
435 ALERT message
436
437 ISDN_CMD_REDIR:
438
439 With this command, the HL-driver is told to redirect a call in proceeding
440 or alerting state.
441
442 Parameter:
443 driver = driver-Id.
444 command = ISDN_CMD_REDIR
445 arg = channel-number locally to the driver. (starting with 0)
446 setup.eazmsn= empty string or string send as uus1 in DSS1 protocol
447 setup.screen= screening indicator
448 setup.phone = redirected to party number
449
450 ISDN_CMD_PROT_IO:
451
452 With this call, the LL-driver invokes protocol specific features through
453 the LL.
454 The call is not implicitely bound to a connection.
455
456 Parameter:
457 driver = driver-Id
458 command = ISDN_CMD_PROT_IO
459 arg = The lower 8 Bits define the addressed protocol as defined
460 in ISDN_PTYPE..., the upper bits are used to differentiate
461 the protocol specific CMD.
462
463 para = protocol and function specific. See isdnif.h for detail.
464
465
466 ISDN_CMD_FAXCMD:
467
468 With this command the HL-driver receives a fax sub-command.
469 For details refer to INTERFACE.fax
470
471 Parameter:
472 driver = driver-Id.
473 command = ISDN_CMD_FAXCMD
474 arg = channel-number locally to the driver. (starting with 0)
475 parm = unused.
476
477
4783. Description of the events to be signaled by the HL-driver to the LL.
479
480 All status-changes are signaled via calling the previously described
481 function statcallb(). The field command of the struct isdn_cmd has
482 to be set by the HL-driver with the appropriate Status-Id (event-number).
483 The field arg has to be set to the channel-number (locally to the driver,
484 starting with 0) to which this event applies. (Exception: STAVAIL-event)
485
486 Until now, the following Status-Ids are defined:
487
488 ISDN_STAT_AVAIL:
489
490 With this call, the HL-driver signals the availability of new data
491 for readstat(). Used only for debugging-purposes, see description
492 of readstat().
493
494 Parameter:
495 driver = driver-Id
496 command = ISDN_STAT_STAVAIL
497 arg = length of available data.
498 parm = unused.
499
500 ISDN_STAT_ICALL:
501 ISDN_STAT_ICALLW:
502
503 With this call, the HL-driver signals an incoming call to the LL.
504 If ICALLW is signalled the incoming call is a waiting call without
505 a available B-chan.
506
507 Parameter:
508 driver = driver-Id
509 command = ISDN_STAT_ICALL
510 arg = channel-number, locally to the driver. (starting with 0)
511 para.setup.phone = Callernumber.
512 para.setup.eazmsn = CalledNumber.
513 para.setup.si1 = Service Indicator.
514 para.setup.si2 = Additional Service Indicator.
515 para.setup.plan = octet 3 from Calling party number Information Element.
516 para.setup.screen = octet 3a from Calling party number Information Element.
517
518 Return:
519 0 = No device matching this call.
520 1 = At least one device matching this call (RING on ttyI).
521 HL-driver may send ALERTING on the D-channel in this case.
522 2 = Call will be rejected.
523 3 = Incoming called party number is currently incomplete.
524 Additional digits are required.
525 Used for signalling with PtP connections.
526 4 = Call will be held in a proceeding state
527 (HL driver sends PROCEEDING)
528 Used when a user space prog needs time to interpret a call
529 para.setup.eazmsn may be filled with an uus1 message of
530 30 octets maximum. Empty string if no uus.
531 5 = Call will be actively deflected to another party
532 Only available in DSS1/EURO protocol
533 para.setup.phone must be set to destination party number
534 para.setup.eazmsn may be filled with an uus1 message of
535 30 octets maximum. Empty string if no uus.
536 -1 = An error happened. (Invalid parameters for example.)
537 The keypad support now is included in the dial command.
538
539
540 ISDN_STAT_RUN:
541
542 With this call, the HL-driver signals availability of the ISDN-card.
543 (after initializing, loading firmware)
544
545 Parameter:
546 driver = driver-Id
547 command = ISDN_STAT_RUN
548 arg = unused.
549 parm = unused.
550
551 ISDN_STAT_STOP:
552
553 With this call, the HL-driver signals unavailability of the ISDN-card.
554 (before unloading, while resetting/reconfiguring the card)
555
556 Parameter:
557 driver = driver-Id
558 command = ISDN_STAT_STOP
559 arg = unused.
560 parm = unused.
561
562 ISDN_STAT_DCONN:
563
564 With this call, the HL-driver signals the successful establishment of
565 a D-Channel-connection. (Response to ISDN_CMD_ACCEPTD or ISDN_CMD_DIAL)
566
567 Parameter:
568 driver = driver-Id
569 command = ISDN_STAT_DCONN
570 arg = channel-number, locally to the driver. (starting with 0)
571 parm = unused.
572
573 ISDN_STAT_BCONN:
574
575 With this call, the HL-driver signals the successful establishment of
576 a B-Channel-connection. (Response to ISDN_CMD_ACCEPTB or because the
577 remote-station has initiated establishment)
578
579 The HL driver should call this when the logical l2/l3 protocol
580 connection on top of the physical B-channel is established.
581
582 Parameter:
583 driver = driver-Id
584 command = ISDN_STAT_BCONN
585 arg = channel-number, locally to the driver. (starting with 0)
586 parm.num = ASCII-String, containing type of connection (for analog
587 modem only). This will be appended to the CONNECT message
588 e.g. 14400/V.32bis
589
590 ISDN_STAT_DHUP:
591
592 With this call, the HL-driver signals the shutdown of a
593 D-Channel-connection. This could be a response to a prior ISDN_CMD_HANGUP,
594 or caused by a remote-hangup or if the remote-station has actively
595 rejected a call.
596
597 Parameter:
598 driver = driver-Id
599 command = ISDN_STAT_DHUP
600 arg = channel-number, locally to the driver. (starting with 0)
601 parm = unused.
602
603 ISDN_STAT_BHUP:
604
605 With this call, the HL-driver signals the shutdown of a
606 B-Channel-connection. This could be a response to a prior ISDN_CMD_HANGUP,
607 or caused by a remote-hangup.
608
609 The HL driver should call this as soon as the logical l2/l3 protocol
610 connection on top of the physical B-channel is released.
611
612 Parameter:
613 driver = driver-Id
614 command = ISDN_STAT_BHUP
615 arg = channel-number, locally to the driver. (starting with 0)
616 parm = unused.
617
618 ISDN_STAT_CINF:
619
620 With this call, the HL-driver delivers charge-unit information to the
621 LL.
622
623 Parameter:
624 driver = driver-Id
625 command = ISDN_STAT_CINF
626 arg = channel-number, locally to the driver. (starting with 0)
627 parm.num = ASCII string containing charge-units (digits only).
628
629 ISDN_STAT_LOAD: (currently unused)
630
631 ISDN_STAT_UNLOAD:
632
633 With this call, the HL-driver signals that it will be unloaded now. This
634 tells the LL to release all corresponding data-structures.
635
636 Parameter:
637 driver = driver-Id
638 command = ISDN_STAT_UNLOAD
639 arg = unused.
640 parm = unused.
641
642 ISDN_STAT_BSENT:
643
644 With this call the HL-driver signals the delivery of a data-packet.
645 This callback is used by the network-interfaces only, tty-Emulation
646 does not need this call.
647
648 Parameter:
649 driver = driver-Id
650 command = ISDN_STAT_BSENT
651 arg = channel-number, locally to the driver. (starting with 0)
652 parm.length = ***CHANGEI.1.21: New field.
653 the driver has to set this to the original length
654 of the skb at the time of receiving it from the linklevel.
655
656 ISDN_STAT_NODCH:
657
658 With this call, the driver has to respond to a prior ISDN_CMD_DIAL, if
659 no D-Channel is available.
660
661 Parameter:
662 driver = driver-Id
663 command = ISDN_STAT_NODCH
664 arg = channel-number, locally to the driver. (starting with 0)
665 parm = unused.
666
667 ISDN_STAT_ADDCH:
668
669 This call is for HL-drivers, which are unable to check card-type
670 or numbers of supported channels before they have loaded any firmware
671 using ioctl. Those HL-driver simply set the channel-parameter to a
672 minimum channel-number when registering, and later if they know
673 the real amount, perform this call, allocating additional channels.
674
675 Parameter:
676 driver = driver-Id
677 command = ISDN_STAT_ADDCH
678 arg = number of channels to be added.
679 parm = unused.
680
681 ISDN_STAT_CAUSE:
682
683 With this call, the HL-driver delivers CAUSE-messages to the LL.
684 Currently the LL does not use this messages. Their contents is simply
685 logged via kernel-messages. Therefore, currently the format of the
686 messages is completely free. However they should be printable.
687
688 Parameter:
689 driver = driver-Id
690 command = ISDN_STAT_NODCH
691 arg = channel-number, locally to the driver. (starting with 0)
692 parm.num = ASCII string containing CAUSE-message.
693
694 ISDN_STAT_DISPLAY:
695
696 With this call, the HL-driver delivers DISPLAY-messages to the LL.
697 Currently the LL does not use this messages.
698
699 Parameter:
700 driver = driver-Id
701 command = ISDN_STAT_DISPLAY
702 arg = channel-number, locally to the driver. (starting with 0)
703 para.display= string containing DISPLAY-message.
704
705 ISDN_STAT_PROT:
706
707 With this call, the HL-driver delivers protocol specific infos to the LL.
708 The call is not implicitely bound to a connection.
709
710 Parameter:
711 driver = driver-Id
712 command = ISDN_STAT_PROT
713 arg = The lower 8 Bits define the addressed protocol as defined
714 in ISDN_PTYPE..., the upper bits are used to differentiate
715 the protocol specific STAT.
716
717 para = protocol and function specific. See isdnif.h for detail.
718
719 ISDN_STAT_DISCH:
720
721 With this call, the HL-driver signals the LL to disable or enable the
722 use of supplied channel and driver.
723 The call may be used to reduce the available number of B-channels after
724 loading the driver. The LL has to ignore a disabled channel when searching
725 for free channels. The HL driver itself never delivers STAT callbacks for
726 disabled channels.
727 The LL returns a nonzero code if the operation was not successful or the
728 selected channel is actually regarded as busy.
729
730 Parameter:
731 driver = driver-Id
732 command = ISDN_STAT_DISCH
733 arg = channel-number, locally to the driver. (starting with 0)
734 parm.num[0] = 0 if channel shall be disabled, else enabled.
735
736 ISDN_STAT_L1ERR:
737
738 ***CHANGEI1.21 new status message.
739 A signal can be sent to the linklevel if an Layer1-error results in
740 packet-loss on receive or send. The field errcode of the cmd.parm
741 union describes the error more precisely.
742
743 Parameter:
744 driver = driver-Id
745 command = ISDN_STAT_L1ERR
746 arg = channel-number, locally to the driver. (starting with 0)
747 parm.errcode= ISDN_STAT_L1ERR_SEND: Packet lost while sending.
748 ISDN_STAT_L1ERR_RECV: Packet lost while receiving.
749 ISDN_STAT_FAXIND:
750
751 With this call the HL-driver signals a fax sub-command to the LL.
752 For details refer to INTERFACE.fax
753
754 Parameter:
755 driver = driver-Id.
756 command = ISDN_STAT_FAXIND
757 arg = channel-number, locally to the driver. (starting with 0)
758 parm = unused.
759
diff --git a/Documentation/isdn/INTERFACE.fax b/Documentation/isdn/INTERFACE.fax
deleted file mode 100644
index 9c8c6d914ec7..000000000000
--- a/Documentation/isdn/INTERFACE.fax
+++ /dev/null
@@ -1,163 +0,0 @@
1$Id: INTERFACE.fax,v 1.2 2000/08/06 09:22:50 armin Exp $
2
3
4Description of the fax-subinterface between linklevel and hardwarelevel of
5 isdn4linux.
6
7 The communication between linklevel (LL) and hardwarelevel (HL) for fax
8 is based on the struct T30_s (defined in isdnif.h).
9 This struct is allocated in the LL.
10 In order to use fax, the LL provides the pointer to this struct with the
11 command ISDN_CMD_SETL3 (parm.fax). This pointer expires in case of hangup
12 and when a new channel to a new connection is assigned.
13
14
15Data handling:
16 In send-mode the HL-driver has to handle the <DLE> codes and the bit-order
17 conversion by itself.
18 In receive-mode the LL-driver takes care of the bit-order conversion
19 (specified by +FBOR)
20
21Structure T30_s description:
22
23 This structure stores the values (set by AT-commands), the remote-
24 capability-values and the command-codes between LL and HL.
25
26 If the HL-driver receives ISDN_CMD_FAXCMD, all needed information
27 is in this struct set by the LL.
28 To signal information to the LL, the HL-driver has to set the
29 parameters and use ISDN_STAT_FAXIND.
30 (Please refer to INTERFACE)
31
32Structure T30_s:
33
34 All members are 8-bit unsigned (__u8)
35
36 - resolution
37 - rate
38 - width
39 - length
40 - compression
41 - ecm
42 - binary
43 - scantime
44 - id[]
45 Local faxmachine's parameters, set by +FDIS, +FDCS, +FLID, ...
46
47 - r_resolution
48 - r_rate
49 - r_width
50 - r_length
51 - r_compression
52 - r_ecm
53 - r_binary
54 - r_scantime
55 - r_id[]
56 Remote faxmachine's parameters. To be set by HL-driver.
57
58 - phase
59 Defines the actual state of fax connection. Set by HL or LL
60 depending on progress and type of connection.
61 If the phase changes because of an AT command, the LL driver
62 changes this value. Otherwise the HL-driver takes care of it, but
63 only necessary on call establishment (from IDLE to PHASE_A).
64 (one of the constants ISDN_FAX_PHASE_[IDLE,A,B,C,D,E])
65
66 - direction
67 Defines outgoing/send or incoming/receive connection.
68 (ISDN_TTY_FAX_CONN_[IN,OUT])
69
70 - code
71 Commands from LL to HL; possible constants :
72 ISDN_TTY_FAX_DR signals +FDR command to HL
73
74 ISDN_TTY_FAX_DT signals +FDT command to HL
75
76 ISDN_TTY_FAX_ET signals +FET command to HL
77
78
79 Other than that the "code" is set with the hangup-code value at
80 the end of connection for the +FHNG message.
81
82 - r_code
83 Commands from HL to LL; possible constants :
84 ISDN_TTY_FAX_CFR output of +FCFR message.
85
86 ISDN_TTY_FAX_RID output of remote ID set in r_id[]
87 (+FCSI/+FTSI on send/receive)
88
89 ISDN_TTY_FAX_DCS output of +FDCS and CONNECT message,
90 switching to phase C.
91
92 ISDN_TTY_FAX_ET signals end of data,
93 switching to phase D.
94
95 ISDN_TTY_FAX_FCON signals the established, outgoing connection,
96 switching to phase B.
97
98 ISDN_TTY_FAX_FCON_I signals the established, incoming connection,
99 switching to phase B.
100
101 ISDN_TTY_FAX_DIS output of +FDIS message and values.
102
103 ISDN_TTY_FAX_SENT signals that all data has been sent
104 and <DLE><ETX> is acknowledged,
105 OK message will be sent.
106
107 ISDN_TTY_FAX_PTS signals a msg-confirmation (page sent successful),
108 depending on fet value:
109 0: output OK message (more pages follow)
110 1: switching to phase B (next document)
111
112 ISDN_TTY_FAX_TRAIN_OK output of +FDCS and OK message (for receive mode).
113
114 ISDN_TTY_FAX_EOP signals end of data in receive mode,
115 switching to phase D.
116
117 ISDN_TTY_FAX_HNG output of the +FHNG and value set by code and
118 OK message, switching to phase E.
119
120
121 - badlin
122 Value of +FBADLIN
123
124 - badmul
125 Value of +FBADMUL
126
127 - bor
128 Value of +FBOR
129
130 - fet
131 Value of +FET command in send-mode.
132 Set by HL in receive-mode for +FET message.
133
134 - pollid[]
135 ID-string, set by +FCIG
136
137 - cq
138 Value of +FCQ
139
140 - cr
141 Value of +FCR
142
143 - ctcrty
144 Value of +FCTCRTY
145
146 - minsp
147 Value of +FMINSP
148
149 - phcto
150 Value of +FPHCTO
151
152 - rel
153 Value of +FREL
154
155 - nbc
156 Value of +FNBC (0,1)
157 (+FNBC is not a known class 2 fax command, I added this to change the
158 automatic "best capabilities" connection in the eicon HL-driver)
159
160
161Armin
162mac@melware.de
163
diff --git a/Documentation/isdn/README b/Documentation/isdn/README
deleted file mode 100644
index 74bd2bdb455b..000000000000
--- a/Documentation/isdn/README
+++ /dev/null
@@ -1,599 +0,0 @@
1README for the ISDN-subsystem
2
31. Preface
4
5 1.1 Introduction
6
7 This README describes how to set up and how to use the different parts
8 of the ISDN-subsystem.
9
10 For using the ISDN-subsystem, some additional userlevel programs are
11 necessary. Those programs and some contributed utilities are available
12 at
13
14 ftp.isdn4linux.de
15
16 /pub/isdn4linux/isdn4k-utils-<VersionNumber>.tar.gz
17
18
19 We also have set up a mailing-list:
20
21 The isdn4linux-project originates in Germany, and therefore by historical
22 reasons, the mailing-list's primary language is german. However mails
23 written in english have been welcome all the time.
24
25 to subscribe: write a email to majordomo@listserv.isdn4linux.de,
26 Subject irrelevant, in the message body:
27 subscribe isdn4linux <your_email_address>
28
29 To write to the mailing-list, write to isdn4linux@listserv.isdn4linux.de
30
31 This mailinglist is bidirectionally gated to the newsgroup
32
33 de.alt.comm.isdn4linux
34
35 There is also a well maintained FAQ in English available at
36 https://www.mhessler.de/i4lfaq/
37 It can be viewed online, or downloaded in sgml/text/html format.
38 The FAQ can also be viewed online at
39 https://www.isdn4linux.de/faq/i4lfaq.html
40 or downloaded from
41 ftp://ftp.isdn4linux.de/pub/isdn4linux/FAQ/
42
43 1.1 Technical details
44
45 In the following Text, the terms MSN and EAZ are used.
46
47 MSN is the abbreviation for (M)ultiple(S)ubscriber(N)umber, and applies
48 to Euro(EDSS1)-type lines. Usually it is simply the phone number.
49
50 EAZ is the abbreviation of (E)ndgeraete(A)uswahl(Z)iffer and
51 applies to German 1TR6-type lines. This is a one-digit string,
52 simply appended to the base phone number
53
54 The internal handling is nearly identical, so replace the appropriate
55 term to that one, which applies to your local ISDN-environment.
56
57 When the link-level-module isdn.o is loaded, it supports up to 16
58 low-level-modules with up to 64 channels. (The number 64 is arbitrarily
59 chosen and can be configured at compile-time --ISDN_MAX in isdn.h).
60 A low-level-driver can register itself through an interface (which is
61 defined in isdnif.h) and gets assigned a slot.
62 The following char-devices are made available for each channel:
63
64 A raw-control-device with the following functions:
65 write: raw D-channel-messages (format: depends on driver).
66 read: raw D-channel-messages (format: depends on driver).
67 ioctl: depends on driver, i.e. for the ICN-driver, the base-address of
68 the ports and the shared memory on the card can be set and read
69 also the boot-code and the protocol software can be loaded into
70 the card.
71
72 O N L Y !!! for debugging (no locking against other devices):
73 One raw-data-device with the following functions:
74 write: data to B-channel.
75 read: data from B-channel.
76
77 In addition the following devices are made available:
78
79 128 tty-devices (64 cuix and 64 ttyIx) with integrated modem-emulator:
80 The functionality is almost the same as that of a serial device
81 (the line-discs are handled by the kernel), which lets you run
82 SLIP, CSLIP and asynchronous PPP through the devices. We have tested
83 Seyon, minicom, CSLIP (uri-dip) PPP, mgetty, XCept and Hylafax.
84
85 The modem-emulation supports the following:
86 1.3.1 Commands:
87
88 ATA Answer incoming call.
89 ATD<No.> Dial, the number may contain:
90 [0-9] and [,#.*WPT-S]
91 the latter are ignored until 'S'.
92 The 'S' must precede the number, if
93 the line is a SPV (German 1TR6).
94 ATE0 Echo off.
95 ATE1 Echo on (default).
96 ATH Hang-up.
97 ATH1 Off hook (ignored).
98 ATH0 Hang-up.
99 ATI Return "ISDN for Linux...".
100 ATI0 "
101 ATI1 "
102 ATI2 Report of last connection.
103 ATO On line (data mode).
104 ATQ0 Enable result codes (default).
105 ATQ1 Disable result codes (default).
106 ATSx=y Set register x to y.
107 ATSx? Show contents of register x.
108 ATV0 Numeric responses.
109 ATV1 English responses (default).
110 ATZ Load registers and EAZ/MSN from Profile.
111 AT&Bx Set Send-Packet-size to x (max. 4000)
112 The real packet-size may be limited by the
113 low-level-driver used. e.g. the HiSax-Module-
114 limit is 2000. You will get NO Error-Message,
115 if you set it to higher values, because at the
116 time of giving this command the corresponding
117 driver may not be selected (see "Automatic
118 Assignment") however the size of outgoing packets
119 will be limited correctly.
120 AT&D0 Ignore DTR
121 AT&D2 DTR-low-edge: Hang up and return to
122 command mode (default).
123 AT&D3 Same as AT&D2 but also resets all registers.
124 AT&Ex Set the EAZ/MSN for this channel to x.
125 AT&F Reset all registers and profile to "factory-defaults"
126 AT&Lx Set list of phone numbers to listen on. x is a
127 list of wildcard patterns separated by semicolon.
128 If this is set, it has precedence over the MSN set
129 by AT&E.
130 AT&Rx Select V.110 bitrate adaption.
131 This command enables V.110 protocol with 9600 baud
132 (x=9600), 19200 baud (x=19200) or 38400 baud
133 (x=38400). A value of x=0 disables V.110 switching
134 back to default X.75. This command sets the following
135 Registers:
136 Reg 14 (Layer-2 protocol):
137 x = 0: 0
138 x = 9600: 7
139 x = 19200: 8
140 x = 38400: 9
141 Reg 18.2 = 1
142 Reg 19 (Additional Service Indicator):
143 x = 0: 0
144 x = 9600: 197
145 x = 19200: 199
146 x = 38400: 198
147 Note on value in Reg 19:
148 There is _NO_ common convention for 38400 baud.
149 The value 198 is chosen arbitrarily. Users
150 _MUST_ negotiate this value before establishing
151 a connection.
152 AT&Sx Set window-size (x = 1..8) (not yet implemented)
153 AT&V Show all settings.
154 AT&W0 Write registers and EAZ/MSN to profile. See also
155 iprofd (5.c in this README).
156 AT&X0 BTX-mode and T.70-mode off (default)
157 AT&X1 BTX-mode on. (S13.1=1, S13.5=0 S14=0, S16=7, S18=7, S19=0)
158 AT&X2 T.70-mode on. (S13.1=1, S13.5=1, S14=0, S16=7, S18=7, S19=0)
159 AT+Rx Resume a suspended call with CallID x (x = 1,2,3...)
160 AT+Sx Suspend a call with CallID x (x = 1,2,3...)
161
162 For voice-mode commands refer to README.audio
163
164 1.3.2 Escape sequence:
165 During a connection, the emulation reacts just like
166 a normal modem to the escape sequence <DELAY>+++<DELAY>.
167 (The escape character - default '+' - can be set in the
168 register 2).
169 The DELAY must at least be 1.5 seconds long and delay
170 between the escape characters must not exceed 0.5 seconds.
171
172 1.3.3 Registers:
173
174 Nr. Default Description
175 0 0 Answer on ring number.
176 (no auto-answer if S0=0).
177 1 0 Count of rings.
178 2 43 Escape character.
179 (a value >= 128 disables the escape sequence).
180 3 13 Carriage return character (ASCII).
181 4 10 Line feed character (ASCII).
182 5 8 Backspace character (ASCII).
183 6 3 Delay in seconds before dialing.
184 7 60 Wait for carrier.
185 8 2 Pause time for comma (ignored)
186 9 6 Carrier detect time (ignored)
187 10 7 Carrier loss to disconnect time (ignored).
188 11 70 Touch tone timing (ignored).
189 12 69 Bit coded register:
190 Bit 0: 0 = Suppress response messages.
191 1 = Show response messages.
192 Bit 1: 0 = English response messages.
193 1 = Numeric response messages.
194 Bit 2: 0 = Echo off.
195 1 = Echo on.
196 Bit 3 0 = DCD always on.
197 1 = DCD follows carrier.
198 Bit 4 0 = CTS follows RTS
199 1 = Ignore RTS, CTS always on.
200 Bit 5 0 = return to command mode on DTR low.
201 1 = Same as 0 but also resets all
202 registers.
203 See also register 13, bit 2
204 Bit 6 0 = DSR always on.
205 1 = DSR only on if channel is available.
206 Bit 7 0 = Cisco-PPP-flag-hack off (default).
207 1 = Cisco-PPP-flag-hack on.
208 13 0 Bit coded register:
209 Bit 0: 0 = Use delayed tty-send-algorithm
210 1 = Direct tty-send.
211 Bit 1: 0 = T.70 protocol (Only for BTX!) off
212 1 = T.70 protocol (Only for BTX!) on
213 Bit 2: 0 = Don't hangup on DTR low.
214 1 = Hangup on DTR low.
215 Bit 3: 0 = Standard response messages
216 1 = Extended response messages
217 Bit 4: 0 = CALLER NUMBER before every RING.
218 1 = CALLER NUMBER after first RING.
219 Bit 5: 0 = T.70 extended protocol off
220 1 = T.70 extended protocol on
221 Bit 6: 0 = Special RUNG Message off
222 1 = Special RUNG Message on
223 "RUNG" is delivered on a ttyI, if
224 an incoming call happened (RING) and
225 the remote party hung up before any
226 local ATA was given.
227 Bit 7: 0 = Don't show display messages from net
228 1 = Show display messages from net
229 (S12 Bit 1 must be 0 too)
230 14 0 Layer-2 protocol:
231 0 = X75/LAPB with I-frames
232 1 = X75/LAPB with UI-frames
233 2 = X75/LAPB with BUI-frames
234 3 = HDLC
235 4 = Transparent (audio)
236 7 = V.110, 9600 baud
237 8 = V.110, 19200 baud
238 9 = V.110, 38400 baud
239 10 = Analog Modem (only if hardware supports this)
240 11 = Fax G3 (only if hardware supports this)
241 15 0 Layer-3 protocol:
242 0 = transparent
243 1 = transparent with audio features (e.g. DSP)
244 2 = Fax G3 Class 2 commands (S14 has to be set to 11)
245 3 = Fax G3 Class 1 commands (S14 has to be set to 11)
246 16 250 Send-Packet-size/16
247 17 8 Window-size (not yet implemented)
248 18 4 Bit coded register, Service-Octet-1 to accept,
249 or to be used on dialout:
250 Bit 0: Service 1 (audio) when set.
251 Bit 1: Service 5 (BTX) when set.
252 Bit 2: Service 7 (data) when set.
253 Note: It is possible to set more than one
254 bit. In this case, on incoming calls
255 the selected services are accepted,
256 and if the service is "audio", the
257 Layer-2-protocol is automatically
258 changed to 4 regardless of the setting
259 of register 14. On outgoing calls,
260 the most significant 1-bit is chosen to
261 select the outgoing service octet.
262 19 0 Service-Octet-2
263 20 0 Bit coded register (readonly)
264 Service-Octet-1 of last call.
265 Bit mapping is the same as register 18
266 21 0 Bit coded register (readonly)
267 Set on incoming call (during RING) to
268 octet 3 of calling party number IE (Numbering plan)
269 See section 4.5.10 of ITU Q.931
270 22 0 Bit coded register (readonly)
271 Set on incoming call (during RING) to
272 octet 3a of calling party number IE (Screening info)
273 See section 4.5.10 of ITU Q.931
274 23 0 Bit coded register:
275 Bit 0: 0 = Add CPN to RING message off
276 1 = Add CPN to RING message on
277 Bit 1: 0 = Add CPN to FCON message off
278 1 = Add CPN to FCON message on
279 Bit 2: 0 = Add CDN to RING/FCON message off
280 1 = Add CDN to RING/FCON message on
281
282 Last but not least a (at the moment fairly primitive) device to request
283 the line-status (/dev/isdninfo) is made available.
284
285 Automatic assignment of devices to lines:
286
287 All inactive physical lines are listening to all EAZs for incoming
288 calls and are NOT assigned to a specific tty or network interface.
289 When an incoming call is detected, the driver looks first for a network
290 interface and then for an opened tty which:
291
292 1. is configured for the same EAZ.
293 2. has the same protocol settings for the B-channel.
294 3. (only for network interfaces if the security flag is set)
295 contains the caller number in its access list.
296 4. Either the channel is not bound exclusively to another Net-interface, or
297 it is bound AND the other checks apply to exactly this interface.
298 (For usage of the bind-features, refer to the isdnctrl-man-page)
299
300 Only when a matching interface or tty is found is the call accepted
301 and the "connection" between the low-level-layer and the link-level-layer
302 is established and kept until the end of the connection.
303 In all other cases no connection is established. Isdn4linux can be
304 configured to either do NOTHING in this case (which is useful, if
305 other, external devices with the same EAZ/MSN are connected to the bus)
306 or to reject the call actively. (isdnctrl busreject ...)
307
308 For an outgoing call, the inactive physical lines are searched.
309 The call is placed on the first physical line, which supports the
310 requested protocols for the B-channel. If a net-interface, however
311 is pre-bound to a channel, this channel is used directly.
312
313 This makes it possible to configure several network interfaces and ttys
314 for one EAZ, if the network interfaces are set to secure operation.
315 If an incoming call matches one network interface, it gets connected to it.
316 If another incoming call for the same EAZ arrives, which does not match
317 a network interface, the first tty gets a "RING" and so on.
318
3192 System prerequisites:
320
321 ATTENTION!
322
323 Always use the latest module utilities. The current version is
324 named in Documentation/Changes. Some old versions of insmod
325 are not capable of setting the driver-Ids correctly.
326
3273. Lowlevel-driver configuration.
328
329 Configuration depends on how the drivers are built. See the
330 README.<yourDriver> for information on driver-specific setup.
331
3324. Device-inodes
333
334 The major and minor numbers and their names are described in
335 Documentation/admin-guide/devices.rst. The major numbers are:
336
337 43 for the ISDN-tty's.
338 44 for the ISDN-callout-tty's.
339 45 for control/info/debug devices.
340
3415. Application
342
343 a) For some card-types, firmware has to be loaded into the cards, before
344 proceeding with device-independent setup. See README.<yourDriver>
345 for how to do that.
346
347 b) If you only intend to use ttys, you are nearly ready now.
348
349 c) If you want to have really permanent "Modem"-settings on disk, you
350 can start the daemon iprofd. Give it a path to a file at the command-
351 line. It will store the profile-settings in this file every time
352 an AT&W0 is performed on any ISDN-tty. If the file already exists,
353 all profiles are initialized from this file. If you want to unload
354 any of the modules, kill iprofd first.
355
356 d) For networking, continue: Create an interface:
357 isdnctrl addif isdn0
358
359 e) Set the EAZ (or MSN for Euro-ISDN):
360 isdnctrl eaz isdn0 2
361
362 (For 1TR6 a single digit is allowed, for Euro-ISDN the number is your
363 real MSN e.g.: Phone-Number)
364
365 f) Set the number for outgoing calls on the interface:
366 isdnctrl addphone isdn0 out 1234567
367 ... (this can be executed more than once, all assigned numbers are
368 tried in order)
369 and the number(s) for incoming calls:
370 isdnctrl addphone isdn0 in 1234567
371
372 g) Set the timeout for hang-up:
373 isdnctrl huptimeout isdn0 <timeout_in_seconds>
374
375 h) additionally you may activate charge-hang-up (= Hang up before
376 next charge-info, this only works, if your isdn-provider transmits
377 the charge-info during and after the connection):
378 isdnctrl chargehup isdn0 on
379
380 i) Set the dial mode of the interface:
381 isdnctrl dialmode isdn0 auto
382 "off" means that you (or the system) cannot make any connection
383 (neither incoming or outgoing connections are possible). Use
384 this if you want to be sure that no connections will be made.
385 "auto" means that the interface is in auto-dial mode, and will
386 attempt to make a connection whenever a network data packet needs
387 the interface's link. Note that this can cause unexpected dialouts,
388 and lead to a high phone bill! Some daemons or other pc's that use
389 this interface can cause this.
390 Incoming connections are also possible.
391 "manual" is a dial mode created to prevent the unexpected dialouts.
392 In this mode, the interface will never make any connections on its
393 own. You must explicitly initiate a connection with "isdnctrl dial
394 isdn0". However, after an idle time of no traffic as configured for
395 the huptimeout value with isdnctrl, the connection _will_ be ended.
396 If you don't want any automatic hangup, set the huptimeout value to 0.
397 "manual" is the default.
398
399 j) Setup the interface with ifconfig as usual, and set a route to it.
400
401 k) (optional) If you run X11 and have Tcl/Tk-wish version 4.0, you can use
402 the script tools/tcltk/isdnmon. You can add actions for line-status
403 changes. See the comments at the beginning of the script for how to
404 do that. There are other tty-based tools in the tools-subdirectory
405 contributed by Michael Knigge (imon), Volker Götz (imontty) and
406 Andreas Kool (isdnmon).
407
408 l) For initial testing, you can set the verbose-level to 2 (default: 0).
409 Then all incoming calls are logged, even if they are not addressed
410 to one of the configured net-interfaces:
411 isdnctrl verbose 2
412
413 Now you are ready! A ping to the set address should now result in an
414 automatic dial-out (look at syslog kernel-messages).
415 The phone numbers and EAZs can be assigned at any time with isdnctrl.
416 You can add as many interfaces as you like with addif following the
417 directions above. Of course, there may be some limitations. But we have
418 tested as many as 20 interfaces without any problem. However, if you
419 don't give an interface name to addif, the kernel will assign a name
420 which starts with "eth". The number of "eth"-interfaces is limited by
421 the kernel.
422
4235. Additional options for isdnctrl:
424
425 "isdnctrl secure <InterfaceName> on"
426 Only incoming calls, for which the caller-id is listed in the access
427 list of the interface are accepted. You can add caller-id's With the
428 command "isdnctrl addphone <InterfaceName> in <caller-id>"
429 Euro-ISDN does not transmit the leading '0' of the caller-id for an
430 incoming call, therefore you should configure it accordingly.
431 If the real number for the dialout e.g. is "09311234567" the number
432 to configure here is "9311234567". The pattern-match function
433 works similar to the shell mechanism.
434
435 ? one arbitrary digit
436 * zero or arbitrary many digits
437 [123] one of the digits in the list
438 [1-5] one digit between '1' and '5'
439 a '^' as the first character in a list inverts the list
440
441
442 "isdnctrl secure <InterfaceName> off"
443 Switch off secure operation (default).
444
445 "isdnctrl ihup <InterfaceName> [on|off]"
446 Switch the hang-up-timer for incoming calls on or off.
447
448 "isdnctrl eaz <InterfaceName>"
449 Returns the EAZ of an interface.
450
451 "isdnctrl delphone <InterfaceName> in|out <number>"
452 Deletes a number from one of the access-lists of the interface.
453
454 "isdnctrl delif <InterfaceName>"
455 Removes the interface (and possible slaves) from the kernel.
456 (You have to unregister it with "ifconfig <InterfaceName> down" before).
457
458 "isdnctrl callback <InterfaceName> [on|off]"
459 Switches an interface to callback-mode. In this mode, an incoming call
460 will be rejected and after this the remote-station will be called. If
461 you test this feature by using ping, some routers will re-dial very
462 quickly, so that the callback from isdn4linux may not be recognized.
463 In this case use ping with the option -i <sec> to increase the interval
464 between echo-packets.
465
466 "isdnctrl cbdelay <InterfaceName> [seconds]"
467 Sets the delay (default 5 sec) between an incoming call and start of
468 dialing when callback is enabled.
469
470 "isdnctrl cbhup <InterfaceName> [on|off]"
471 This enables (default) or disables an active hangup (reject) when getting an
472 incoming call for an interface which is configured for callback.
473
474 "isdnctrl encap <InterfaceName> <EncapType>"
475 Selects the type of packet-encapsulation. The encapsulation can be changed
476 only while an interface is down.
477
478 At the moment the following values are supported:
479
480 rawip (Default) Selects raw-IP-encapsulation. This means, MAC-headers
481 are stripped off.
482 ip IP with type-field. Same as IP but the type-field of the MAC-header
483 is preserved.
484 x25iface X.25 interface encapsulation (first byte semantics as defined in
485 ../networking/x25-iface.txt). Use this for running the linux
486 X.25 network protocol stack (AF_X25 sockets) on top of isdn.
487 cisco-h A special-mode for communicating with a Cisco, which is configured
488 to do "hdlc"
489 ethernet No stripping. Packets are sent with full MAC-header.
490 The Ethernet-address of the interface is faked, from its
491 IP-address: fc:fc:i1:i2:i3:i4, where i1-4 are the IP-addr.-values.
492 syncppp Synchronous PPP
493
494 uihdlc HDLC with UI-frame-header (for use with DOS ISPA, option -h1)
495
496
497 NOTE: x25iface encapsulation is currently experimental. Please
498 read README.x25 for further details
499
500
501 Watching packets, using standard-tcpdump will fail for all encapsulations
502 except ethernet because tcpdump does not know how to handle packets
503 without MAC-header. A patch for tcpdump is included in the utility-package
504 mentioned above.
505
506 "isdnctrl l2_prot <InterfaceName> <L2-ProtocolName>"
507 Selects a layer-2-protocol.
508 (With the ICN-driver and the HiSax-driver, "x75i" and "hdlc" is available.
509 With other drivers, "x75ui", "x75bui", "x25dte", "x25dce" may be
510 possible too. See README.x25 for x25 related l2 protocols.)
511
512 isdnctrl l3_prot <InterfaceName> <L3-ProtocolName>
513 The same for layer-3. (At the moment only "trans" is allowed)
514
515 "isdnctrl list <InterfaceName>"
516 Shows all parameters of an interface and the charge-info.
517 Try "all" as the interface name.
518
519 "isdnctrl hangup <InterfaceName>"
520 Forces hangup of an interface.
521
522 "isdnctrl bind <InterfaceName> <DriverId>,<ChannelNumber> [exclusive]"
523 If you are using more than one ISDN card, it is sometimes necessary to
524 dial out using a specific card or even preserve a specific channel for
525 dialout of a specific net-interface. This can be done with the above
526 command. Replace <DriverId> by whatever you assigned while loading the
527 module. The <ChannelNumber> is counted from zero. The upper limit
528 depends on the card used. At the moment no card supports more than
529 2 channels, so the upper limit is one.
530
531 "isdnctrl unbind <InterfaceName>"
532 unbinds a previously bound interface.
533
534 "isdnctrl busreject <DriverId> on|off"
535 If switched on, isdn4linux replies a REJECT to incoming calls, it
536 cannot match to any configured interface.
537 If switched off, nothing happens in this case.
538 You normally should NOT enable this feature, if the ISDN adapter is not
539 the only device connected to the S0-bus. Otherwise it could happen that
540 isdn4linux rejects an incoming call, which belongs to another device on
541 the bus.
542
543 "isdnctrl addslave <InterfaceName> <SlaveName>
544 Creates a slave interface for channel-bundling. Slave interfaces are
545 not seen by the kernel, but their ISDN-part can be configured with
546 isdnctrl as usual. (Phone numbers, EAZ/MSN, timeouts etc.) If more
547 than two channels are to be bundled, feel free to create as many as you
548 want. InterfaceName must be a real interface, NOT a slave. Slave interfaces
549 start dialing, if the master interface resp. the previous slave interface
550 has a load of more than 7000 cps. They hangup if the load goes under 7000
551 cps, according to their "huptimeout"-parameter.
552
553 "isdnctrl sdelay <InterfaceName> secs."
554 This sets the minimum time an Interface has to be fully loaded, until
555 it sends a dial-request to its slave.
556
557 "isdnctrl dial <InterfaceName>"
558 Forces an interface to start dialing even if no packets are to be
559 transferred.
560
561 "isdnctrl mapping <DriverId> MSN0,MSN1,MSN2,...MSN9"
562 This installs a mapping table for EAZ<->MSN-mapping for a single line.
563 Missing MSN's have to be given as "-" or can be omitted, if at the end
564 of the commandline.
565 With this command, it's now possible to have an interface listening to
566 mixed 1TR6- and Euro-Type lines. In this case, the interface has to be
567 configured to a 1TR6-type EAZ (one digit). The mapping is also valid
568 for tty-emulation. Seen from the interface/tty-level the mapping
569 CAN be used, however it's possible to use single tty's/interfaces with
570 real MSN's (more digits) also, in which case the mapping will be ignored.
571 Here is an example:
572
573 You have a 1TR6-type line with base-nr. 1234567 and a Euro-line with
574 MSN's 987654, 987655 and 987656. The DriverId for the Euro-line is "EURO".
575
576 isdnctrl mapping EURO -,987654,987655,987656,-,987655
577 ...
578 isdnctrl eaz isdn0 1 # listen on 12345671(1tr6) and 987654(euro)
579 ...
580 isdnctrl eaz isdn1 4 # listen on 12345674(1tr6) only.
581 ...
582 isdnctrl eaz isdn2 987654 # listen on 987654(euro) only.
583
584 Same scheme is used with AT&E... at the tty's.
585
5866. If you want to write a new low-level-driver, you are welcome.
587 The interface to the link-level-module is described in the file INTERFACE.
588 If the interface should be expanded for any reason, don't do it
589 on your own, send me a mail containing the proposed changes and
590 some reasoning about them.
591 If other drivers will not be affected, I will include the changes
592 in the next release.
593 For developers only, there is a second mailing-list. Write to me
594 (fritz@isdn4linux.de), if you want to join that list.
595
596Have fun!
597
598 -Fritz
599
diff --git a/Documentation/isdn/README.FAQ b/Documentation/isdn/README.FAQ
deleted file mode 100644
index e5dd1addacdd..000000000000
--- a/Documentation/isdn/README.FAQ
+++ /dev/null
@@ -1,26 +0,0 @@
1
2The FAQ for isdn4linux
3======================
4
5Please note that there is a big FAQ available in the isdn4k-utils.
6You find it in:
7 isdn4k-utils/FAQ/i4lfaq.sgml
8
9In case you just want to see the FAQ online, or download the newest version,
10you can have a look at my website:
11https://www.mhessler.de/i4lfaq/ (view + download)
12or:
13https://www.isdn4linux.de/faq/4lfaq.html (view)
14
15As the extension tells, the FAQ is in SGML format, and you can convert it
16into text/html/... format by using the sgml2txt/sgml2html/... tools.
17Alternatively, you can also do a 'configure; make all' in the FAQ directory.
18
19
20Please have a look at the FAQ before posting anything in the Mailinglist,
21or the newsgroup!
22
23
24Matthias Hessler
25hessler@isdn4linux.de
26
diff --git a/Documentation/isdn/README.audio b/Documentation/isdn/README.audio
deleted file mode 100644
index 8ebca19290d9..000000000000
--- a/Documentation/isdn/README.audio
+++ /dev/null
@@ -1,138 +0,0 @@
1$Id: README.audio,v 1.8 1999/07/11 17:17:29 armin Exp $
2
3ISDN subsystem for Linux.
4 Description of audio mode.
5
6When enabled during kernel configuration, the tty emulator of the ISDN
7subsystem is capable of a reduced set of commands to support audio.
8This document describes the commands supported and the format of
9audio data.
10
11Commands for enabling/disabling audio mode:
12
13 AT+FCLASS=8 Enable audio mode.
14 This affects the following registers:
15 S18: Bits 0 and 2 are set.
16 S16: Set to 48 and any further change to
17 larger values is blocked.
18 AT+FCLASS=0 Disable audio mode.
19 Register 18 is set to 4.
20 AT+FCLASS=? Show possible modes.
21 AT+FCLASS? Report current mode (0 or 8).
22
23Commands supported in audio mode:
24
25All audio mode commands have one of the following forms:
26
27 AT+Vxx? Show current setting.
28 AT+Vxx=? Show possible settings.
29 AT+Vxx=v Set simple parameter.
30 AT+Vxx=v,v ... Set complex parameter.
31
32where xx is a two-character code and v are alphanumerical parameters.
33The following commands are supported:
34
35 AT+VNH=x Auto hangup setting. NO EFFECT, supported
36 for compatibility only.
37 AT+VNH? Always reporting "1"
38 AT+VNH=? Always reporting "1"
39
40 AT+VIP Reset all audio parameters.
41
42 AT+VLS=x Line select. x is one of the following:
43 0 = No device.
44 2 = Phone line.
45 AT+VLS=? Always reporting "0,2"
46 AT+VLS? Show current line.
47
48 AT+VRX Start recording. Emulator responds with
49 CONNECT and starts sending audio data to
50 the application. See below for data format
51
52 AT+VSD=x,y Set silence-detection parameters.
53 Possible parameters:
54 x = 0 ... 31 sensitivity threshold level.
55 (default 0 , deactivated)
56 y = 0 ... 255 range of interval in units
57 of 0.1 second. (default 70)
58 AT+VSD=? Report possible parameters.
59 AT+VSD? Show current parameters.
60
61 AT+VDD=x,y Set DTMF-detection parameters.
62 Only possible if online and during this connection.
63 Possible parameters:
64 x = 0 ... 15 sensitivity threshold level.
65 (default 0 , I4L soft-decode)
66 (1-15 soft-decode off, hardware on)
67 y = 0 ... 255 tone duration in units of 5ms.
68 Not for I4L soft decode (default 8, 40ms)
69 AT+VDD=? Report possible parameters.
70 AT+VDD? Show current parameters.
71
72 AT+VSM=x Select audio data format.
73 Possible parameters:
74 2 = ADPCM-2
75 3 = ADPCM-3
76 4 = ADPCM-4
77 5 = aLAW
78 6 = uLAW
79 AT+VSM=? Show possible audio formats.
80
81 AT+VTX Start audio playback. Emulator responds
82 with CONNECT and starts sending audio data
83 received from the application via phone line.
84General behavior and description of data formats/protocol.
85 when a connection is made:
86
87 On incoming calls, if the application responds to a RING
88 with ATA, depending on the calling service, the emulator
89 responds with either CONNECT (data call) or VCON (voice call).
90
91 On outgoing voice calls, the emulator responds with VCON
92 upon connection setup.
93
94 Audio recording.
95
96 When receiving audio data, a kind of bisync protocol is used.
97 Upon AT+VRX command, the emulator responds with CONNECT, and
98 starts sending audio data to the application. There are several
99 escape sequences defined, all using DLE (0x10) as Escape char:
100
101 <DLE><ETX> End of audio data. (i.e. caused by a
102 hangup of the remote side) Emulator stops
103 recording, responding with VCON.
104 <DLE><DC4> Abort recording, (send by appl.) Emulator
105 stops recording, sends DLE,ETX.
106 <DLE><DLE> Escape sequence for DLE in data stream.
107 <DLE>0 Touchtone "0" received.
108 ...
109 <DLE>9 Touchtone "9" received.
110 <DLE># Touchtone "#" received.
111 <DLE>* Touchtone "*" received.
112 <DLE>A Touchtone "A" received.
113 <DLE>B Touchtone "B" received.
114 <DLE>C Touchtone "C" received.
115 <DLE>D Touchtone "D" received.
116
117 <DLE>q quiet. Silence detected after non-silence.
118 <DLE>s silence. Silence detected from the
119 start of recording.
120
121 Currently unsupported DLE sequences:
122
123 <DLE>c FAX calling tone received.
124 <DLE>b busy tone received.
125
126 Audio playback.
127
128 When sending audio data, upon AT+VTX command, emulator responds with
129 CONNECT, and starts transferring data from application to the phone line.
130 The same DLE sequences apply to this mode.
131
132 Full-Duplex-Audio:
133
134 When _both_ commands for recording and playback are given in _one_
135 AT-command-line (i.e.: "AT+VTX+VRX"), full-duplex-mode is selected.
136 In this mode, the only way to stop recording is sending <DLE><DC4>
137 and the only way to stop playback is to send <DLE><ETX>.
138
diff --git a/Documentation/isdn/README.concap b/Documentation/isdn/README.concap
deleted file mode 100644
index a76d74845a4c..000000000000
--- a/Documentation/isdn/README.concap
+++ /dev/null
@@ -1,259 +0,0 @@
1Description of the "concap" encapsulation protocol interface
2============================================================
3
4The "concap" interface is intended to be used by network device
5drivers that need to process an encapsulation protocol.
6It is assumed that the protocol interacts with a linux network device by
7- data transmission
8- connection control (establish, release)
9Thus, the mnemonic: "CONnection CONtrolling eNCAPsulation Protocol".
10
11This is currently only used inside the isdn subsystem. But it might
12also be useful to other kinds of network devices. Thus, if you want
13to suggest changes that improve usability or performance of the
14interface, please let me know. I'm willing to include them in future
15releases (even if I needed to adapt the current isdn code to the
16changed interface).
17
18
19Why is this useful?
20===================
21
22The encapsulation protocol used on top of WAN connections or permanent
23point-to-point links are frequently chosen upon bilateral agreement.
24Thus, a device driver for a certain type of hardware must support
25several different encapsulation protocols at once.
26
27The isdn device driver did already support several different
28encapsulation protocols. The encapsulation protocol is configured by a
29user space utility (isdnctrl). The isdn network interface code then
30uses several case statements which select appropriate actions
31depending on the currently configured encapsulation protocol.
32
33In contrast, LAN network interfaces always used a single encapsulation
34protocol which is unique to the hardware type of the interface. The LAN
35encapsulation is usually done by just sticking a header on the data. Thus,
36traditional linux network device drivers used to process the
37encapsulation protocol directly (usually by just providing a hard_header()
38method in the device structure) using some hardware type specific support
39functions. This is simple, direct and efficient. But it doesn't fit all
40the requirements for complex WAN encapsulations.
41
42
43 The configurability of the encapsulation protocol to be used
44 makes isdn network interfaces more flexible, but also much more
45 complex than traditional lan network interfaces.
46
47
48Many Encapsulation protocols used on top of WAN connections will not just
49stick a header on the data. They also might need to set up or release
50the WAN connection. They also might want to send other data for their
51private purpose over the wire, e.g. ppp does a lot of link level
52negotiation before the first piece of user data can be transmitted.
53Such encapsulation protocols for WAN devices are typically more complex
54than encapsulation protocols for lan devices. Thus, network interface
55code for typical WAN devices also tends to be more complex.
56
57
58In order to support Linux' x25 PLP implementation on top of
59isdn network interfaces I could have introduced yet another branch to
60the various case statements inside drivers/isdn/isdn_net.c.
61This eventually made isdn_net.c even more complex. In addition, it made
62isdn_net.c harder to maintain. Thus, by identifying an abstract
63interface between the network interface code and the encapsulation
64protocol, complexity could be reduced and maintainability could be
65increased.
66
67
68Likewise, a similar encapsulation protocol will frequently be needed by
69several different interfaces of even different hardware type, e.g. the
70synchronous ppp implementation used by the isdn driver and the
71asynchronous ppp implementation used by the ppp driver have a lot of
72similar code in them. By cleanly separating the encapsulation protocol
73from the hardware specific interface stuff such code could be shared
74better in future.
75
76
77When operating over dial-up-connections (e.g. telephone lines via modem,
78non-permanent virtual circuits of wide area networks, ISDN) many
79encapsulation protocols will need to control the connection. Therefore,
80some basic connection control primitives are supported. The type and
81semantics of the connection (i.e the ISO layer where connection service
82is provided) is outside our scope and might be different depending on
83the encapsulation protocol used, e.g. for a ppp module using our service
84on top of a modem connection a connect_request will result in dialing
85a (somewhere else configured) remote phone number. For an X25-interface
86module (LAPB semantics, as defined in Documentation/networking/x25-iface.txt)
87a connect_request will ask for establishing a reliable lapb
88datalink connection.
89
90
91The encapsulation protocol currently provides the following
92service primitives to the network device.
93
94- create a new encapsulation protocol instance
95- delete encapsulation protocol instance and free all its resources
96- initialize (open) the encapsulation protocol instance for use.
97- deactivate (close) an encapsulation protocol instance.
98- process (xmit) data handed down by upper protocol layer
99- receive data from lower (hardware) layer
100- process connect indication from lower (hardware) layer
101- process disconnect indication from lower (hardware) layer
102
103
104The network interface driver accesses those primitives via callbacks
105provided by the encapsulation protocol instance within a
106struct concap_proto_ops.
107
108struct concap_proto_ops{
109
110 /* create a new encapsulation protocol instance of same type */
111 struct concap_proto * (*proto_new) (void);
112
113 /* delete encapsulation protocol instance and free all its resources.
114 cprot may no longer be referenced after calling this */
115 void (*proto_del)(struct concap_proto *cprot);
116
117 /* initialize the protocol's data. To be called at interface startup
118 or when the device driver resets the interface. All services of the
119 encapsulation protocol may be used after this*/
120 int (*restart)(struct concap_proto *cprot,
121 struct net_device *ndev,
122 struct concap_device_ops *dops);
123
124 /* deactivate an encapsulation protocol instance. The encapsulation
125 protocol may not call any *dops methods after this. */
126 int (*close)(struct concap_proto *cprot);
127
128 /* process a frame handed down to us by upper layer */
129 int (*encap_and_xmit)(struct concap_proto *cprot, struct sk_buff *skb);
130
131 /* to be called for each data entity received from lower layer*/
132 int (*data_ind)(struct concap_proto *cprot, struct sk_buff *skb);
133
134 /* to be called when a connection was set up/down.
135 Protocols that don't process these primitives might fill in
136 dummy methods here */
137 int (*connect_ind)(struct concap_proto *cprot);
138 int (*disconn_ind)(struct concap_proto *cprot);
139};
140
141
142The data structures are defined in the header file include/linux/concap.h.
143
144
145A Network interface using encapsulation protocols must also provide
146some service primitives to the encapsulation protocol:
147
148- request data being submitted by lower layer (device hardware)
149- request a connection being set up by lower layer
150- request a connection being released by lower layer
151
152The encapsulation protocol accesses those primitives via callbacks
153provided by the network interface within a struct concap_device_ops.
154
155struct concap_device_ops{
156
157 /* to request data be submitted by device */
158 int (*data_req)(struct concap_proto *, struct sk_buff *);
159
160 /* Control methods must be set to NULL by devices which do not
161 support connection control. */
162 /* to request a connection be set up */
163 int (*connect_req)(struct concap_proto *);
164
165 /* to request a connection be released */
166 int (*disconn_req)(struct concap_proto *);
167};
168
169The network interface does not explicitly provide a receive service
170because the encapsulation protocol directly calls netif_rx().
171
172
173
174
175An encapsulation protocol itself is actually the
176struct concap_proto{
177 struct net_device *net_dev; /* net device using our service */
178 struct concap_device_ops *dops; /* callbacks provided by device */
179 struct concap_proto_ops *pops; /* callbacks provided by us */
180 int flags;
181 void *proto_data; /* protocol specific private data, to
182 be accessed via *pops methods only*/
183 /*
184 :
185 whatever
186 :
187 */
188};
189
190Most of this is filled in when the device requests the protocol to
191be reset (opend). The network interface must provide the net_dev and
192dops pointers. Other concap_proto members should be considered private
193data that are only accessed by the pops callback functions. Likewise,
194a concap proto should access the network device's private data
195only by means of the callbacks referred to by the dops pointer.
196
197
198A possible extended device structure which uses the connection controlling
199encapsulation services could look like this:
200
201struct concap_device{
202 struct net_device net_dev;
203 struct my_priv /* device->local stuff */
204 /* the my_priv struct might contain a
205 struct concap_device_ops *dops;
206 to provide the device specific callbacks
207 */
208 struct concap_proto *cprot; /* callbacks provided by protocol */
209};
210
211
212
213Misc Thoughts
214=============
215
216The concept of the concap proto might help to reuse protocol code and
217reduce the complexity of certain network interface implementations.
218The trade off is that it introduces yet another procedure call layer
219when processing the protocol. This has of course some impact on
220performance. However, typically the concap interface will be used by
221devices attached to slow lines (like telephone, isdn, leased synchronous
222lines). For such slow lines, the overhead is probably negligible.
223This might no longer hold for certain high speed WAN links (like
224ATM).
225
226
227If general linux network interfaces explicitly supported concap
228protocols (e.g. by a member struct concap_proto* in struct net_device)
229then the interface of the service function could be changed
230by passing a pointer of type (struct net_device*) instead of
231type (struct concap_proto*). Doing so would make many of the service
232functions compatible to network device support functions.
233
234e.g. instead of the concap protocol's service function
235
236 int (*encap_and_xmit)(struct concap_proto *cprot, struct sk_buff *skb);
237
238we could have
239
240 int (*encap_and_xmit)(struct net_device *ndev, struct sk_buff *skb);
241
242As this is compatible to the dev->hard_start_xmit() method, the device
243driver could directly register the concap protocol's encap_and_xmit()
244function as its hard_start_xmit() method. This would eliminate one
245procedure call layer.
246
247
248The device's data request function could also be defined as
249
250 int (*data_req)(struct net_device *ndev, struct sk_buff *skb);
251
252This might even allow for some protocol stacking. And the network
253interface might even register the same data_req() function directly
254as its hard_start_xmit() method when a zero layer encapsulation
255protocol is configured. Thus, eliminating the performance penalty
256of the concap interface when a trivial concap protocol is used.
257Nevertheless, the device remains able to support encapsulation
258protocol configuration.
259
diff --git a/Documentation/isdn/README.diversion b/Documentation/isdn/README.diversion
deleted file mode 100644
index bddcd5fb86ff..000000000000
--- a/Documentation/isdn/README.diversion
+++ /dev/null
@@ -1,127 +0,0 @@
1The isdn diversion services are a supporting module working together with
2the isdn4linux and the HiSax module for passive cards.
3Active cards, TAs and cards using a own or other driver than the HiSax
4module need to be adapted to the HL<->LL interface described in a separate
5document. The diversion services may be used with all cards supported by
6the HiSax driver.
7The diversion kernel interface and controlling tool divertctrl were written
8by Werner Cornelius (werner@isdn4linux.de or werner@titro.de) under the
9GNU General Public License.
10
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24
25Table of contents
26=================
27
281. Features of the i4l diversion services
29 (Or what can the i4l diversion services do for me)
30
312. Required hard- and software
32
333. Compiling, installing and loading/unloading the module
34 Tracing calling and diversion information
35
364. Tracing calling and diversion information
37
385. Format of the divert device ASCII output
39
40
411. Features of the i4l diversion services
42 (Or what can the i4l diversion services do for me)
43
44 The i4l diversion services offers call forwarding and logging normally
45 only supported by isdn phones. Incoming calls may be diverted
46 unconditionally (CFU), when not reachable (CFNR) or on busy condition
47 (CFB).
48 The diversions may be invoked statically in the providers exchange
49 as normally done by isdn phones. In this case all incoming calls
50 with a special (or all) service identifiers are forwarded if the
51 forwarding reason is met. Activated static services may also be
52 interrogated (queried).
53 The i4l diversion services additionally offers a dynamic version of
54 call forwarding which is not preprogrammed inside the providers exchange
55 but dynamically activated by i4l.
56 In this case all incoming calls are checked by rules that may be
57 compared to the mechanism of ipfwadm or ipchains. If a given rule matches
58 the checking process is finished and the rule matching will be applied
59 to the call.
60 The rules include primary and secondary service identifiers, called
61 number and subaddress, callers number and subaddress and whether the rule
62 matches to all filtered calls or only those when all B-channel resources
63 are exhausted.
64 Actions that may be invoked by a rule are ignore, proceed, reject,
65 direct divert or delayed divert of a call.
66 All incoming calls matching a rule except the ignore rule a reported and
67 logged as ASCII via the proc filesystem (/proc/net/isdn/divert). If proceed
68 is selected the call will be held in a proceeding state (without ringing)
69 for a certain amount of time to let an external program or client decide
70 how to handle the call.
71
72
732. Required hard- and software
74
75 For using the i4l diversion services the isdn line must be of a EURO/DSS1
76 type. Additionally the i4l services only work together with the HiSax
77 driver for passive isdn cards. All HiSax supported cards may be used for
78 the diversion purposes.
79 The static diversion services require the provider having static services
80 CFU, CFNR, CFB activated on an MSN-line. The static services may not be
81 used on a point-to-point connection. Further the static services are only
82 available in some countries (for example germany). Countries requiring the
83 keypad protocol for activating static diversions (like the netherlands) are
84 not supported but may use the tty devices for this purpose.
85 The dynamic diversion services may be used in all countries if the provider
86 enables the feature CF (call forwarding). This should work on both MSN- and
87 point-to-point lines.
88 To add and delete rules the additional divertctrl program is needed. This
89 program is part of the isdn4kutils package.
90
913. Compiling, installing and loading/unloading the module
92 Tracing calling and diversion information
93
94
95 To compile the i4l code with diversion support you need to say yes to the
96 DSS1 diversion services when selecting the i4l options in the kernel
97 config (menuconfig or config).
98 After having properly activated a make modules and make modules_install all
99 required modules will be correctly installed in the needed modules dirs.
100 As the diversion services are currently not included in the scripts of most
101 standard distributions you will have to add a "insmod dss1_divert" after
102 having loaded the global isdn module.
103 The module can be loaded without any command line parameters.
104 If the module is actually loaded and active may be checked with a
105 "cat /proc/modules" or "ls /proc/net/isdn/divert". The divert file is
106 dynamically created by the diversion module and removed when the module is
107 unloaded.
108
109
1104. Tracing calling and diversion information
111
112 You also may put a "cat /proc/net/isdn/divert" in the background with the
113 output redirected to a file. Then all actions of the module are logged.
114 The divert file in the proc system may be opened more than once, so in
115 conjunction with inetd and a small remote client on other machines inside
116 your network incoming calls and reactions by the module may be shown on
117 every listening machine.
118 If a call is reported as proceeding an external program or client may
119 specify during a certain amount of time (normally 4 to 10 seconds) what
120 to do with that call.
121 To unload the module all open files to the device in the proc system must
122 be closed. Otherwise the module (and isdn.o) may not be unloaded.
123
1245. Format of the divert device ASCII output
125
126 To be done later
127
diff --git a/Documentation/isdn/README.fax b/Documentation/isdn/README.fax
deleted file mode 100644
index 5314958a8a6e..000000000000
--- a/Documentation/isdn/README.fax
+++ /dev/null
@@ -1,45 +0,0 @@
1
2Fax with isdn4linux
3===================
4
5When enabled during kernel configuration, the tty emulator
6of the ISDN subsystem is capable of the Fax Class 2 commands.
7
8This only makes sense under the following conditions :
9
10- You need the commands as dummy, because you are using
11 hylafax (with patch) for AVM capi.
12- You want to use the fax capabilities of your isdn-card.
13 (supported cards are listed below)
14
15
16NOTE: This implementation does *not* support fax with passive
17 ISDN-cards (known as softfax). The low-level driver of
18 the ISDN-card and/or the card itself must support this.
19
20
21Supported ISDN-Cards
22--------------------
23
24Eicon DIVA Server BRI/PCI
25 - full support with both B-channels.
26
27Eicon DIVA Server 4BRI/PCI
28 - full support with all B-channels.
29
30Eicon DIVA Server PRI/PCI
31 - full support on amount of B-channels
32 depending on DSPs on board.
33
34
35
36The command set is known as Class 2 (not Class 2.0) and
37can be activated by AT+FCLASS=2
38
39
40The interface between the link-level-module and the hardware-level driver
41is described in the files INTERFACE.fax and INTERFACE.
42
43Armin
44mac@melware.de
45
diff --git a/Documentation/isdn/README.hfc-pci b/Documentation/isdn/README.hfc-pci
deleted file mode 100644
index e8a4ef0226e8..000000000000
--- a/Documentation/isdn/README.hfc-pci
+++ /dev/null
@@ -1,41 +0,0 @@
1The driver for the HFC-PCI and HFC-PCI-A chips from CCD may be used
2for many OEM cards using this chips.
3Additionally the driver has a special feature which makes it possible
4to read the echo-channel of the isdn bus. So all frames in both directions
5may be logged.
6When the echo logging feature is used the number of available B-channels
7for a HFC-PCI card is reduced to 1. Of course this is only relevant to
8the card, not to the isdn line.
9To activate the echo mode the following ioctls must be entered:
10
11hisaxctrl <driver/cardname> 10 1
12
13This reduces the available channels to 1. There must not be open connections
14through this card when entering the command.
15And then:
16
17hisaxctrl <driver/cardname> 12 1
18
19This enables the echo mode. If Hex logging is activated the isdnctrlx
20devices show a output with a line beginning of HEX: for the providers
21exchange and ECHO: for isdn devices sending to the provider.
22
23If more than one HFC-PCI cards are installed, a specific card may be selected
24at the hisax module load command line. Supply the load command with the desired
25IO-address of the desired card.
26Example:
27There tree cards installed in your machine at IO-base addresses 0xd000, 0xd400
28and 0xdc00
29If you want to use the card at 0xd400 standalone you should supply the insmod
30or depmod with type=35 io=0xd400.
31If you want to use all three cards, but the order needs to be at 0xdc00,0xd400,
320xd000 you may give the parameters type=35,35,35 io=0xdc00,0xd400,0xd00
33Then the desired card will be the initialised in the desired order.
34If the io parameter is used the io addresses of all used cards should be
35supplied else the parameter is assumed 0 and a auto search for a free card is
36invoked which may not give the wanted result.
37
38Comments and reports to werner@isdn4linux.de or werner@isdn-development.de
39
40
41
diff --git a/Documentation/isdn/README.syncppp b/Documentation/isdn/README.syncppp
deleted file mode 100644
index 27d260095cce..000000000000
--- a/Documentation/isdn/README.syncppp
+++ /dev/null
@@ -1,58 +0,0 @@
1Some additional information for setting up a syncPPP
2connection using network interfaces.
3---------------------------------------------------------------
4
5You need one thing beside the isdn4linux package:
6
7 a patched pppd .. (I called it ipppd to show the difference)
8
9Compiling isdn4linux with sync PPP:
10-----------------------------------
11To compile isdn4linux with the sync PPP part, you have
12to answer the appropriate question when doing a "make config"
13Don't forget to load the slhc.o
14module before the isdn.o module, if VJ-compression support
15is not compiled into your kernel. (e.g if you have no PPP or
16CSLIP in the kernel)
17
18Using isdn4linux with sync PPP:
19-------------------------------
20Sync PPP is just another encapsulation for isdn4linux. The
21name to enable sync PPP encapsulation is 'syncppp' .. e.g:
22
23 /sbin/isdnctrl encap ippp0 syncppp
24
25The name of the interface is here 'ippp0'. You need
26one interface with the name 'ippp0' to saturate the
27ipppd, which checks the ppp version via this interface.
28Currently, all devices must have the name ipppX where
29'X' is a decimal value.
30
31To set up a PPP connection you need the ipppd .. You must start
32the ipppd once after installing the modules. The ipppd
33communicates with the isdn4linux link-level driver using the
34/dev/ippp0 to /dev/ippp15 devices. One ipppd can handle
35all devices at once. If you want to use two PPP connections
36at the same time, you have to connect the ipppd to two
37devices .. and so on.
38I've implemented one additional option for the ipppd:
39 'useifip' will get (if set to not 0.0.0.0) the IP address
40 for the negotiation from the attached network-interface.
41(also: ipppd will try to negotiate pointopoint IP as remote IP)
42You must disable BSD-compression, this implementation can't
43handle compressed packets.
44
45Check the etc/rc.isdn.syncppp in the isdn4kernel-util package
46for an example setup script.
47
48To use the MPPP stuff, you must configure a slave device
49with isdn4linux. Now call the ipppd with the '+mp' option.
50To increase the number of links, you must use the
51'addlink' option of the isdnctrl tool. (rc.isdn.syncppp.MPPP is
52an example script)
53
54enjoy it,
55 michael
56
57
58
diff --git a/Documentation/isdn/README.x25 b/Documentation/isdn/README.x25
deleted file mode 100644
index e561a77c4e22..000000000000
--- a/Documentation/isdn/README.x25
+++ /dev/null
@@ -1,184 +0,0 @@
1
2X.25 support within isdn4linux
3==============================
4
5This is alpha/beta test code. Use it completely at your own risk.
6As new versions appear, the stuff described here might suddenly change
7or become invalid without notice.
8
9Keep in mind:
10
11You are using several new parts of the 2.2.x kernel series which
12have not been tested in a large scale. Therefore, you might encounter
13more bugs as usual.
14
15- If you connect to an X.25 neighbour not operated by yourself, ASK the
16 other side first. Be prepared that bugs in the protocol implementation
17 might result in problems.
18
19- This implementation has never wiped out my whole hard disk yet. But as
20 this is experimental code, don't blame me if that happened to you.
21 Backing up important data will never harm.
22
23- Monitor your isdn connections while using this software. This should
24 prevent you from undesired phone bills in case of driver problems.
25
26
27
28
29How to configure the kernel
30===========================
31
32The ITU-T (former CCITT) X.25 network protocol layer has been implemented
33in the Linux source tree since version 2.1.16. The isdn subsystem might be
34useful to run X.25 on top of ISDN. If you want to try it, select
35
36 "CCITT X.25 Packet Layer"
37
38from the networking options as well as
39
40 "ISDN Support" and "X.25 PLP on Top of ISDN"
41
42from the ISDN subsystem options when you configure your kernel for
43compilation. You currently also need to enable
44"Prompt for development and/or incomplete code/drivers" from the
45"Code maturity level options" menu. For the x25trace utility to work
46you also need to enable "Packet socket".
47
48For local testing it is also recommended to enable the isdnloop driver
49from the isdn subsystem's configuration menu.
50
51For testing, it is recommended that all isdn drivers and the X.25 PLP
52protocol are compiled as loadable modules. Like this, you can recover
53from certain errors by simply unloading and reloading the modules.
54
55
56
57What's it for? How to use it?
58=============================
59
60X.25 on top of isdn might be useful with two different scenarios:
61
62- You might want to access a public X.25 data network from your Linux box.
63 You can use i4l if you were physically connected to the X.25 switch
64 by an ISDN B-channel (leased line as well as dial up connection should
65 work).
66
67 This corresponds to ITU-T recommendation X.31 Case A (circuit-mode
68 access to PSPDN [packet switched public data network]).
69
70 NOTE: X.31 also covers a Case B (access to PSPDN via virtual
71 circuit / packet mode service). The latter mode (which in theory
72 also allows using the D-channel) is not supported by isdn4linux.
73 It should however be possible to establish such packet mode connections
74 with certain active isdn cards provided that the firmware supports X.31
75 and the driver exports this functionality to the user. Currently,
76 the AVM B1 driver is the only driver which does so. (It should be
77 possible to access D-channel X.31 with active AVM cards using the
78 CAPI interface of the AVM-B1 driver).
79
80- Or you might want to operate certain ISDN teleservices on your linux
81 box. A lot of those teleservices run on top of the ISO-8208
82 (DTE-DTE mode) network layer protocol. ISO-8208 is essentially the
83 same as ITU-T X.25.
84
85 Popular candidates of such teleservices are EUROfile transfer or any
86 teleservice applying ITU-T recommendation T.90.
87
88To use the X.25 protocol on top of isdn, just create an isdn network
89interface as usual, configure your own and/or peer's ISDN numbers,
90and choose x25iface encapsulation by
91
92 isdnctrl encap <iface-name> x25iface.
93
94Once encap is set like this, the device can be used by the X.25 packet layer.
95
96All the stuff needed for X.25 is implemented inside the isdn link
97level (mainly isdn_net.c and some new source files). Thus, it should
98work with every existing HL driver. I was able to successfully open X.25
99connections on top of the isdnloop driver and the hisax driver.
100"x25iface"-encapsulation bypasses demand dialing. Dialing will be
101initiated when the upper (X.25 packet) layer requests the lapb datalink to
102be established. But hangup timeout is still active. Whenever a hangup
103occurs, all existing X.25 connections on that link will be cleared
104It is recommended to use sufficiently large hangup-timeouts for the
105isdn interfaces.
106
107
108In order to set up a conforming protocol stack you also need to
109specify the proper l2_prot parameter:
110
111To operate in ISO-8208 X.25 DTE-DTE mode, use
112
113 isdnctrl l2_prot <iface-name> x75i
114
115To access an X.25 network switch via isdn (your linux box is the DTE), use
116
117 isdnctrl l2_prot <iface-name> x25dte
118
119To mimic an X.25 network switch (DCE side of the connection), use
120
121 isdnctrl l2_prot <iface-name> x25dce
122
123However, x25dte or x25dce is currently not supported by any real HL
124level driver. The main difference between x75i and x25dte/dce is that
125x25d[tc]e uses fixed lap_b addresses. With x75i, the side which
126initiates the isdn connection uses the DTE's lap_b address while the
127called side used the DCE's lap_b address. Thus, l2_prot x75i might
128probably work if you access a public X.25 network as long as the
129corresponding isdn connection is set up by you. At least one test
130was successful to connect via isdn4linux to an X.25 switch using this
131trick. At the switch side, a terminal adapter X.21 was used to connect
132it to the isdn.
133
134
135How to set up a test installation?
136==================================
137
138To test X.25 on top of isdn, you need to get
139
140- a recent version of the "isdnctrl" program that supports setting the new
141 X.25 specific parameters.
142
143- the x25-utils-2.X package from
144 ftp://ftp.hes.iki.fi/pub/ham/linux/ax25/x25utils-*
145 (don't confuse the x25-utils with the ax25-utils)
146
147- an application program that uses linux PF_X25 sockets (some are
148 contained in the x25-util package).
149
150Before compiling the user level utilities make sure that the compiler/
151preprocessor will fetch the proper kernel header files of this kernel
152source tree. Either make /usr/include/linux a symbolic link pointing to
153this kernel's include/linux directory or set the appropriate compiler flags.
154
155When all drivers and interfaces are loaded and configured you need to
156ifconfig the network interfaces up and add X.25-routes to them. Use
157the usual ifconfig tool.
158
159ifconfig <iface-name> up
160
161But a special x25route tool (distributed with the x25-util package)
162is needed to set up X.25 routes. I.e.
163
164x25route add 01 <iface-name>
165
166will cause all x.25 connections to the destination X.25-address
167"01" to be routed to your created isdn network interface.
168
169There are currently no real X.25 applications available. However, for
170tests, the x25-utils package contains a modified version of telnet
171and telnetd that uses X.25 sockets instead of tcp/ip sockets. You can
172use those for your first tests. Furthermore, you might check
173ftp://ftp.hamburg.pop.de/pub/LOCAL/linux/i4l-eft/ which contains some
174alpha-test implementation ("eftp4linux") of the EUROfile transfer
175protocol.
176
177The scripts distributed with the eftp4linux test releases might also
178provide useful examples for setting up X.25 on top of isdn.
179
180The x25-utility package also contains an x25trace tool that can be
181used to monitor X.25 packets received by the network interfaces.
182The /proc/net/x25* files also contain useful information.
183
184- Henner
diff --git a/Documentation/isdn/syncPPP.FAQ b/Documentation/isdn/syncPPP.FAQ
deleted file mode 100644
index 3257a4bc0786..000000000000
--- a/Documentation/isdn/syncPPP.FAQ
+++ /dev/null
@@ -1,224 +0,0 @@
1simple isdn4linux PPP FAQ .. to be continued .. not 'debugged'
2-------------------------------------------------------------------
3
4Q01: what's pppd, ipppd, syncPPP, asyncPPP ??
5Q02: error message "this system lacks PPP support"
6Q03: strange information using 'ifconfig'
7Q04: MPPP?? What's that and how can I use it ...
8Q05: I tried MPPP but it doesn't work
9Q06: can I use asynchronous PPP encapsulation with network devices
10Q07: A SunISDN machine can't connect to my i4l system
11Q08: I wanna talk to several machines, which need different configs
12Q09: Starting the ipppd, I get only error messages from i4l
13Q10: I wanna use dynamic IP address assignment
14Q11: I can't connect. How can I check where the problem is.
15Q12: How can I reduce login delay?
16
17-------------------------------------------------------------------
18
19Q01: pppd, ipppd, syncPPP, asyncPPP .. what is that ?
20 what should I use?
21A: The pppd is for asynchronous PPP .. asynchronous means
22 here, the framing is character based. (e.g when
23 using ttyI* or tty* devices)
24
25 The ipppd handles PPP packets coming in HDLC
26 frames (bit based protocol) ... The PPP driver
27 in isdn4linux pushes all IP packets direct
28 to the network layer and all PPP protocol
29 frames to the /dev/ippp* device.
30 So, the ipppd is a simple external network
31 protocol handler.
32
33 If you login into a remote machine using the
34 /dev/ttyI* devices and then enable PPP on the
35 remote terminal server -> use the 'old' pppd
36
37 If your remote side immediately starts to send
38 frames ... you probably connect to a
39 syncPPP machine .. use the network device part
40 of isdn4linux with the 'syncppp' encapsulation
41 and make sure, that the ipppd is running and
42 connected to at least one /dev/ippp*. Check the
43 isdn4linux manual on how to configure a network device.
44
45--
46
47Q02: when I start the ipppd .. I only get the
48 error message "this system lacks PPP support"
49A: check that at least the device 'ippp0' exists.
50 (you can check this e.g with the program 'ifconfig')
51 The ipppd NEEDS this device under THIS name ..
52 If this device doesn't exists, use:
53 isdnctrl addif ippp0
54 isdnctrl encap ippp0 syncppp
55 ... (see isdn4linux doc for more) ...
56A: Maybe you have compiled the ipppd with another
57 kernel source tree than the kernel you currently
58 run ...
59
60--
61
62Q03: when I list the netdevices with ifconfig I see, that
63 my ISDN interface has a HWaddr and IRQ=0 and Base
64 address = 0
65A: The device is a fake ethernet device .. ignore IRQ and baseaddr
66 You need the HWaddr only for ethernet encapsulation.
67
68--
69
70Q04: MPPP?? What's that and how can I use it ...
71
72A: MPPP or MP or MPP (Warning: MP is also an
73 acronym for 'Multi Processor') stands for
74 Multi Point to Point and means bundling
75 of several channels to one logical stream.
76 To enable MPPP negotiation you must call the
77 ipppd with the '+mp' option.
78 You must also configure a slave device for
79 every additional channel. (see the i4l manual
80 for more)
81 To use channel bundling you must first activate
82 the 'master' or initial call. Now you can add
83 the slave channels with the command:
84 isdnctrl addlink <device>
85 e.g:
86 isdnctrl addlink ippp0
87 This is different from other encapsulations of
88 isdn4linux! With syncPPP, there is no automatic
89 activation of slave devices.
90
91--
92
93Q05: I tried MPPP but it doesn't work .. the ipppd
94 writes in the debug log something like:
95 .. rcvd [0][proto=0x3d] c0 00 00 00 80 fd 01 01 00 0a ...
96 .. sent [0][LCP ProtRej id=0x2 00 3d c0 00 00 00 80 fd 01 ...
97
98A: you forgot to compile MPPP/RFC1717 support into the
99 ISDN Subsystem. Recompile with this option enabled.
100
101--
102
103Q06: can I use asynchronous PPP encapsulation
104 over the network interface of isdn4linux ..
105
106A: No .. that's not possible .. Use the standard
107 PPP package over the /dev/ttyI* devices. You
108 must not use the ipppd for this.
109
110--
111
112Q07: A SunISDN machine tries to connect my i4l system,
113 which doesn't work.
114 Checking the debug log I just saw garbage like:
115!![ ... fill in the line ... ]!!
116
117A: The Sun tries to talk asynchronous PPP ... i4l
118 can't understand this ... try to use the ttyI*
119 devices with the standard PPP/pppd package
120
121A: (from Alexanter Strauss: )
122!![ ... fill in mail ]!!
123
124--
125
126Q08: I wanna talk to remote machines, which need
127 a different configuration. The only way
128 I found to do this is to kill the ipppd and
129 start a new one with another config to connect
130 to the second machine.
131
132A: you must bind a network interface explicitly to
133 an ippp device, where you can connect a (for this
134 interface) individually configured ipppd.
135
136--
137
138Q09: When I start the ipppd I only get error messages
139 from the i4l driver ..
140
141A: When starting, the ipppd calls functions which may
142 trigger a network packet. (e.g gethostbyname()).
143 Without the ipppd (at this moment, it is not
144 fully started) we can't handle this network request.
145 Try to configure hostnames necessary for the ipppd
146 in your local /etc/hosts file or in a way, that
147 your system can resolve it without using an
148 isdn/ippp network-interface.
149
150--
151
152Q10: I wanna use dynamic IP address assignment ... How
153 must I configure the network device.
154
155A: At least you must have a route which forwards
156 a packet to the ippp network-interface to trigger
157 the dial-on-demand.
158 A default route to the ippp-interface will work.
159 Now you must choose a dummy IP address for your
160 interface.
161 If for some reason you can't set the default
162 route to the ippp interface, you may take any
163 address of the subnet from which you expect your
164 dynamic IP number and set a 'network route' for
165 this subnet to the ippp interface.
166 To allow overriding of the dummy address you
167 must call the ipppd with the 'ipcp-accept-local' option.
168
169A: You must know, how the ipppd gets the addresses it wanna
170 configure. If you don't give any option, the ipppd
171 tries to negotiate the local host address!
172 With the option 'noipdefault' it requests an address
173 from the remote machine. With 'useifip' it gets the
174 addresses from the net interface. Or you set the address
175 on the option line with the <a.b.c.d:e.f.g.h> option.
176 Note: the IP address of the remote machine must be configured
177 locally or the remote machine must send it in an IPCP request.
178 If your side doesn't know the IP address after negotiation, it
179 closes the connection!
180 You must allow overriding of address with the 'ipcp-accept-*'
181 options, if you have set your own or the remote address
182 explicitly.
183
184A: Maybe you try these options .. e.g:
185
186 /sbin/ipppd :$REMOTE noipdefault /dev/ippp0
187
188 where REMOTE must be the address of the remote machine (the
189 machine, which gives you your address)
190
191--
192
193Q11: I can't connect. How can I check where the problem is.
194
195A: A good help log is the debug output from the ipppd...
196 Check whether you can find there:
197 - only a few LCP-conf-req SENT messages (less then 10)
198 and then a Term-REQ:
199 -> check whether your ISDN card is well configured
200 it seems, that your machine doesn't dial
201 (IRQ,IO,Proto, etc problems)
202 Configure your ISDN card to print debug messages and
203 check the /dev/isdnctrl output next time. There
204 you can see, whether there is activity on the card/line.
205 - there are at least a few RECV messages in the log:
206 -> fine: your card is dialing and your remote machine
207 tries to talk with you. Maybe only a missing
208 authentication. Check your ipppd configuration again.
209 - the ipppd exits for some reason:
210 -> not good ... check /var/adm/syslog and /var/adm/daemon.
211 Could be a bug in the ipppd.
212
213--
214
215Q12: How can I reduce login delay?
216
217A: Log a login session ('debug' log) and check which options
218 your remote side rejects. Next time configure your ipppd
219 to not negotiate these options. Another 'side effect' is, that
220 this increases redundancy. (e.g your remote side is buggy and
221 rejects options in a wrong way).
222
223
224
diff --git a/Documentation/process/changes.rst b/Documentation/process/changes.rst
index 18735dc460a0..111636ad1bad 100644
--- a/Documentation/process/changes.rst
+++ b/Documentation/process/changes.rst
@@ -23,8 +23,8 @@ running, the suggested command should tell you.
23 23
24Again, keep in mind that this list assumes you are already functionally 24Again, keep in mind that this list assumes you are already functionally
25running a Linux kernel. Also, not all tools are necessary on all 25running a Linux kernel. Also, not all tools are necessary on all
26systems; obviously, if you don't have any ISDN hardware, for example, 26systems; obviously, if you don't have any PC Card hardware, for example,
27you probably needn't concern yourself with isdn4k-utils. 27you probably needn't concern yourself with pcmciautils.
28 28
29====================== =============== ======================================== 29====================== =============== ========================================
30 Program Minimal version Command to check the version 30 Program Minimal version Command to check the version
@@ -45,7 +45,6 @@ btrfs-progs 0.18 btrfsck
45pcmciautils 004 pccardctl -V 45pcmciautils 004 pccardctl -V
46quota-tools 3.09 quota -V 46quota-tools 3.09 quota -V
47PPP 2.4.0 pppd --version 47PPP 2.4.0 pppd --version
48isdn4k-utils 3.1pre1 isdnctrl 2>&1|grep version
49nfs-utils 1.0.5 showmount --version 48nfs-utils 1.0.5 showmount --version
50procps 3.2.0 ps --version 49procps 3.2.0 ps --version
51oprofile 0.9 oprofiled --version 50oprofile 0.9 oprofiled --version
@@ -279,12 +278,6 @@ which can be made by::
279 278
280as root. 279as root.
281 280
282Isdn4k-utils
283------------
284
285Due to changes in the length of the phone number field, isdn4k-utils
286needs to be recompiled or (preferably) upgraded.
287
288NFS-utils 281NFS-utils
289--------- 282---------
290 283
@@ -448,11 +441,6 @@ PPP
448 441
449- <ftp://ftp.samba.org/pub/ppp/> 442- <ftp://ftp.samba.org/pub/ppp/>
450 443
451Isdn4k-utils
452------------
453
454- <ftp://ftp.isdn4linux.de/pub/isdn4linux/utils/>
455
456NFS-utils 444NFS-utils
457--------- 445---------
458 446
diff --git a/MAINTAINERS b/MAINTAINERS
index 0c55b0fedbe2..3a761e680296 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8371,9 +8371,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/kkeil/isdn-2.6.git
8371S: Maintained 8371S: Maintained
8372F: Documentation/isdn/ 8372F: Documentation/isdn/
8373F: drivers/isdn/ 8373F: drivers/isdn/
8374F: include/linux/isdn.h
8375F: include/linux/isdn/ 8374F: include/linux/isdn/
8376F: include/uapi/linux/isdn.h
8377F: include/uapi/linux/isdn/ 8375F: include/uapi/linux/isdn/
8378 8376
8379IT87 HARDWARE MONITORING DRIVER 8377IT87 HARDWARE MONITORING DRIVER
diff --git a/drivers/isdn/Kconfig b/drivers/isdn/Kconfig
index 1ca4d70d198a..6e3bf833c67e 100644
--- a/drivers/isdn/Kconfig
+++ b/drivers/isdn/Kconfig
@@ -21,27 +21,6 @@ menuconfig ISDN
21 21
22if ISDN 22if ISDN
23 23
24menuconfig ISDN_I4L
25 tristate "Old ISDN4Linux (deprecated)"
26 depends on TTY
27 ---help---
28 This driver allows you to use an ISDN adapter for networking
29 connections and as dialin/out device. The isdn-tty's have a built
30 in AT-compatible modem emulator. Network devices support autodial,
31 channel-bundling, callback and caller-authentication without having
32 a daemon running. A reduced T.70 protocol is supported with tty's
33 suitable for German BTX. On D-Channel, the protocols EDSS1
34 (Euro-ISDN) and 1TR6 (German style) are supported. See
35 <file:Documentation/isdn/README> for more information.
36
37 ISDN support in the linux kernel is moving towards a new API,
38 called CAPI (Common ISDN Application Programming Interface).
39 Therefore the old ISDN4Linux layer will eventually become obsolete.
40 It is still available, though, for use with adapters that are not
41 supported by the new CAPI subsystem yet.
42
43source "drivers/isdn/i4l/Kconfig"
44
45menuconfig ISDN_CAPI 24menuconfig ISDN_CAPI
46 tristate "CAPI 2.0 subsystem" 25 tristate "CAPI 2.0 subsystem"
47 help 26 help
@@ -71,9 +50,4 @@ source "drivers/isdn/hysdn/Kconfig"
71 50
72source "drivers/isdn/mISDN/Kconfig" 51source "drivers/isdn/mISDN/Kconfig"
73 52
74config ISDN_HDLC
75 tristate
76 select CRC_CCITT
77 select BITREVERSE
78
79endif # ISDN 53endif # ISDN
diff --git a/drivers/isdn/Makefile b/drivers/isdn/Makefile
index 7487f0bbe855..379b4a03c321 100644
--- a/drivers/isdn/Makefile
+++ b/drivers/isdn/Makefile
@@ -7,7 +7,5 @@ obj-$(CONFIG_ISDN_I4L) += i4l/
7obj-$(CONFIG_ISDN_CAPI) += capi/ 7obj-$(CONFIG_ISDN_CAPI) += capi/
8obj-$(CONFIG_MISDN) += mISDN/ 8obj-$(CONFIG_MISDN) += mISDN/
9obj-$(CONFIG_ISDN) += hardware/ 9obj-$(CONFIG_ISDN) += hardware/
10obj-$(CONFIG_ISDN_DIVERSION) += divert/
11obj-$(CONFIG_ISDN_DRV_LOOP) += isdnloop/
12obj-$(CONFIG_HYSDN) += hysdn/ 10obj-$(CONFIG_HYSDN) += hysdn/
13obj-$(CONFIG_ISDN_DRV_GIGASET) += gigaset/ 11obj-$(CONFIG_ISDN_DRV_GIGASET) += gigaset/
diff --git a/drivers/isdn/capi/Kconfig b/drivers/isdn/capi/Kconfig
index abaadce376c5..089dbee18f36 100644
--- a/drivers/isdn/capi/Kconfig
+++ b/drivers/isdn/capi/Kconfig
@@ -27,15 +27,6 @@ config ISDN_CAPI_MIDDLEWARE
27 device. If you want to use pppd with pppdcapiplugin to dial up to 27 device. If you want to use pppd with pppdcapiplugin to dial up to
28 your ISP, say Y here. 28 your ISP, say Y here.
29 29
30config ISDN_CAPI_CAPIDRV
31 tristate "CAPI2.0 capidrv interface support"
32 depends on ISDN_I4L
33 help
34 This option provides the glue code to hook up CAPI driven cards to
35 the legacy isdn4linux link layer. If you have a card which is
36 supported by a CAPI driver, but still want to use old features like
37 ippp interfaces or ttyI emulation, say Y/M here.
38
39config ISDN_CAPI_CAPIDRV_VERBOSE 30config ISDN_CAPI_CAPIDRV_VERBOSE
40 bool "Verbose reason code reporting" 31 bool "Verbose reason code reporting"
41 depends on ISDN_CAPI_CAPIDRV 32 depends on ISDN_CAPI_CAPIDRV
diff --git a/drivers/isdn/capi/capidrv.c b/drivers/isdn/capi/capidrv.c
deleted file mode 100644
index e8949f3dcae1..000000000000
--- a/drivers/isdn/capi/capidrv.c
+++ /dev/null
@@ -1,2525 +0,0 @@
1/* $Id: capidrv.c,v 1.1.2.2 2004/01/12 23:17:24 keil Exp $
2 *
3 * ISDN4Linux Driver, using capi20 interface (kernelcapi)
4 *
5 * Copyright 1997 by Carsten Paeth <calle@calle.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/compiler.h>
13#include <linux/module.h>
14#include <linux/errno.h>
15#include <linux/kernel.h>
16#include <linux/major.h>
17#include <linux/slab.h>
18#include <linux/fcntl.h>
19#include <linux/fs.h>
20#include <linux/signal.h>
21#include <linux/mm.h>
22#include <linux/timer.h>
23#include <linux/wait.h>
24#include <linux/skbuff.h>
25#include <linux/isdn.h>
26#include <linux/isdnif.h>
27#include <linux/proc_fs.h>
28#include <linux/seq_file.h>
29#include <linux/capi.h>
30#include <linux/kernelcapi.h>
31#include <linux/ctype.h>
32#include <linux/init.h>
33#include <linux/moduleparam.h>
34
35#include <linux/isdn/capiutil.h>
36#include <linux/isdn/capicmd.h>
37#include "capidrv.h"
38
39static int debugmode = 0;
40
41MODULE_DESCRIPTION("CAPI4Linux: Interface to ISDN4Linux");
42MODULE_AUTHOR("Carsten Paeth");
43MODULE_LICENSE("GPL");
44module_param(debugmode, uint, S_IRUGO | S_IWUSR);
45
46/* -------- type definitions ----------------------------------------- */
47
48
49struct capidrv_contr {
50
51 struct capidrv_contr *next;
52 struct module *owner;
53 u32 contrnr;
54 char name[20];
55
56 /*
57 * for isdn4linux
58 */
59 isdn_if interface;
60 int myid;
61
62 /*
63 * LISTEN state
64 */
65 int state;
66 u32 cipmask;
67 u32 cipmask2;
68 struct timer_list listentimer;
69
70 /*
71 * ID of capi message sent
72 */
73 u16 msgid;
74
75 /*
76 * B-Channels
77 */
78 int nbchan;
79 struct capidrv_bchan {
80 struct capidrv_contr *contr;
81 u8 msn[ISDN_MSNLEN];
82 int l2;
83 int l3;
84 u8 num[ISDN_MSNLEN];
85 u8 mynum[ISDN_MSNLEN];
86 int si1;
87 int si2;
88 int incoming;
89 int disconnecting;
90 struct capidrv_plci {
91 struct capidrv_plci *next;
92 u32 plci;
93 u32 ncci; /* ncci for CONNECT_ACTIVE_IND */
94 u16 msgid; /* to identfy CONNECT_CONF */
95 int chan;
96 int state;
97 int leasedline;
98 struct capidrv_ncci {
99 struct capidrv_ncci *next;
100 struct capidrv_plci *plcip;
101 u32 ncci;
102 u16 msgid; /* to identfy CONNECT_B3_CONF */
103 int chan;
104 int state;
105 int oldstate;
106 /* */
107 u16 datahandle;
108 struct ncci_datahandle_queue {
109 struct ncci_datahandle_queue *next;
110 u16 datahandle;
111 int len;
112 } *ackqueue;
113 } *ncci_list;
114 } *plcip;
115 struct capidrv_ncci *nccip;
116 } *bchans;
117
118 struct capidrv_plci *plci_list;
119
120 /* for q931 data */
121 u8 q931_buf[4096];
122 u8 *q931_read;
123 u8 *q931_write;
124 u8 *q931_end;
125};
126
127
128struct capidrv_data {
129 struct capi20_appl ap;
130 int ncontr;
131 struct capidrv_contr *contr_list;
132};
133
134typedef struct capidrv_plci capidrv_plci;
135typedef struct capidrv_ncci capidrv_ncci;
136typedef struct capidrv_contr capidrv_contr;
137typedef struct capidrv_data capidrv_data;
138typedef struct capidrv_bchan capidrv_bchan;
139
140/* -------- data definitions ----------------------------------------- */
141
142static capidrv_data global;
143static DEFINE_SPINLOCK(global_lock);
144
145static void handle_dtrace_data(capidrv_contr *card,
146 int send, int level2, u8 *data, u16 len);
147
148/* -------- convert functions ---------------------------------------- */
149
150static inline u32 b1prot(int l2, int l3)
151{
152 switch (l2) {
153 case ISDN_PROTO_L2_X75I:
154 case ISDN_PROTO_L2_X75UI:
155 case ISDN_PROTO_L2_X75BUI:
156 return 0;
157 case ISDN_PROTO_L2_HDLC:
158 default:
159 return 0;
160 case ISDN_PROTO_L2_TRANS:
161 return 1;
162 case ISDN_PROTO_L2_V11096:
163 case ISDN_PROTO_L2_V11019:
164 case ISDN_PROTO_L2_V11038:
165 return 2;
166 case ISDN_PROTO_L2_FAX:
167 return 4;
168 case ISDN_PROTO_L2_MODEM:
169 return 8;
170 }
171}
172
173static inline u32 b2prot(int l2, int l3)
174{
175 switch (l2) {
176 case ISDN_PROTO_L2_X75I:
177 case ISDN_PROTO_L2_X75UI:
178 case ISDN_PROTO_L2_X75BUI:
179 default:
180 return 0;
181 case ISDN_PROTO_L2_HDLC:
182 case ISDN_PROTO_L2_TRANS:
183 case ISDN_PROTO_L2_V11096:
184 case ISDN_PROTO_L2_V11019:
185 case ISDN_PROTO_L2_V11038:
186 case ISDN_PROTO_L2_MODEM:
187 return 1;
188 case ISDN_PROTO_L2_FAX:
189 return 4;
190 }
191}
192
193static inline u32 b3prot(int l2, int l3)
194{
195 switch (l2) {
196 case ISDN_PROTO_L2_X75I:
197 case ISDN_PROTO_L2_X75UI:
198 case ISDN_PROTO_L2_X75BUI:
199 case ISDN_PROTO_L2_HDLC:
200 case ISDN_PROTO_L2_TRANS:
201 case ISDN_PROTO_L2_V11096:
202 case ISDN_PROTO_L2_V11019:
203 case ISDN_PROTO_L2_V11038:
204 case ISDN_PROTO_L2_MODEM:
205 default:
206 return 0;
207 case ISDN_PROTO_L2_FAX:
208 return 4;
209 }
210}
211
212static _cstruct b1config_async_v110(u16 rate)
213{
214 /* CAPI-Spec "B1 Configuration" */
215 static unsigned char buf[9];
216 buf[0] = 8; /* len */
217 /* maximum bitrate */
218 buf[1] = rate & 0xff; buf[2] = (rate >> 8) & 0xff;
219 buf[3] = 8; buf[4] = 0; /* 8 bits per character */
220 buf[5] = 0; buf[6] = 0; /* parity none */
221 buf[7] = 0; buf[8] = 0; /* 1 stop bit */
222 return buf;
223}
224
225static _cstruct b1config(int l2, int l3)
226{
227 switch (l2) {
228 case ISDN_PROTO_L2_X75I:
229 case ISDN_PROTO_L2_X75UI:
230 case ISDN_PROTO_L2_X75BUI:
231 case ISDN_PROTO_L2_HDLC:
232 case ISDN_PROTO_L2_TRANS:
233 default:
234 return NULL;
235 case ISDN_PROTO_L2_V11096:
236 return b1config_async_v110(9600);
237 case ISDN_PROTO_L2_V11019:
238 return b1config_async_v110(19200);
239 case ISDN_PROTO_L2_V11038:
240 return b1config_async_v110(38400);
241 }
242}
243
244static inline u16 si2cip(u8 si1, u8 si2)
245{
246 static const u8 cip[17][5] =
247 {
248 /* 0 1 2 3 4 */
249 {0, 0, 0, 0, 0}, /*0 */
250 {16, 16, 4, 26, 16}, /*1 */
251 {17, 17, 17, 4, 4}, /*2 */
252 {2, 2, 2, 2, 2}, /*3 */
253 {18, 18, 18, 18, 18}, /*4 */
254 {2, 2, 2, 2, 2}, /*5 */
255 {0, 0, 0, 0, 0}, /*6 */
256 {2, 2, 2, 2, 2}, /*7 */
257 {2, 2, 2, 2, 2}, /*8 */
258 {21, 21, 21, 21, 21}, /*9 */
259 {19, 19, 19, 19, 19}, /*10 */
260 {0, 0, 0, 0, 0}, /*11 */
261 {0, 0, 0, 0, 0}, /*12 */
262 {0, 0, 0, 0, 0}, /*13 */
263 {0, 0, 0, 0, 0}, /*14 */
264 {22, 22, 22, 22, 22}, /*15 */
265 {27, 27, 27, 28, 27} /*16 */
266 };
267 if (si1 > 16)
268 si1 = 0;
269 if (si2 > 4)
270 si2 = 0;
271
272 return (u16) cip[si1][si2];
273}
274
275static inline u8 cip2si1(u16 cipval)
276{
277 static const u8 si[32] =
278 {7, 1, 7, 7, 1, 1, 7, 7, /*0-7 */
279 7, 1, 0, 0, 0, 0, 0, 0, /*8-15 */
280 1, 2, 4, 10, 9, 9, 15, 7, /*16-23 */
281 7, 7, 1, 16, 16, 0, 0, 0}; /*24-31 */
282
283 if (cipval > 31)
284 cipval = 0; /* .... */
285 return si[cipval];
286}
287
288static inline u8 cip2si2(u16 cipval)
289{
290 static const u8 si[32] =
291 {0, 0, 0, 0, 2, 3, 0, 0, /*0-7 */
292 0, 3, 0, 0, 0, 0, 0, 0, /*8-15 */
293 1, 2, 0, 0, 9, 0, 0, 0, /*16-23 */
294 0, 0, 3, 2, 3, 0, 0, 0}; /*24-31 */
295
296 if (cipval > 31)
297 cipval = 0; /* .... */
298 return si[cipval];
299}
300
301
302/* -------- controller management ------------------------------------- */
303
304static inline capidrv_contr *findcontrbydriverid(int driverid)
305{
306 unsigned long flags;
307 capidrv_contr *p;
308
309 spin_lock_irqsave(&global_lock, flags);
310 for (p = global.contr_list; p; p = p->next)
311 if (p->myid == driverid)
312 break;
313 spin_unlock_irqrestore(&global_lock, flags);
314 return p;
315}
316
317static capidrv_contr *findcontrbynumber(u32 contr)
318{
319 unsigned long flags;
320 capidrv_contr *p = global.contr_list;
321
322 spin_lock_irqsave(&global_lock, flags);
323 for (p = global.contr_list; p; p = p->next)
324 if (p->contrnr == contr)
325 break;
326 spin_unlock_irqrestore(&global_lock, flags);
327 return p;
328}
329
330
331/* -------- plci management ------------------------------------------ */
332
333static capidrv_plci *new_plci(capidrv_contr *card, int chan)
334{
335 capidrv_plci *plcip;
336
337 plcip = kzalloc(sizeof(capidrv_plci), GFP_ATOMIC);
338
339 if (plcip == NULL)
340 return NULL;
341
342 plcip->state = ST_PLCI_NONE;
343 plcip->plci = 0;
344 plcip->msgid = 0;
345 plcip->chan = chan;
346 plcip->next = card->plci_list;
347 card->plci_list = plcip;
348 card->bchans[chan].plcip = plcip;
349
350 return plcip;
351}
352
353static capidrv_plci *find_plci_by_plci(capidrv_contr *card, u32 plci)
354{
355 capidrv_plci *p;
356 for (p = card->plci_list; p; p = p->next)
357 if (p->plci == plci)
358 return p;
359 return NULL;
360}
361
362static capidrv_plci *find_plci_by_msgid(capidrv_contr *card, u16 msgid)
363{
364 capidrv_plci *p;
365 for (p = card->plci_list; p; p = p->next)
366 if (p->msgid == msgid)
367 return p;
368 return NULL;
369}
370
371static capidrv_plci *find_plci_by_ncci(capidrv_contr *card, u32 ncci)
372{
373 capidrv_plci *p;
374 for (p = card->plci_list; p; p = p->next)
375 if (p->plci == (ncci & 0xffff))
376 return p;
377 return NULL;
378}
379
380static void free_plci(capidrv_contr *card, capidrv_plci *plcip)
381{
382 capidrv_plci **pp;
383
384 for (pp = &card->plci_list; *pp; pp = &(*pp)->next) {
385 if (*pp == plcip) {
386 *pp = (*pp)->next;
387 card->bchans[plcip->chan].plcip = NULL;
388 card->bchans[plcip->chan].disconnecting = 0;
389 card->bchans[plcip->chan].incoming = 0;
390 kfree(plcip);
391 return;
392 }
393 }
394 printk(KERN_ERR "capidrv-%d: free_plci %p (0x%x) not found, Huh?\n",
395 card->contrnr, plcip, plcip->plci);
396}
397
398/* -------- ncci management ------------------------------------------ */
399
400static inline capidrv_ncci *new_ncci(capidrv_contr *card,
401 capidrv_plci *plcip,
402 u32 ncci)
403{
404 capidrv_ncci *nccip;
405
406 nccip = kzalloc(sizeof(capidrv_ncci), GFP_ATOMIC);
407
408 if (nccip == NULL)
409 return NULL;
410
411 nccip->ncci = ncci;
412 nccip->state = ST_NCCI_NONE;
413 nccip->plcip = plcip;
414 nccip->chan = plcip->chan;
415 nccip->datahandle = 0;
416
417 nccip->next = plcip->ncci_list;
418 plcip->ncci_list = nccip;
419
420 card->bchans[plcip->chan].nccip = nccip;
421
422 return nccip;
423}
424
425static inline capidrv_ncci *find_ncci(capidrv_contr *card, u32 ncci)
426{
427 capidrv_plci *plcip;
428 capidrv_ncci *p;
429
430 if ((plcip = find_plci_by_ncci(card, ncci)) == NULL)
431 return NULL;
432
433 for (p = plcip->ncci_list; p; p = p->next)
434 if (p->ncci == ncci)
435 return p;
436 return NULL;
437}
438
439static inline capidrv_ncci *find_ncci_by_msgid(capidrv_contr *card,
440 u32 ncci, u16 msgid)
441{
442 capidrv_plci *plcip;
443 capidrv_ncci *p;
444
445 if ((plcip = find_plci_by_ncci(card, ncci)) == NULL)
446 return NULL;
447
448 for (p = plcip->ncci_list; p; p = p->next)
449 if (p->msgid == msgid)
450 return p;
451 return NULL;
452}
453
454static void free_ncci(capidrv_contr *card, struct capidrv_ncci *nccip)
455{
456 struct capidrv_ncci **pp;
457
458 for (pp = &(nccip->plcip->ncci_list); *pp; pp = &(*pp)->next) {
459 if (*pp == nccip) {
460 *pp = (*pp)->next;
461 break;
462 }
463 }
464 card->bchans[nccip->chan].nccip = NULL;
465 kfree(nccip);
466}
467
468static int capidrv_add_ack(struct capidrv_ncci *nccip,
469 u16 datahandle, int len)
470{
471 struct ncci_datahandle_queue *n, **pp;
472
473 n = kmalloc(sizeof(struct ncci_datahandle_queue), GFP_ATOMIC);
474 if (!n) {
475 printk(KERN_ERR "capidrv: kmalloc ncci_datahandle failed\n");
476 return -1;
477 }
478 n->next = NULL;
479 n->datahandle = datahandle;
480 n->len = len;
481 for (pp = &nccip->ackqueue; *pp; pp = &(*pp)->next);
482 *pp = n;
483 return 0;
484}
485
486static int capidrv_del_ack(struct capidrv_ncci *nccip, u16 datahandle)
487{
488 struct ncci_datahandle_queue **pp, *p;
489 int len;
490
491 for (pp = &nccip->ackqueue; *pp; pp = &(*pp)->next) {
492 if ((*pp)->datahandle == datahandle) {
493 p = *pp;
494 len = p->len;
495 *pp = (*pp)->next;
496 kfree(p);
497 return len;
498 }
499 }
500 return -1;
501}
502
503/* -------- convert and send capi message ---------------------------- */
504
505static void send_message(capidrv_contr *card, _cmsg *cmsg)
506{
507 struct sk_buff *skb;
508 size_t len;
509
510 if (capi_cmsg2message(cmsg, cmsg->buf)) {
511 printk(KERN_ERR "capidrv::send_message: parser failure\n");
512 return;
513 }
514 len = CAPIMSG_LEN(cmsg->buf);
515 skb = alloc_skb(len, GFP_ATOMIC);
516 if (!skb) {
517 printk(KERN_ERR "capidrv::send_message: can't allocate mem\n");
518 return;
519 }
520 skb_put_data(skb, cmsg->buf, len);
521 if (capi20_put_message(&global.ap, skb) != CAPI_NOERROR)
522 kfree_skb(skb);
523}
524
525/* -------- state machine -------------------------------------------- */
526
527struct listenstatechange {
528 int actstate;
529 int nextstate;
530 int event;
531};
532
533static struct listenstatechange listentable[] =
534{
535 {ST_LISTEN_NONE, ST_LISTEN_WAIT_CONF, EV_LISTEN_REQ},
536 {ST_LISTEN_ACTIVE, ST_LISTEN_ACTIVE_WAIT_CONF, EV_LISTEN_REQ},
537 {ST_LISTEN_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_ERROR},
538 {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_ERROR},
539 {ST_LISTEN_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_EMPTY},
540 {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_NONE, EV_LISTEN_CONF_EMPTY},
541 {ST_LISTEN_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_OK},
542 {ST_LISTEN_ACTIVE_WAIT_CONF, ST_LISTEN_ACTIVE, EV_LISTEN_CONF_OK},
543 {},
544};
545
546static void listen_change_state(capidrv_contr *card, int event)
547{
548 struct listenstatechange *p = listentable;
549 while (p->event) {
550 if (card->state == p->actstate && p->event == event) {
551 if (debugmode)
552 printk(KERN_DEBUG "capidrv-%d: listen_change_state %d -> %d\n",
553 card->contrnr, card->state, p->nextstate);
554 card->state = p->nextstate;
555 return;
556 }
557 p++;
558 }
559 printk(KERN_ERR "capidrv-%d: listen_change_state state=%d event=%d ????\n",
560 card->contrnr, card->state, event);
561
562}
563
564/* ------------------------------------------------------------------ */
565
566static void p0(capidrv_contr *card, capidrv_plci *plci)
567{
568 isdn_ctrl cmd;
569
570 card->bchans[plci->chan].contr = NULL;
571 cmd.command = ISDN_STAT_DHUP;
572 cmd.driver = card->myid;
573 cmd.arg = plci->chan;
574 card->interface.statcallb(&cmd);
575 free_plci(card, plci);
576}
577
578/* ------------------------------------------------------------------ */
579
580struct plcistatechange {
581 int actstate;
582 int nextstate;
583 int event;
584 void (*changefunc)(capidrv_contr *card, capidrv_plci *plci);
585};
586
587static struct plcistatechange plcitable[] =
588{
589 /* P-0 */
590 {ST_PLCI_NONE, ST_PLCI_OUTGOING, EV_PLCI_CONNECT_REQ, NULL},
591 {ST_PLCI_NONE, ST_PLCI_ALLOCATED, EV_PLCI_FACILITY_IND_UP, NULL},
592 {ST_PLCI_NONE, ST_PLCI_INCOMING, EV_PLCI_CONNECT_IND, NULL},
593 {ST_PLCI_NONE, ST_PLCI_RESUMEING, EV_PLCI_RESUME_REQ, NULL},
594 /* P-0.1 */
595 {ST_PLCI_OUTGOING, ST_PLCI_NONE, EV_PLCI_CONNECT_CONF_ERROR, p0},
596 {ST_PLCI_OUTGOING, ST_PLCI_ALLOCATED, EV_PLCI_CONNECT_CONF_OK, NULL},
597 /* P-1 */
598 {ST_PLCI_ALLOCATED, ST_PLCI_ACTIVE, EV_PLCI_CONNECT_ACTIVE_IND, NULL},
599 {ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, NULL},
600 {ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, NULL},
601 {ST_PLCI_ALLOCATED, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, NULL},
602 /* P-ACT */
603 {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, NULL},
604 {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, NULL},
605 {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, NULL},
606 {ST_PLCI_ACTIVE, ST_PLCI_HELD, EV_PLCI_HOLD_IND, NULL},
607 {ST_PLCI_ACTIVE, ST_PLCI_DISCONNECTING, EV_PLCI_SUSPEND_IND, NULL},
608 /* P-2 */
609 {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_CONNECT_REJECT, NULL},
610 {ST_PLCI_INCOMING, ST_PLCI_FACILITY_IND, EV_PLCI_FACILITY_IND_UP, NULL},
611 {ST_PLCI_INCOMING, ST_PLCI_ACCEPTING, EV_PLCI_CONNECT_RESP, NULL},
612 {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, NULL},
613 {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, NULL},
614 {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, NULL},
615 {ST_PLCI_INCOMING, ST_PLCI_DISCONNECTING, EV_PLCI_CD_IND, NULL},
616 /* P-3 */
617 {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_CONNECT_REJECT, NULL},
618 {ST_PLCI_FACILITY_IND, ST_PLCI_ACCEPTING, EV_PLCI_CONNECT_ACTIVE_IND, NULL},
619 {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, NULL},
620 {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, NULL},
621 {ST_PLCI_FACILITY_IND, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, NULL},
622 /* P-4 */
623 {ST_PLCI_ACCEPTING, ST_PLCI_ACTIVE, EV_PLCI_CONNECT_ACTIVE_IND, NULL},
624 {ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTING, EV_PLCI_DISCONNECT_REQ, NULL},
625 {ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTING, EV_PLCI_FACILITY_IND_DOWN, NULL},
626 {ST_PLCI_ACCEPTING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, NULL},
627 /* P-5 */
628 {ST_PLCI_DISCONNECTING, ST_PLCI_DISCONNECTED, EV_PLCI_DISCONNECT_IND, NULL},
629 /* P-6 */
630 {ST_PLCI_DISCONNECTED, ST_PLCI_NONE, EV_PLCI_DISCONNECT_RESP, p0},
631 /* P-0.Res */
632 {ST_PLCI_RESUMEING, ST_PLCI_NONE, EV_PLCI_RESUME_CONF_ERROR, p0},
633 {ST_PLCI_RESUMEING, ST_PLCI_RESUME, EV_PLCI_RESUME_CONF_OK, NULL},
634 /* P-RES */
635 {ST_PLCI_RESUME, ST_PLCI_ACTIVE, EV_PLCI_RESUME_IND, NULL},
636 /* P-HELD */
637 {ST_PLCI_HELD, ST_PLCI_ACTIVE, EV_PLCI_RETRIEVE_IND, NULL},
638 {},
639};
640
641static void plci_change_state(capidrv_contr *card, capidrv_plci *plci, int event)
642{
643 struct plcistatechange *p = plcitable;
644 while (p->event) {
645 if (plci->state == p->actstate && p->event == event) {
646 if (debugmode)
647 printk(KERN_DEBUG "capidrv-%d: plci_change_state:0x%x %d -> %d\n",
648 card->contrnr, plci->plci, plci->state, p->nextstate);
649 plci->state = p->nextstate;
650 if (p->changefunc)
651 p->changefunc(card, plci);
652 return;
653 }
654 p++;
655 }
656 printk(KERN_ERR "capidrv-%d: plci_change_state:0x%x state=%d event=%d ????\n",
657 card->contrnr, plci->plci, plci->state, event);
658}
659
660/* ------------------------------------------------------------------ */
661
662static _cmsg cmsg;
663
664static void n0(capidrv_contr *card, capidrv_ncci *ncci)
665{
666 isdn_ctrl cmd;
667
668 capi_fill_DISCONNECT_REQ(&cmsg,
669 global.ap.applid,
670 card->msgid++,
671 ncci->plcip->plci,
672 NULL, /* BChannelinformation */
673 NULL, /* Keypadfacility */
674 NULL, /* Useruserdata */ /* $$$$ */
675 NULL /* Facilitydataarray */
676 );
677 plci_change_state(card, ncci->plcip, EV_PLCI_DISCONNECT_REQ);
678 send_message(card, &cmsg);
679
680 cmd.command = ISDN_STAT_BHUP;
681 cmd.driver = card->myid;
682 cmd.arg = ncci->chan;
683 card->interface.statcallb(&cmd);
684 free_ncci(card, ncci);
685}
686
687/* ------------------------------------------------------------------ */
688
689struct nccistatechange {
690 int actstate;
691 int nextstate;
692 int event;
693 void (*changefunc)(capidrv_contr *card, capidrv_ncci *ncci);
694};
695
696static struct nccistatechange nccitable[] =
697{
698 /* N-0 */
699 {ST_NCCI_NONE, ST_NCCI_OUTGOING, EV_NCCI_CONNECT_B3_REQ, NULL},
700 {ST_NCCI_NONE, ST_NCCI_INCOMING, EV_NCCI_CONNECT_B3_IND, NULL},
701 /* N-0.1 */
702 {ST_NCCI_OUTGOING, ST_NCCI_ALLOCATED, EV_NCCI_CONNECT_B3_CONF_OK, NULL},
703 {ST_NCCI_OUTGOING, ST_NCCI_NONE, EV_NCCI_CONNECT_B3_CONF_ERROR, n0},
704 /* N-1 */
705 {ST_NCCI_INCOMING, ST_NCCI_DISCONNECTING, EV_NCCI_CONNECT_B3_REJECT, NULL},
706 {ST_NCCI_INCOMING, ST_NCCI_ALLOCATED, EV_NCCI_CONNECT_B3_RESP, NULL},
707 {ST_NCCI_INCOMING, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, NULL},
708 {ST_NCCI_INCOMING, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, NULL},
709 /* N-2 */
710 {ST_NCCI_ALLOCATED, ST_NCCI_ACTIVE, EV_NCCI_CONNECT_B3_ACTIVE_IND, NULL},
711 {ST_NCCI_ALLOCATED, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, NULL},
712 {ST_NCCI_ALLOCATED, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, NULL},
713 /* N-ACT */
714 {ST_NCCI_ACTIVE, ST_NCCI_ACTIVE, EV_NCCI_RESET_B3_IND, NULL},
715 {ST_NCCI_ACTIVE, ST_NCCI_RESETING, EV_NCCI_RESET_B3_REQ, NULL},
716 {ST_NCCI_ACTIVE, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, NULL},
717 {ST_NCCI_ACTIVE, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, NULL},
718 /* N-3 */
719 {ST_NCCI_RESETING, ST_NCCI_ACTIVE, EV_NCCI_RESET_B3_IND, NULL},
720 {ST_NCCI_RESETING, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, NULL},
721 {ST_NCCI_RESETING, ST_NCCI_DISCONNECTING, EV_NCCI_DISCONNECT_B3_REQ, NULL},
722 /* N-4 */
723 {ST_NCCI_DISCONNECTING, ST_NCCI_DISCONNECTED, EV_NCCI_DISCONNECT_B3_IND, NULL},
724 {ST_NCCI_DISCONNECTING, ST_NCCI_PREVIOUS, EV_NCCI_DISCONNECT_B3_CONF_ERROR, NULL},
725 /* N-5 */
726 {ST_NCCI_DISCONNECTED, ST_NCCI_NONE, EV_NCCI_DISCONNECT_B3_RESP, n0},
727 {},
728};
729
730static void ncci_change_state(capidrv_contr *card, capidrv_ncci *ncci, int event)
731{
732 struct nccistatechange *p = nccitable;
733 while (p->event) {
734 if (ncci->state == p->actstate && p->event == event) {
735 if (debugmode)
736 printk(KERN_DEBUG "capidrv-%d: ncci_change_state:0x%x %d -> %d\n",
737 card->contrnr, ncci->ncci, ncci->state, p->nextstate);
738 if (p->nextstate == ST_NCCI_PREVIOUS) {
739 ncci->state = ncci->oldstate;
740 ncci->oldstate = p->actstate;
741 } else {
742 ncci->oldstate = p->actstate;
743 ncci->state = p->nextstate;
744 }
745 if (p->changefunc)
746 p->changefunc(card, ncci);
747 return;
748 }
749 p++;
750 }
751 printk(KERN_ERR "capidrv-%d: ncci_change_state:0x%x state=%d event=%d ????\n",
752 card->contrnr, ncci->ncci, ncci->state, event);
753}
754
755/* ------------------------------------------------------------------- */
756
757static inline int new_bchan(capidrv_contr *card)
758{
759 int i;
760 for (i = 0; i < card->nbchan; i++) {
761 if (card->bchans[i].plcip == NULL) {
762 card->bchans[i].disconnecting = 0;
763 return i;
764 }
765 }
766 return -1;
767}
768
769/* ------------------------------------------------------------------- */
770static char *capi_info2str(u16 reason)
771{
772#ifndef CONFIG_ISDN_CAPI_CAPIDRV_VERBOSE
773 return "..";
774#else
775 switch (reason) {
776
777/*-- informative values (corresponding message was processed) -----*/
778 case 0x0001:
779 return "NCPI not supported by current protocol, NCPI ignored";
780 case 0x0002:
781 return "Flags not supported by current protocol, flags ignored";
782 case 0x0003:
783 return "Alert already sent by another application";
784
785/*-- error information concerning CAPI_REGISTER -----*/
786 case 0x1001:
787 return "Too many applications";
788 case 0x1002:
789 return "Logical block size too small, must be at least 128 Bytes";
790 case 0x1003:
791 return "Buffer exceeds 64 kByte";
792 case 0x1004:
793 return "Message buffer size too small, must be at least 1024 Bytes";
794 case 0x1005:
795 return "Max. number of logical connections not supported";
796 case 0x1006:
797 return "Reserved";
798 case 0x1007:
799 return "The message could not be accepted because of an internal busy condition";
800 case 0x1008:
801 return "OS resource error (no memory ?)";
802 case 0x1009:
803 return "CAPI not installed";
804 case 0x100A:
805 return "Controller does not support external equipment";
806 case 0x100B:
807 return "Controller does only support external equipment";
808
809/*-- error information concerning message exchange functions -----*/
810 case 0x1101:
811 return "Illegal application number";
812 case 0x1102:
813 return "Illegal command or subcommand or message length less than 12 bytes";
814 case 0x1103:
815 return "The message could not be accepted because of a queue full condition !! The error code does not imply that CAPI cannot receive messages directed to another controller, PLCI or NCCI";
816 case 0x1104:
817 return "Queue is empty";
818 case 0x1105:
819 return "Queue overflow, a message was lost !! This indicates a configuration error. The only recovery from this error is to perform a CAPI_RELEASE";
820 case 0x1106:
821 return "Unknown notification parameter";
822 case 0x1107:
823 return "The Message could not be accepted because of an internal busy condition";
824 case 0x1108:
825 return "OS Resource error (no memory ?)";
826 case 0x1109:
827 return "CAPI not installed";
828 case 0x110A:
829 return "Controller does not support external equipment";
830 case 0x110B:
831 return "Controller does only support external equipment";
832
833/*-- error information concerning resource / coding problems -----*/
834 case 0x2001:
835 return "Message not supported in current state";
836 case 0x2002:
837 return "Illegal Controller / PLCI / NCCI";
838 case 0x2003:
839 return "Out of PLCI";
840 case 0x2004:
841 return "Out of NCCI";
842 case 0x2005:
843 return "Out of LISTEN";
844 case 0x2006:
845 return "Out of FAX resources (protocol T.30)";
846 case 0x2007:
847 return "Illegal message parameter coding";
848
849/*-- error information concerning requested services -----*/
850 case 0x3001:
851 return "B1 protocol not supported";
852 case 0x3002:
853 return "B2 protocol not supported";
854 case 0x3003:
855 return "B3 protocol not supported";
856 case 0x3004:
857 return "B1 protocol parameter not supported";
858 case 0x3005:
859 return "B2 protocol parameter not supported";
860 case 0x3006:
861 return "B3 protocol parameter not supported";
862 case 0x3007:
863 return "B protocol combination not supported";
864 case 0x3008:
865 return "NCPI not supported";
866 case 0x3009:
867 return "CIP Value unknown";
868 case 0x300A:
869 return "Flags not supported (reserved bits)";
870 case 0x300B:
871 return "Facility not supported";
872 case 0x300C:
873 return "Data length not supported by current protocol";
874 case 0x300D:
875 return "Reset procedure not supported by current protocol";
876
877/*-- informations about the clearing of a physical connection -----*/
878 case 0x3301:
879 return "Protocol error layer 1 (broken line or B-channel removed by signalling protocol)";
880 case 0x3302:
881 return "Protocol error layer 2";
882 case 0x3303:
883 return "Protocol error layer 3";
884 case 0x3304:
885 return "Another application got that call";
886/*-- T.30 specific reasons -----*/
887 case 0x3311:
888 return "Connecting not successful (remote station is no FAX G3 machine)";
889 case 0x3312:
890 return "Connecting not successful (training error)";
891 case 0x3313:
892 return "Disconnected before transfer (remote station does not support transfer mode, e.g. resolution)";
893 case 0x3314:
894 return "Disconnected during transfer (remote abort)";
895 case 0x3315:
896 return "Disconnected during transfer (remote procedure error, e.g. unsuccessful repetition of T.30 commands)";
897 case 0x3316:
898 return "Disconnected during transfer (local tx data underrun)";
899 case 0x3317:
900 return "Disconnected during transfer (local rx data overflow)";
901 case 0x3318:
902 return "Disconnected during transfer (local abort)";
903 case 0x3319:
904 return "Illegal parameter coding (e.g. SFF coding error)";
905
906/*-- disconnect causes from the network according to ETS 300 102-1/Q.931 -----*/
907 case 0x3481: return "Unallocated (unassigned) number";
908 case 0x3482: return "No route to specified transit network";
909 case 0x3483: return "No route to destination";
910 case 0x3486: return "Channel unacceptable";
911 case 0x3487:
912 return "Call awarded and being delivered in an established channel";
913 case 0x3490: return "Normal call clearing";
914 case 0x3491: return "User busy";
915 case 0x3492: return "No user responding";
916 case 0x3493: return "No answer from user (user alerted)";
917 case 0x3495: return "Call rejected";
918 case 0x3496: return "Number changed";
919 case 0x349A: return "Non-selected user clearing";
920 case 0x349B: return "Destination out of order";
921 case 0x349C: return "Invalid number format";
922 case 0x349D: return "Facility rejected";
923 case 0x349E: return "Response to STATUS ENQUIRY";
924 case 0x349F: return "Normal, unspecified";
925 case 0x34A2: return "No circuit / channel available";
926 case 0x34A6: return "Network out of order";
927 case 0x34A9: return "Temporary failure";
928 case 0x34AA: return "Switching equipment congestion";
929 case 0x34AB: return "Access information discarded";
930 case 0x34AC: return "Requested circuit / channel not available";
931 case 0x34AF: return "Resources unavailable, unspecified";
932 case 0x34B1: return "Quality of service unavailable";
933 case 0x34B2: return "Requested facility not subscribed";
934 case 0x34B9: return "Bearer capability not authorized";
935 case 0x34BA: return "Bearer capability not presently available";
936 case 0x34BF: return "Service or option not available, unspecified";
937 case 0x34C1: return "Bearer capability not implemented";
938 case 0x34C2: return "Channel type not implemented";
939 case 0x34C5: return "Requested facility not implemented";
940 case 0x34C6: return "Only restricted digital information bearer capability is available";
941 case 0x34CF: return "Service or option not implemented, unspecified";
942 case 0x34D1: return "Invalid call reference value";
943 case 0x34D2: return "Identified channel does not exist";
944 case 0x34D3: return "A suspended call exists, but this call identity does not";
945 case 0x34D4: return "Call identity in use";
946 case 0x34D5: return "No call suspended";
947 case 0x34D6: return "Call having the requested call identity has been cleared";
948 case 0x34D8: return "Incompatible destination";
949 case 0x34DB: return "Invalid transit network selection";
950 case 0x34DF: return "Invalid message, unspecified";
951 case 0x34E0: return "Mandatory information element is missing";
952 case 0x34E1: return "Message type non-existent or not implemented";
953 case 0x34E2: return "Message not compatible with call state or message type non-existent or not implemented";
954 case 0x34E3: return "Information element non-existent or not implemented";
955 case 0x34E4: return "Invalid information element contents";
956 case 0x34E5: return "Message not compatible with call state";
957 case 0x34E6: return "Recovery on timer expiry";
958 case 0x34EF: return "Protocol error, unspecified";
959 case 0x34FF: return "Interworking, unspecified";
960
961 default: return "No additional information";
962 }
963#endif
964}
965
966static void handle_controller(_cmsg *cmsg)
967{
968 capidrv_contr *card = findcontrbynumber(cmsg->adr.adrController & 0x7f);
969
970 if (!card) {
971 printk(KERN_ERR "capidrv: %s from unknown controller 0x%x\n",
972 capi_cmd2str(cmsg->Command, cmsg->Subcommand),
973 cmsg->adr.adrController & 0x7f);
974 return;
975 }
976 switch (CAPICMD(cmsg->Command, cmsg->Subcommand)) {
977
978 case CAPI_LISTEN_CONF: /* Controller */
979 if (debugmode)
980 printk(KERN_DEBUG "capidrv-%d: listenconf Info=0x%4x (%s) cipmask=0x%x\n",
981 card->contrnr, cmsg->Info, capi_info2str(cmsg->Info), card->cipmask);
982 if (cmsg->Info) {
983 listen_change_state(card, EV_LISTEN_CONF_ERROR);
984 } else if (card->cipmask == 0) {
985 listen_change_state(card, EV_LISTEN_CONF_EMPTY);
986 } else {
987 listen_change_state(card, EV_LISTEN_CONF_OK);
988 }
989 break;
990
991 case CAPI_MANUFACTURER_IND: /* Controller */
992 if (cmsg->ManuID == 0x214D5641
993 && cmsg->Class == 0
994 && cmsg->Function == 1) {
995 u8 *data = cmsg->ManuData + 3;
996 u16 len = cmsg->ManuData[0];
997 u16 layer;
998 int direction;
999 if (len == 255) {
1000 len = (cmsg->ManuData[1] | (cmsg->ManuData[2] << 8));
1001 data += 2;
1002 }
1003 len -= 2;
1004 layer = ((*(data - 1)) << 8) | *(data - 2);
1005 if (layer & 0x300)
1006 direction = (layer & 0x200) ? 0 : 1;
1007 else direction = (layer & 0x800) ? 0 : 1;
1008 if (layer & 0x0C00) {
1009 if ((layer & 0xff) == 0x80) {
1010 handle_dtrace_data(card, direction, 1, data, len);
1011 break;
1012 }
1013 } else if ((layer & 0xff) < 0x80) {
1014 handle_dtrace_data(card, direction, 0, data, len);
1015 break;
1016 }
1017 printk(KERN_INFO "capidrv-%d: %s from controller 0x%x layer 0x%x, ignored\n",
1018 card->contrnr,
1019 capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1020 cmsg->adr.adrController, layer);
1021 break;
1022 }
1023 goto ignored;
1024 case CAPI_MANUFACTURER_CONF: /* Controller */
1025 if (cmsg->ManuID == 0x214D5641) {
1026 char *s = NULL;
1027 switch (cmsg->Class) {
1028 case 0: break;
1029 case 1: s = "unknown class"; break;
1030 case 2: s = "unknown function"; break;
1031 default: s = "unknown error"; break;
1032 }
1033 if (s)
1034 printk(KERN_INFO "capidrv-%d: %s from controller 0x%x function %d: %s\n",
1035 card->contrnr,
1036 capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1037 cmsg->adr.adrController,
1038 cmsg->Function, s);
1039 break;
1040 }
1041 goto ignored;
1042 case CAPI_FACILITY_IND: /* Controller/plci/ncci */
1043 goto ignored;
1044 case CAPI_FACILITY_CONF: /* Controller/plci/ncci */
1045 goto ignored;
1046 case CAPI_INFO_IND: /* Controller/plci */
1047 goto ignored;
1048 case CAPI_INFO_CONF: /* Controller/plci */
1049 goto ignored;
1050
1051 default:
1052 printk(KERN_ERR "capidrv-%d: got %s from controller 0x%x ???",
1053 card->contrnr,
1054 capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1055 cmsg->adr.adrController);
1056 }
1057 return;
1058
1059ignored:
1060 printk(KERN_INFO "capidrv-%d: %s from controller 0x%x ignored\n",
1061 card->contrnr,
1062 capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1063 cmsg->adr.adrController);
1064}
1065
1066static void handle_incoming_call(capidrv_contr *card, _cmsg *cmsg)
1067{
1068 capidrv_plci *plcip;
1069 capidrv_bchan *bchan;
1070 isdn_ctrl cmd;
1071 int chan;
1072
1073 if ((chan = new_bchan(card)) == -1) {
1074 printk(KERN_ERR "capidrv-%d: incoming call on not existing bchan ?\n", card->contrnr);
1075 return;
1076 }
1077 bchan = &card->bchans[chan];
1078 if ((plcip = new_plci(card, chan)) == NULL) {
1079 printk(KERN_ERR "capidrv-%d: incoming call: no memory, sorry.\n", card->contrnr);
1080 return;
1081 }
1082 bchan->incoming = 1;
1083 plcip->plci = cmsg->adr.adrPLCI;
1084 plci_change_state(card, plcip, EV_PLCI_CONNECT_IND);
1085
1086 cmd.command = ISDN_STAT_ICALL;
1087 cmd.driver = card->myid;
1088 cmd.arg = chan;
1089 memset(&cmd.parm.setup, 0, sizeof(cmd.parm.setup));
1090 strncpy(cmd.parm.setup.phone,
1091 cmsg->CallingPartyNumber + 3,
1092 cmsg->CallingPartyNumber[0] - 2);
1093 strncpy(cmd.parm.setup.eazmsn,
1094 cmsg->CalledPartyNumber + 2,
1095 cmsg->CalledPartyNumber[0] - 1);
1096 cmd.parm.setup.si1 = cip2si1(cmsg->CIPValue);
1097 cmd.parm.setup.si2 = cip2si2(cmsg->CIPValue);
1098 cmd.parm.setup.plan = cmsg->CallingPartyNumber[1];
1099 cmd.parm.setup.screen = cmsg->CallingPartyNumber[2];
1100
1101 printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%s\n",
1102 card->contrnr,
1103 cmd.parm.setup.phone,
1104 cmd.parm.setup.si1,
1105 cmd.parm.setup.si2,
1106 cmd.parm.setup.eazmsn);
1107
1108 if (cmd.parm.setup.si1 == 1 && cmd.parm.setup.si2 != 0) {
1109 printk(KERN_INFO "capidrv-%d: patching si2=%d to 0 for VBOX\n",
1110 card->contrnr,
1111 cmd.parm.setup.si2);
1112 cmd.parm.setup.si2 = 0;
1113 }
1114
1115 switch (card->interface.statcallb(&cmd)) {
1116 case 0:
1117 case 3:
1118 /* No device matching this call.
1119 * and isdn_common.c has send a HANGUP command
1120 * which is ignored in state ST_PLCI_INCOMING,
1121 * so we send RESP to ignore the call
1122 */
1123 capi_cmsg_answer(cmsg);
1124 cmsg->Reject = 1; /* ignore */
1125 plci_change_state(card, plcip, EV_PLCI_CONNECT_REJECT);
1126 send_message(card, cmsg);
1127 printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%s ignored\n",
1128 card->contrnr,
1129 cmd.parm.setup.phone,
1130 cmd.parm.setup.si1,
1131 cmd.parm.setup.si2,
1132 cmd.parm.setup.eazmsn);
1133 break;
1134 case 1:
1135 /* At least one device matching this call (RING on ttyI)
1136 * HL-driver may send ALERTING on the D-channel in this
1137 * case.
1138 * really means: RING on ttyI or a net interface
1139 * accepted this call already.
1140 *
1141 * If the call was accepted, state has already changed,
1142 * and CONNECT_RESP already sent.
1143 */
1144 if (plcip->state == ST_PLCI_INCOMING) {
1145 printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%s tty alerting\n",
1146 card->contrnr,
1147 cmd.parm.setup.phone,
1148 cmd.parm.setup.si1,
1149 cmd.parm.setup.si2,
1150 cmd.parm.setup.eazmsn);
1151 capi_fill_ALERT_REQ(cmsg,
1152 global.ap.applid,
1153 card->msgid++,
1154 plcip->plci, /* adr */
1155 NULL,/* BChannelinformation */
1156 NULL,/* Keypadfacility */
1157 NULL,/* Useruserdata */
1158 NULL /* Facilitydataarray */
1159 );
1160 plcip->msgid = cmsg->Messagenumber;
1161 send_message(card, cmsg);
1162 } else {
1163 printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%s on netdev\n",
1164 card->contrnr,
1165 cmd.parm.setup.phone,
1166 cmd.parm.setup.si1,
1167 cmd.parm.setup.si2,
1168 cmd.parm.setup.eazmsn);
1169 }
1170 break;
1171
1172 case 2: /* Call will be rejected. */
1173 capi_cmsg_answer(cmsg);
1174 cmsg->Reject = 2; /* reject call, normal call clearing */
1175 plci_change_state(card, plcip, EV_PLCI_CONNECT_REJECT);
1176 send_message(card, cmsg);
1177 break;
1178
1179 default:
1180 /* An error happened. (Invalid parameters for example.) */
1181 capi_cmsg_answer(cmsg);
1182 cmsg->Reject = 8; /* reject call,
1183 destination out of order */
1184 plci_change_state(card, plcip, EV_PLCI_CONNECT_REJECT);
1185 send_message(card, cmsg);
1186 break;
1187 }
1188 return;
1189}
1190
1191static void handle_plci(_cmsg *cmsg)
1192{
1193 capidrv_contr *card = findcontrbynumber(cmsg->adr.adrController & 0x7f);
1194 capidrv_plci *plcip;
1195 isdn_ctrl cmd;
1196 _cdebbuf *cdb;
1197
1198 if (!card) {
1199 printk(KERN_ERR "capidrv: %s from unknown controller 0x%x\n",
1200 capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1201 cmsg->adr.adrController & 0x7f);
1202 return;
1203 }
1204 switch (CAPICMD(cmsg->Command, cmsg->Subcommand)) {
1205
1206 case CAPI_DISCONNECT_IND: /* plci */
1207 if (cmsg->Reason) {
1208 printk(KERN_INFO "capidrv-%d: %s reason 0x%x (%s) for plci 0x%x\n",
1209 card->contrnr,
1210 capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1211 cmsg->Reason, capi_info2str(cmsg->Reason), cmsg->adr.adrPLCI);
1212 }
1213 if (!(plcip = find_plci_by_plci(card, cmsg->adr.adrPLCI))) {
1214 capi_cmsg_answer(cmsg);
1215 send_message(card, cmsg);
1216 goto notfound;
1217 }
1218 card->bchans[plcip->chan].disconnecting = 1;
1219 plci_change_state(card, plcip, EV_PLCI_DISCONNECT_IND);
1220 capi_cmsg_answer(cmsg);
1221 plci_change_state(card, plcip, EV_PLCI_DISCONNECT_RESP);
1222 send_message(card, cmsg);
1223 break;
1224
1225 case CAPI_DISCONNECT_CONF: /* plci */
1226 if (cmsg->Info) {
1227 printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for plci 0x%x\n",
1228 card->contrnr,
1229 capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1230 cmsg->Info, capi_info2str(cmsg->Info),
1231 cmsg->adr.adrPLCI);
1232 }
1233 if (!(plcip = find_plci_by_plci(card, cmsg->adr.adrPLCI)))
1234 goto notfound;
1235
1236 card->bchans[plcip->chan].disconnecting = 1;
1237 break;
1238
1239 case CAPI_ALERT_CONF: /* plci */
1240 if (cmsg->Info) {
1241 printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for plci 0x%x\n",
1242 card->contrnr,
1243 capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1244 cmsg->Info, capi_info2str(cmsg->Info),
1245 cmsg->adr.adrPLCI);
1246 }
1247 break;
1248
1249 case CAPI_CONNECT_IND: /* plci */
1250 handle_incoming_call(card, cmsg);
1251 break;
1252
1253 case CAPI_CONNECT_CONF: /* plci */
1254 if (cmsg->Info) {
1255 printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for plci 0x%x\n",
1256 card->contrnr,
1257 capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1258 cmsg->Info, capi_info2str(cmsg->Info),
1259 cmsg->adr.adrPLCI);
1260 }
1261 if (!(plcip = find_plci_by_msgid(card, cmsg->Messagenumber)))
1262 goto notfound;
1263
1264 plcip->plci = cmsg->adr.adrPLCI;
1265 if (cmsg->Info) {
1266 plci_change_state(card, plcip, EV_PLCI_CONNECT_CONF_ERROR);
1267 } else {
1268 plci_change_state(card, plcip, EV_PLCI_CONNECT_CONF_OK);
1269 }
1270 break;
1271
1272 case CAPI_CONNECT_ACTIVE_IND: /* plci */
1273
1274 if (!(plcip = find_plci_by_plci(card, cmsg->adr.adrPLCI)))
1275 goto notfound;
1276
1277 if (card->bchans[plcip->chan].incoming) {
1278 capi_cmsg_answer(cmsg);
1279 plci_change_state(card, plcip, EV_PLCI_CONNECT_ACTIVE_IND);
1280 send_message(card, cmsg);
1281 } else {
1282 capidrv_ncci *nccip;
1283 capi_cmsg_answer(cmsg);
1284 send_message(card, cmsg);
1285
1286 nccip = new_ncci(card, plcip, cmsg->adr.adrPLCI);
1287
1288 if (!nccip) {
1289 printk(KERN_ERR "capidrv-%d: no mem for ncci, sorry\n", card->contrnr);
1290 break; /* $$$$ */
1291 }
1292 capi_fill_CONNECT_B3_REQ(cmsg,
1293 global.ap.applid,
1294 card->msgid++,
1295 plcip->plci, /* adr */
1296 NULL /* NCPI */
1297 );
1298 nccip->msgid = cmsg->Messagenumber;
1299 plci_change_state(card, plcip,
1300 EV_PLCI_CONNECT_ACTIVE_IND);
1301 ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_REQ);
1302 send_message(card, cmsg);
1303 cmd.command = ISDN_STAT_DCONN;
1304 cmd.driver = card->myid;
1305 cmd.arg = plcip->chan;
1306 card->interface.statcallb(&cmd);
1307 }
1308 break;
1309
1310 case CAPI_INFO_IND: /* Controller/plci */
1311
1312 if (!(plcip = find_plci_by_plci(card, cmsg->adr.adrPLCI)))
1313 goto notfound;
1314
1315 if (cmsg->InfoNumber == 0x4000) {
1316 if (cmsg->InfoElement[0] == 4) {
1317 cmd.command = ISDN_STAT_CINF;
1318 cmd.driver = card->myid;
1319 cmd.arg = plcip->chan;
1320 sprintf(cmd.parm.num, "%lu",
1321 (unsigned long)
1322 ((u32) cmsg->InfoElement[1]
1323 | ((u32) (cmsg->InfoElement[2]) << 8)
1324 | ((u32) (cmsg->InfoElement[3]) << 16)
1325 | ((u32) (cmsg->InfoElement[4]) << 24)));
1326 card->interface.statcallb(&cmd);
1327 break;
1328 }
1329 }
1330 cdb = capi_cmsg2str(cmsg);
1331 if (cdb) {
1332 printk(KERN_WARNING "capidrv-%d: %s\n",
1333 card->contrnr, cdb->buf);
1334 cdebbuf_free(cdb);
1335 } else
1336 printk(KERN_WARNING "capidrv-%d: CAPI_INFO_IND InfoNumber %x not handled\n",
1337 card->contrnr, cmsg->InfoNumber);
1338
1339 break;
1340
1341 case CAPI_CONNECT_ACTIVE_CONF: /* plci */
1342 goto ignored;
1343 case CAPI_SELECT_B_PROTOCOL_CONF: /* plci */
1344 goto ignored;
1345 case CAPI_FACILITY_IND: /* Controller/plci/ncci */
1346 goto ignored;
1347 case CAPI_FACILITY_CONF: /* Controller/plci/ncci */
1348 goto ignored;
1349
1350 case CAPI_INFO_CONF: /* Controller/plci */
1351 goto ignored;
1352
1353 default:
1354 printk(KERN_ERR "capidrv-%d: got %s for plci 0x%x ???",
1355 card->contrnr,
1356 capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1357 cmsg->adr.adrPLCI);
1358 }
1359 return;
1360ignored:
1361 printk(KERN_INFO "capidrv-%d: %s for plci 0x%x ignored\n",
1362 card->contrnr,
1363 capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1364 cmsg->adr.adrPLCI);
1365 return;
1366notfound:
1367 printk(KERN_ERR "capidrv-%d: %s: plci 0x%x not found\n",
1368 card->contrnr,
1369 capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1370 cmsg->adr.adrPLCI);
1371 return;
1372}
1373
1374static void handle_ncci(_cmsg *cmsg)
1375{
1376 capidrv_contr *card = findcontrbynumber(cmsg->adr.adrController & 0x7f);
1377 capidrv_plci *plcip;
1378 capidrv_ncci *nccip;
1379 isdn_ctrl cmd;
1380 int len;
1381
1382 if (!card) {
1383 printk(KERN_ERR "capidrv: %s from unknown controller 0x%x\n",
1384 capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1385 cmsg->adr.adrController & 0x7f);
1386 return;
1387 }
1388 switch (CAPICMD(cmsg->Command, cmsg->Subcommand)) {
1389
1390 case CAPI_CONNECT_B3_ACTIVE_IND: /* ncci */
1391 if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI)))
1392 goto notfound;
1393
1394 capi_cmsg_answer(cmsg);
1395 ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_ACTIVE_IND);
1396 send_message(card, cmsg);
1397
1398 cmd.command = ISDN_STAT_BCONN;
1399 cmd.driver = card->myid;
1400 cmd.arg = nccip->chan;
1401 card->interface.statcallb(&cmd);
1402
1403 printk(KERN_INFO "capidrv-%d: chan %d up with ncci 0x%x\n",
1404 card->contrnr, nccip->chan, nccip->ncci);
1405 break;
1406
1407 case CAPI_CONNECT_B3_ACTIVE_CONF: /* ncci */
1408 goto ignored;
1409
1410 case CAPI_CONNECT_B3_IND: /* ncci */
1411
1412 plcip = find_plci_by_ncci(card, cmsg->adr.adrNCCI);
1413 if (plcip) {
1414 nccip = new_ncci(card, plcip, cmsg->adr.adrNCCI);
1415 if (nccip) {
1416 ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_IND);
1417 capi_fill_CONNECT_B3_RESP(cmsg,
1418 global.ap.applid,
1419 card->msgid++,
1420 nccip->ncci, /* adr */
1421 0, /* Reject */
1422 NULL /* NCPI */
1423 );
1424 ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_RESP);
1425 send_message(card, cmsg);
1426 break;
1427 }
1428 printk(KERN_ERR "capidrv-%d: no mem for ncci, sorry\n", card->contrnr);
1429 } else {
1430 printk(KERN_ERR "capidrv-%d: %s: plci for ncci 0x%x not found\n",
1431 card->contrnr,
1432 capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1433 cmsg->adr.adrNCCI);
1434 }
1435 capi_fill_CONNECT_B3_RESP(cmsg,
1436 global.ap.applid,
1437 card->msgid++,
1438 cmsg->adr.adrNCCI,
1439 2, /* Reject */
1440 NULL /* NCPI */
1441 );
1442 send_message(card, cmsg);
1443 break;
1444
1445 case CAPI_CONNECT_B3_CONF: /* ncci */
1446
1447 if (!(nccip = find_ncci_by_msgid(card,
1448 cmsg->adr.adrNCCI,
1449 cmsg->Messagenumber)))
1450 goto notfound;
1451
1452 nccip->ncci = cmsg->adr.adrNCCI;
1453 if (cmsg->Info) {
1454 printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for ncci 0x%x\n",
1455 card->contrnr,
1456 capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1457 cmsg->Info, capi_info2str(cmsg->Info),
1458 cmsg->adr.adrNCCI);
1459 }
1460
1461 if (cmsg->Info)
1462 ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_CONF_ERROR);
1463 else
1464 ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_CONF_OK);
1465 break;
1466
1467 case CAPI_CONNECT_B3_T90_ACTIVE_IND: /* ncci */
1468 capi_cmsg_answer(cmsg);
1469 send_message(card, cmsg);
1470 break;
1471
1472 case CAPI_DATA_B3_IND: /* ncci */
1473 /* handled in handle_data() */
1474 goto ignored;
1475
1476 case CAPI_DATA_B3_CONF: /* ncci */
1477 if (cmsg->Info) {
1478 printk(KERN_WARNING "CAPI_DATA_B3_CONF: Info %x - %s\n",
1479 cmsg->Info, capi_info2str(cmsg->Info));
1480 }
1481 if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI)))
1482 goto notfound;
1483
1484 len = capidrv_del_ack(nccip, cmsg->DataHandle);
1485 if (len < 0)
1486 break;
1487 cmd.command = ISDN_STAT_BSENT;
1488 cmd.driver = card->myid;
1489 cmd.arg = nccip->chan;
1490 cmd.parm.length = len;
1491 card->interface.statcallb(&cmd);
1492 break;
1493
1494 case CAPI_DISCONNECT_B3_IND: /* ncci */
1495 if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI)))
1496 goto notfound;
1497
1498 card->bchans[nccip->chan].disconnecting = 1;
1499 ncci_change_state(card, nccip, EV_NCCI_DISCONNECT_B3_IND);
1500 capi_cmsg_answer(cmsg);
1501 ncci_change_state(card, nccip, EV_NCCI_DISCONNECT_B3_RESP);
1502 send_message(card, cmsg);
1503 break;
1504
1505 case CAPI_DISCONNECT_B3_CONF: /* ncci */
1506 if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI)))
1507 goto notfound;
1508 if (cmsg->Info) {
1509 printk(KERN_INFO "capidrv-%d: %s info 0x%x (%s) for ncci 0x%x\n",
1510 card->contrnr,
1511 capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1512 cmsg->Info, capi_info2str(cmsg->Info),
1513 cmsg->adr.adrNCCI);
1514 ncci_change_state(card, nccip, EV_NCCI_DISCONNECT_B3_CONF_ERROR);
1515 }
1516 break;
1517
1518 case CAPI_RESET_B3_IND: /* ncci */
1519 if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI)))
1520 goto notfound;
1521 ncci_change_state(card, nccip, EV_NCCI_RESET_B3_IND);
1522 capi_cmsg_answer(cmsg);
1523 send_message(card, cmsg);
1524 break;
1525
1526 case CAPI_RESET_B3_CONF: /* ncci */
1527 goto ignored; /* $$$$ */
1528
1529 case CAPI_FACILITY_IND: /* Controller/plci/ncci */
1530 goto ignored;
1531 case CAPI_FACILITY_CONF: /* Controller/plci/ncci */
1532 goto ignored;
1533
1534 default:
1535 printk(KERN_ERR "capidrv-%d: got %s for ncci 0x%x ???",
1536 card->contrnr,
1537 capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1538 cmsg->adr.adrNCCI);
1539 }
1540 return;
1541ignored:
1542 printk(KERN_INFO "capidrv-%d: %s for ncci 0x%x ignored\n",
1543 card->contrnr,
1544 capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1545 cmsg->adr.adrNCCI);
1546 return;
1547notfound:
1548 printk(KERN_ERR "capidrv-%d: %s: ncci 0x%x not found\n",
1549 card->contrnr,
1550 capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1551 cmsg->adr.adrNCCI);
1552}
1553
1554
1555static void handle_data(_cmsg *cmsg, struct sk_buff *skb)
1556{
1557 capidrv_contr *card = findcontrbynumber(cmsg->adr.adrController & 0x7f);
1558 capidrv_ncci *nccip;
1559
1560 if (!card) {
1561 printk(KERN_ERR "capidrv: %s from unknown controller 0x%x\n",
1562 capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1563 cmsg->adr.adrController & 0x7f);
1564 kfree_skb(skb);
1565 return;
1566 }
1567 if (!(nccip = find_ncci(card, cmsg->adr.adrNCCI))) {
1568 printk(KERN_ERR "capidrv-%d: %s: ncci 0x%x not found\n",
1569 card->contrnr,
1570 capi_cmd2str(cmsg->Command, cmsg->Subcommand),
1571 cmsg->adr.adrNCCI);
1572 kfree_skb(skb);
1573 return;
1574 }
1575 (void) skb_pull(skb, CAPIMSG_LEN(skb->data));
1576 card->interface.rcvcallb_skb(card->myid, nccip->chan, skb);
1577 capi_cmsg_answer(cmsg);
1578 send_message(card, cmsg);
1579}
1580
1581static _cmsg s_cmsg;
1582
1583static void capidrv_recv_message(struct capi20_appl *ap, struct sk_buff *skb)
1584{
1585 if (capi_message2cmsg(&s_cmsg, skb->data)) {
1586 printk(KERN_ERR "capidrv: applid=%d: received invalid message\n",
1587 ap->applid);
1588 kfree_skb(skb);
1589 return;
1590 }
1591 if (debugmode > 3) {
1592 _cdebbuf *cdb = capi_cmsg2str(&s_cmsg);
1593
1594 if (cdb) {
1595 printk(KERN_DEBUG "%s: applid=%d %s\n", __func__,
1596 ap->applid, cdb->buf);
1597 cdebbuf_free(cdb);
1598 } else
1599 printk(KERN_DEBUG "%s: applid=%d %s not traced\n",
1600 __func__, ap->applid,
1601 capi_cmd2str(s_cmsg.Command, s_cmsg.Subcommand));
1602 }
1603 if (s_cmsg.Command == CAPI_DATA_B3
1604 && s_cmsg.Subcommand == CAPI_IND) {
1605 handle_data(&s_cmsg, skb);
1606 return;
1607 }
1608 if ((s_cmsg.adr.adrController & 0xffffff00) == 0)
1609 handle_controller(&s_cmsg);
1610 else if ((s_cmsg.adr.adrPLCI & 0xffff0000) == 0)
1611 handle_plci(&s_cmsg);
1612 else
1613 handle_ncci(&s_cmsg);
1614 /*
1615 * data of skb used in s_cmsg,
1616 * free data when s_cmsg is not used again
1617 * thanks to Lars Heete <hel@admin.de>
1618 */
1619 kfree_skb(skb);
1620}
1621
1622/* ------------------------------------------------------------------- */
1623
1624#define PUTBYTE_TO_STATUS(card, byte) \
1625 do { \
1626 *(card)->q931_write++ = (byte); \
1627 if ((card)->q931_write > (card)->q931_end) \
1628 (card)->q931_write = (card)->q931_buf; \
1629 } while (0)
1630
1631static void handle_dtrace_data(capidrv_contr *card,
1632 int send, int level2, u8 *data, u16 len)
1633{
1634 u8 *p, *end;
1635 isdn_ctrl cmd;
1636
1637 if (!len) {
1638 printk(KERN_DEBUG "capidrv-%d: avmb1_q931_data: len == %d\n",
1639 card->contrnr, len);
1640 return;
1641 }
1642
1643 if (level2) {
1644 PUTBYTE_TO_STATUS(card, 'D');
1645 PUTBYTE_TO_STATUS(card, '2');
1646 PUTBYTE_TO_STATUS(card, send ? '>' : '<');
1647 PUTBYTE_TO_STATUS(card, ':');
1648 } else {
1649 PUTBYTE_TO_STATUS(card, 'D');
1650 PUTBYTE_TO_STATUS(card, '3');
1651 PUTBYTE_TO_STATUS(card, send ? '>' : '<');
1652 PUTBYTE_TO_STATUS(card, ':');
1653 }
1654
1655 for (p = data, end = data + len; p < end; p++) {
1656 PUTBYTE_TO_STATUS(card, ' ');
1657 PUTBYTE_TO_STATUS(card, hex_asc_hi(*p));
1658 PUTBYTE_TO_STATUS(card, hex_asc_lo(*p));
1659 }
1660 PUTBYTE_TO_STATUS(card, '\n');
1661
1662 cmd.command = ISDN_STAT_STAVAIL;
1663 cmd.driver = card->myid;
1664 cmd.arg = len * 3 + 5;
1665 card->interface.statcallb(&cmd);
1666}
1667
1668/* ------------------------------------------------------------------- */
1669
1670static _cmsg cmdcmsg;
1671
1672static int capidrv_ioctl(isdn_ctrl *c, capidrv_contr *card)
1673{
1674 switch (c->arg) {
1675 case 1:
1676 debugmode = (int)(*((unsigned int *)c->parm.num));
1677 printk(KERN_DEBUG "capidrv-%d: debugmode=%d\n",
1678 card->contrnr, debugmode);
1679 return 0;
1680 default:
1681 printk(KERN_DEBUG "capidrv-%d: capidrv_ioctl(%ld) called ??\n",
1682 card->contrnr, c->arg);
1683 return -EINVAL;
1684 }
1685 return -EINVAL;
1686}
1687
1688/*
1689 * Handle leased lines (CAPI-Bundling)
1690 */
1691
1692struct internal_bchannelinfo {
1693 unsigned short channelalloc;
1694 unsigned short operation;
1695 unsigned char cmask[31];
1696};
1697
1698static int decodeFVteln(char *teln, unsigned long *bmaskp, int *activep)
1699{
1700 unsigned long bmask = 0;
1701 int active = !0;
1702 char *s;
1703 int i;
1704
1705 if (strncmp(teln, "FV:", 3) != 0)
1706 return 1;
1707 s = teln + 3;
1708 while (*s && *s == ' ') s++;
1709 if (!*s) return -2;
1710 if (*s == 'p' || *s == 'P') {
1711 active = 0;
1712 s++;
1713 }
1714 if (*s == 'a' || *s == 'A') {
1715 active = !0;
1716 s++;
1717 }
1718 while (*s) {
1719 int digit1 = 0;
1720 int digit2 = 0;
1721 char *endp;
1722
1723 digit1 = simple_strtoul(s, &endp, 10);
1724 if (s == endp)
1725 return -3;
1726 s = endp;
1727
1728 if (digit1 <= 0 || digit1 > 30) return -4;
1729 if (*s == 0 || *s == ',' || *s == ' ') {
1730 bmask |= (1 << digit1);
1731 digit1 = 0;
1732 if (*s) s++;
1733 continue;
1734 }
1735 if (*s != '-') return -5;
1736 s++;
1737
1738 digit2 = simple_strtoul(s, &endp, 10);
1739 if (s == endp)
1740 return -3;
1741 s = endp;
1742
1743 if (digit2 <= 0 || digit2 > 30) return -4;
1744 if (*s == 0 || *s == ',' || *s == ' ') {
1745 if (digit1 > digit2)
1746 for (i = digit2; i <= digit1; i++)
1747 bmask |= (1 << i);
1748 else
1749 for (i = digit1; i <= digit2; i++)
1750 bmask |= (1 << i);
1751 digit1 = digit2 = 0;
1752 if (*s) s++;
1753 continue;
1754 }
1755 return -6;
1756 }
1757 if (activep) *activep = active;
1758 if (bmaskp) *bmaskp = bmask;
1759 return 0;
1760}
1761
1762static int FVteln2capi20(char *teln, u8 AdditionalInfo[1 + 2 + 2 + 31])
1763{
1764 unsigned long bmask;
1765 int active;
1766 int rc, i;
1767
1768 rc = decodeFVteln(teln, &bmask, &active);
1769 if (rc) return rc;
1770 /* Length */
1771 AdditionalInfo[0] = 2 + 2 + 31;
1772 /* Channel: 3 => use channel allocation */
1773 AdditionalInfo[1] = 3; AdditionalInfo[2] = 0;
1774 /* Operation: 0 => DTE mode, 1 => DCE mode */
1775 if (active) {
1776 AdditionalInfo[3] = 0; AdditionalInfo[4] = 0;
1777 } else {
1778 AdditionalInfo[3] = 1; AdditionalInfo[4] = 0;
1779 }
1780 /* Channel mask array */
1781 AdditionalInfo[5] = 0; /* no D-Channel */
1782 for (i = 1; i <= 30; i++)
1783 AdditionalInfo[5 + i] = (bmask & (1 << i)) ? 0xff : 0;
1784 return 0;
1785}
1786
1787static int capidrv_command(isdn_ctrl *c, capidrv_contr *card)
1788{
1789 isdn_ctrl cmd;
1790 struct capidrv_bchan *bchan;
1791 struct capidrv_plci *plcip;
1792 u8 AdditionalInfo[1 + 2 + 2 + 31];
1793 int rc, isleasedline = 0;
1794
1795 if (c->command == ISDN_CMD_IOCTL)
1796 return capidrv_ioctl(c, card);
1797
1798 switch (c->command) {
1799 case ISDN_CMD_DIAL: {
1800 u8 calling[ISDN_MSNLEN + 3];
1801 u8 called[ISDN_MSNLEN + 2];
1802
1803 if (debugmode)
1804 printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_DIAL(ch=%ld,\"%s,%d,%d,%s\")\n",
1805 card->contrnr,
1806 c->arg,
1807 c->parm.setup.phone,
1808 c->parm.setup.si1,
1809 c->parm.setup.si2,
1810 c->parm.setup.eazmsn);
1811
1812 bchan = &card->bchans[c->arg % card->nbchan];
1813
1814 if (bchan->plcip) {
1815 printk(KERN_ERR "capidrv-%d: dail ch=%ld,\"%s,%d,%d,%s\" in use (plci=0x%x)\n",
1816 card->contrnr,
1817 c->arg,
1818 c->parm.setup.phone,
1819 c->parm.setup.si1,
1820 c->parm.setup.si2,
1821 c->parm.setup.eazmsn,
1822 bchan->plcip->plci);
1823 return 0;
1824 }
1825 bchan->si1 = c->parm.setup.si1;
1826 bchan->si2 = c->parm.setup.si2;
1827
1828 strncpy(bchan->num, c->parm.setup.phone, sizeof(bchan->num));
1829 strncpy(bchan->mynum, c->parm.setup.eazmsn, sizeof(bchan->mynum));
1830 rc = FVteln2capi20(bchan->num, AdditionalInfo);
1831 isleasedline = (rc == 0);
1832 if (rc < 0)
1833 printk(KERN_ERR "capidrv-%d: WARNING: invalid leased linedefinition \"%s\"\n", card->contrnr, bchan->num);
1834
1835 if (isleasedline) {
1836 calling[0] = 0;
1837 called[0] = 0;
1838 if (debugmode)
1839 printk(KERN_DEBUG "capidrv-%d: connecting leased line\n", card->contrnr);
1840 } else {
1841 calling[0] = strlen(bchan->mynum) + 2;
1842 calling[1] = 0;
1843 calling[2] = 0x80;
1844 strncpy(calling + 3, bchan->mynum, ISDN_MSNLEN);
1845 called[0] = strlen(bchan->num) + 1;
1846 called[1] = 0x80;
1847 strncpy(called + 2, bchan->num, ISDN_MSNLEN);
1848 }
1849
1850 capi_fill_CONNECT_REQ(&cmdcmsg,
1851 global.ap.applid,
1852 card->msgid++,
1853 card->contrnr, /* adr */
1854 si2cip(bchan->si1, bchan->si2), /* cipvalue */
1855 called, /* CalledPartyNumber */
1856 calling, /* CallingPartyNumber */
1857 NULL, /* CalledPartySubaddress */
1858 NULL, /* CallingPartySubaddress */
1859 b1prot(bchan->l2, bchan->l3), /* B1protocol */
1860 b2prot(bchan->l2, bchan->l3), /* B2protocol */
1861 b3prot(bchan->l2, bchan->l3), /* B3protocol */
1862 b1config(bchan->l2, bchan->l3), /* B1configuration */
1863 NULL, /* B2configuration */
1864 NULL, /* B3configuration */
1865 NULL, /* BC */
1866 NULL, /* LLC */
1867 NULL, /* HLC */
1868 /* BChannelinformation */
1869 isleasedline ? AdditionalInfo : NULL,
1870 NULL, /* Keypadfacility */
1871 NULL, /* Useruserdata */
1872 NULL /* Facilitydataarray */
1873 );
1874 if ((plcip = new_plci(card, (c->arg % card->nbchan))) == NULL) {
1875 cmd.command = ISDN_STAT_DHUP;
1876 cmd.driver = card->myid;
1877 cmd.arg = (c->arg % card->nbchan);
1878 card->interface.statcallb(&cmd);
1879 return -1;
1880 }
1881 plcip->msgid = cmdcmsg.Messagenumber;
1882 plcip->leasedline = isleasedline;
1883 plci_change_state(card, plcip, EV_PLCI_CONNECT_REQ);
1884 send_message(card, &cmdcmsg);
1885 return 0;
1886 }
1887
1888 case ISDN_CMD_ACCEPTD:
1889
1890 bchan = &card->bchans[c->arg % card->nbchan];
1891 if (debugmode)
1892 printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_ACCEPTD(ch=%ld) l2=%d l3=%d\n",
1893 card->contrnr,
1894 c->arg, bchan->l2, bchan->l3);
1895
1896 capi_fill_CONNECT_RESP(&cmdcmsg,
1897 global.ap.applid,
1898 card->msgid++,
1899 bchan->plcip->plci, /* adr */
1900 0, /* Reject */
1901 b1prot(bchan->l2, bchan->l3), /* B1protocol */
1902 b2prot(bchan->l2, bchan->l3), /* B2protocol */
1903 b3prot(bchan->l2, bchan->l3), /* B3protocol */
1904 b1config(bchan->l2, bchan->l3), /* B1configuration */
1905 NULL, /* B2configuration */
1906 NULL, /* B3configuration */
1907 NULL, /* ConnectedNumber */
1908 NULL, /* ConnectedSubaddress */
1909 NULL, /* LLC */
1910 NULL, /* BChannelinformation */
1911 NULL, /* Keypadfacility */
1912 NULL, /* Useruserdata */
1913 NULL /* Facilitydataarray */
1914 );
1915 if (capi_cmsg2message(&cmdcmsg, cmdcmsg.buf)) {
1916 printk(KERN_ERR "capidrv-%d: capidrv_command: parser failure\n",
1917 card->contrnr);
1918 return -EINVAL;
1919 }
1920 plci_change_state(card, bchan->plcip, EV_PLCI_CONNECT_RESP);
1921 send_message(card, &cmdcmsg);
1922 return 0;
1923
1924 case ISDN_CMD_ACCEPTB:
1925 if (debugmode)
1926 printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_ACCEPTB(ch=%ld)\n",
1927 card->contrnr,
1928 c->arg);
1929 return -ENOSYS;
1930
1931 case ISDN_CMD_HANGUP:
1932 if (debugmode)
1933 printk(KERN_DEBUG "capidrv-%d: ISDN_CMD_HANGUP(ch=%ld)\n",
1934 card->contrnr,
1935 c->arg);
1936 bchan = &card->bchans[c->arg % card->nbchan];
1937
1938 if (bchan->disconnecting) {
1939 if (debugmode)
1940 printk(KERN_DEBUG "capidrv-%d: chan %ld already disconnecting ...\n",
1941 card->contrnr,
1942 c->arg);
1943 return 0;
1944 }
1945 if (bchan->nccip) {
1946 bchan->disconnecting = 1;
1947 capi_fill_DISCONNECT_B3_REQ(&cmdcmsg,
1948 global.ap.applid,
1949 card->msgid++,
1950 bchan->nccip->ncci,
1951 NULL /* NCPI */
1952 );
1953 ncci_change_state(card, bchan->nccip, EV_NCCI_DISCONNECT_B3_REQ);
1954 send_message(card, &cmdcmsg);
1955 return 0;
1956 } else if (bchan->plcip) {
1957 if (bchan->plcip->state == ST_PLCI_INCOMING) {
1958 /*
1959 * just ignore, we a called from
1960 * isdn_status_callback(),
1961 * which will return 0 or 2, this is handled
1962 * by the CONNECT_IND handler
1963 */
1964 bchan->disconnecting = 1;
1965 return 0;
1966 } else if (bchan->plcip->plci) {
1967 bchan->disconnecting = 1;
1968 capi_fill_DISCONNECT_REQ(&cmdcmsg,
1969 global.ap.applid,
1970 card->msgid++,
1971 bchan->plcip->plci,
1972 NULL, /* BChannelinformation */
1973 NULL, /* Keypadfacility */
1974 NULL, /* Useruserdata */
1975 NULL /* Facilitydataarray */
1976 );
1977 plci_change_state(card, bchan->plcip, EV_PLCI_DISCONNECT_REQ);
1978 send_message(card, &cmdcmsg);
1979 return 0;
1980 } else {
1981 printk(KERN_ERR "capidrv-%d: chan %ld disconnect request while waiting for CONNECT_CONF\n",
1982 card->contrnr,
1983 c->arg);
1984 return -EINVAL;
1985 }
1986 }
1987 printk(KERN_ERR "capidrv-%d: chan %ld disconnect request on free channel\n",
1988 card->contrnr,
1989 c->arg);
1990 return -EINVAL;
1991/* ready */
1992
1993 case ISDN_CMD_SETL2:
1994 if (debugmode)
1995 printk(KERN_DEBUG "capidrv-%d: set L2 on chan %ld to %ld\n",
1996 card->contrnr,
1997 (c->arg & 0xff), (c->arg >> 8));
1998 bchan = &card->bchans[(c->arg & 0xff) % card->nbchan];
1999 bchan->l2 = (c->arg >> 8);
2000 return 0;
2001
2002 case ISDN_CMD_SETL3:
2003 if (debugmode)
2004 printk(KERN_DEBUG "capidrv-%d: set L3 on chan %ld to %ld\n",
2005 card->contrnr,
2006 (c->arg & 0xff), (c->arg >> 8));
2007 bchan = &card->bchans[(c->arg & 0xff) % card->nbchan];
2008 bchan->l3 = (c->arg >> 8);
2009 return 0;
2010
2011 case ISDN_CMD_SETEAZ:
2012 if (debugmode)
2013 printk(KERN_DEBUG "capidrv-%d: set EAZ \"%s\" on chan %ld\n",
2014 card->contrnr,
2015 c->parm.num, c->arg);
2016 bchan = &card->bchans[c->arg % card->nbchan];
2017 strncpy(bchan->msn, c->parm.num, ISDN_MSNLEN);
2018 return 0;
2019
2020 case ISDN_CMD_CLREAZ:
2021 if (debugmode)
2022 printk(KERN_DEBUG "capidrv-%d: clearing EAZ on chan %ld\n",
2023 card->contrnr, c->arg);
2024 bchan = &card->bchans[c->arg % card->nbchan];
2025 bchan->msn[0] = 0;
2026 return 0;
2027
2028 default:
2029 printk(KERN_ERR "capidrv-%d: ISDN_CMD_%d, Huh?\n",
2030 card->contrnr, c->command);
2031 return -EINVAL;
2032 }
2033 return 0;
2034}
2035
2036static int if_command(isdn_ctrl *c)
2037{
2038 capidrv_contr *card = findcontrbydriverid(c->driver);
2039
2040 if (card)
2041 return capidrv_command(c, card);
2042
2043 printk(KERN_ERR
2044 "capidrv: if_command %d called with invalid driverId %d!\n",
2045 c->command, c->driver);
2046 return -ENODEV;
2047}
2048
2049static _cmsg sendcmsg;
2050
2051static int if_sendbuf(int id, int channel, int doack, struct sk_buff *skb)
2052{
2053 capidrv_contr *card = findcontrbydriverid(id);
2054 capidrv_bchan *bchan;
2055 capidrv_ncci *nccip;
2056 int len = skb->len;
2057 int msglen;
2058 u16 errcode;
2059 u16 datahandle;
2060 u32 data;
2061
2062 if (!card) {
2063 printk(KERN_ERR "capidrv: if_sendbuf called with invalid driverId %d!\n",
2064 id);
2065 return 0;
2066 }
2067 if (debugmode > 4)
2068 printk(KERN_DEBUG "capidrv-%d: sendbuf len=%d skb=%p doack=%d\n",
2069 card->contrnr, len, skb, doack);
2070 bchan = &card->bchans[channel % card->nbchan];
2071 nccip = bchan->nccip;
2072 if (!nccip || nccip->state != ST_NCCI_ACTIVE) {
2073 printk(KERN_ERR "capidrv-%d: if_sendbuf: %s:%d: chan not up!\n",
2074 card->contrnr, card->name, channel);
2075 return 0;
2076 }
2077 datahandle = nccip->datahandle;
2078
2079 /*
2080 * Here we copy pointer skb->data into the 32-bit 'Data' field.
2081 * The 'Data' field is not used in practice in linux kernel
2082 * (neither in 32 or 64 bit), but should have some value,
2083 * since a CAPI message trace will display it.
2084 *
2085 * The correct value in the 32 bit case is the address of the
2086 * data, in 64 bit it makes no sense, we use 0 there.
2087 */
2088
2089#ifdef CONFIG_64BIT
2090 data = 0;
2091#else
2092 data = (unsigned long) skb->data;
2093#endif
2094
2095 capi_fill_DATA_B3_REQ(&sendcmsg, global.ap.applid, card->msgid++,
2096 nccip->ncci, /* adr */
2097 data, /* Data */
2098 skb->len, /* DataLength */
2099 datahandle, /* DataHandle */
2100 0 /* Flags */
2101 );
2102
2103 if (capidrv_add_ack(nccip, datahandle, doack ? (int)skb->len : -1) < 0)
2104 return 0;
2105
2106 if (capi_cmsg2message(&sendcmsg, sendcmsg.buf)) {
2107 printk(KERN_ERR "capidrv-%d: if_sendbuf: parser failure\n",
2108 card->contrnr);
2109 return -EINVAL;
2110 }
2111 msglen = CAPIMSG_LEN(sendcmsg.buf);
2112 if (skb_headroom(skb) < msglen) {
2113 struct sk_buff *nskb = skb_realloc_headroom(skb, msglen);
2114 if (!nskb) {
2115 printk(KERN_ERR "capidrv-%d: if_sendbuf: no memory\n",
2116 card->contrnr);
2117 (void)capidrv_del_ack(nccip, datahandle);
2118 return 0;
2119 }
2120 printk(KERN_DEBUG "capidrv-%d: only %d bytes headroom, need %d\n",
2121 card->contrnr, skb_headroom(skb), msglen);
2122 memcpy(skb_push(nskb, msglen), sendcmsg.buf, msglen);
2123 errcode = capi20_put_message(&global.ap, nskb);
2124 if (errcode == CAPI_NOERROR) {
2125 dev_kfree_skb(skb);
2126 nccip->datahandle++;
2127 return len;
2128 }
2129 if (debugmode > 3)
2130 printk(KERN_DEBUG "capidrv-%d: sendbuf putmsg ret(%x) - %s\n",
2131 card->contrnr, errcode, capi_info2str(errcode));
2132 (void)capidrv_del_ack(nccip, datahandle);
2133 dev_kfree_skb(nskb);
2134 return errcode == CAPI_SENDQUEUEFULL ? 0 : -1;
2135 } else {
2136 memcpy(skb_push(skb, msglen), sendcmsg.buf, msglen);
2137 errcode = capi20_put_message(&global.ap, skb);
2138 if (errcode == CAPI_NOERROR) {
2139 nccip->datahandle++;
2140 return len;
2141 }
2142 if (debugmode > 3)
2143 printk(KERN_DEBUG "capidrv-%d: sendbuf putmsg ret(%x) - %s\n",
2144 card->contrnr, errcode, capi_info2str(errcode));
2145 skb_pull(skb, msglen);
2146 (void)capidrv_del_ack(nccip, datahandle);
2147 return errcode == CAPI_SENDQUEUEFULL ? 0 : -1;
2148 }
2149}
2150
2151static int if_readstat(u8 __user *buf, int len, int id, int channel)
2152{
2153 capidrv_contr *card = findcontrbydriverid(id);
2154 int count;
2155 u8 __user *p;
2156
2157 if (!card) {
2158 printk(KERN_ERR "capidrv: if_readstat called with invalid driverId %d!\n",
2159 id);
2160 return -ENODEV;
2161 }
2162
2163 for (p = buf, count = 0; count < len; p++, count++) {
2164 if (put_user(*card->q931_read++, p))
2165 return -EFAULT;
2166 if (card->q931_read > card->q931_end)
2167 card->q931_read = card->q931_buf;
2168 }
2169 return count;
2170
2171}
2172
2173static void enable_dchannel_trace(capidrv_contr *card)
2174{
2175 u8 manufacturer[CAPI_MANUFACTURER_LEN];
2176 capi_version version;
2177 u16 contr = card->contrnr;
2178 u16 errcode;
2179 u16 avmversion[3];
2180
2181 errcode = capi20_get_manufacturer(contr, manufacturer);
2182 if (errcode != CAPI_NOERROR) {
2183 printk(KERN_ERR "%s: can't get manufacturer (0x%x)\n",
2184 card->name, errcode);
2185 return;
2186 }
2187 if (strstr(manufacturer, "AVM") == NULL) {
2188 printk(KERN_ERR "%s: not from AVM, no d-channel trace possible (%s)\n",
2189 card->name, manufacturer);
2190 return;
2191 }
2192 errcode = capi20_get_version(contr, &version);
2193 if (errcode != CAPI_NOERROR) {
2194 printk(KERN_ERR "%s: can't get version (0x%x)\n",
2195 card->name, errcode);
2196 return;
2197 }
2198 avmversion[0] = (version.majormanuversion >> 4) & 0x0f;
2199 avmversion[1] = (version.majormanuversion << 4) & 0xf0;
2200 avmversion[1] |= (version.minormanuversion >> 4) & 0x0f;
2201 avmversion[2] |= version.minormanuversion & 0x0f;
2202
2203 if (avmversion[0] > 3 || (avmversion[0] == 3 && avmversion[1] > 5)) {
2204 printk(KERN_INFO "%s: D2 trace enabled\n", card->name);
2205 capi_fill_MANUFACTURER_REQ(&cmdcmsg, global.ap.applid,
2206 card->msgid++,
2207 contr,
2208 0x214D5641, /* ManuID */
2209 0, /* Class */
2210 1, /* Function */
2211 (_cstruct)"\004\200\014\000\000");
2212 } else {
2213 printk(KERN_INFO "%s: D3 trace enabled\n", card->name);
2214 capi_fill_MANUFACTURER_REQ(&cmdcmsg, global.ap.applid,
2215 card->msgid++,
2216 contr,
2217 0x214D5641, /* ManuID */
2218 0, /* Class */
2219 1, /* Function */
2220 (_cstruct)"\004\002\003\000\000");
2221 }
2222 send_message(card, &cmdcmsg);
2223}
2224
2225
2226static void send_listen(capidrv_contr *card)
2227{
2228 capi_fill_LISTEN_REQ(&cmdcmsg, global.ap.applid,
2229 card->msgid++,
2230 card->contrnr, /* controller */
2231 1 << 6, /* Infomask */
2232 card->cipmask,
2233 card->cipmask2,
2234 NULL, NULL);
2235 listen_change_state(card, EV_LISTEN_REQ);
2236 send_message(card, &cmdcmsg);
2237}
2238
2239static void listentimerfunc(struct timer_list *t)
2240{
2241 capidrv_contr *card = from_timer(card, t, listentimer);
2242 if (card->state != ST_LISTEN_NONE && card->state != ST_LISTEN_ACTIVE)
2243 printk(KERN_ERR "%s: controller dead ??\n", card->name);
2244 send_listen(card);
2245 mod_timer(&card->listentimer, jiffies + 60 * HZ);
2246}
2247
2248
2249static int capidrv_addcontr(u16 contr, struct capi_profile *profp)
2250{
2251 capidrv_contr *card;
2252 unsigned long flags;
2253 isdn_ctrl cmd;
2254 char id[20];
2255 int i;
2256
2257 sprintf(id, "capidrv-%d", contr);
2258 if (!try_module_get(THIS_MODULE)) {
2259 printk(KERN_WARNING "capidrv: (%s) Could not reserve module\n", id);
2260 return -1;
2261 }
2262 if (!(card = kzalloc(sizeof(capidrv_contr), GFP_ATOMIC))) {
2263 printk(KERN_WARNING
2264 "capidrv: (%s) Could not allocate contr-struct.\n", id);
2265 return -1;
2266 }
2267 card->owner = THIS_MODULE;
2268 timer_setup(&card->listentimer, listentimerfunc, 0);
2269 strcpy(card->name, id);
2270 card->contrnr = contr;
2271 card->nbchan = profp->nbchannel;
2272 card->bchans = kmalloc_array(card->nbchan, sizeof(capidrv_bchan),
2273 GFP_ATOMIC);
2274 if (!card->bchans) {
2275 printk(KERN_WARNING
2276 "capidrv: (%s) Could not allocate bchan-structs.\n", id);
2277 module_put(card->owner);
2278 kfree(card);
2279 return -1;
2280 }
2281 card->interface.channels = profp->nbchannel;
2282 card->interface.maxbufsize = 2048;
2283 card->interface.command = if_command;
2284 card->interface.writebuf_skb = if_sendbuf;
2285 card->interface.writecmd = NULL;
2286 card->interface.readstat = if_readstat;
2287 card->interface.features =
2288 ISDN_FEATURE_L2_HDLC |
2289 ISDN_FEATURE_L2_TRANS |
2290 ISDN_FEATURE_L3_TRANS |
2291 ISDN_FEATURE_P_UNKNOWN |
2292 ISDN_FEATURE_L2_X75I |
2293 ISDN_FEATURE_L2_X75UI |
2294 ISDN_FEATURE_L2_X75BUI;
2295 if (profp->support1 & (1 << 2))
2296 card->interface.features |=
2297 ISDN_FEATURE_L2_V11096 |
2298 ISDN_FEATURE_L2_V11019 |
2299 ISDN_FEATURE_L2_V11038;
2300 if (profp->support1 & (1 << 8))
2301 card->interface.features |= ISDN_FEATURE_L2_MODEM;
2302 card->interface.hl_hdrlen = 22; /* len of DATA_B3_REQ */
2303 strncpy(card->interface.id, id, sizeof(card->interface.id) - 1);
2304
2305
2306 card->q931_read = card->q931_buf;
2307 card->q931_write = card->q931_buf;
2308 card->q931_end = card->q931_buf + sizeof(card->q931_buf) - 1;
2309
2310 if (!register_isdn(&card->interface)) {
2311 printk(KERN_ERR "capidrv: Unable to register contr %s\n", id);
2312 kfree(card->bchans);
2313 module_put(card->owner);
2314 kfree(card);
2315 return -1;
2316 }
2317 card->myid = card->interface.channels;
2318 memset(card->bchans, 0, sizeof(capidrv_bchan) * card->nbchan);
2319 for (i = 0; i < card->nbchan; i++) {
2320 card->bchans[i].contr = card;
2321 }
2322
2323 spin_lock_irqsave(&global_lock, flags);
2324 card->next = global.contr_list;
2325 global.contr_list = card;
2326 global.ncontr++;
2327 spin_unlock_irqrestore(&global_lock, flags);
2328
2329 cmd.command = ISDN_STAT_RUN;
2330 cmd.driver = card->myid;
2331 card->interface.statcallb(&cmd);
2332
2333 card->cipmask = 0x1FFF03FF; /* any */
2334 card->cipmask2 = 0;
2335
2336 send_listen(card);
2337 mod_timer(&card->listentimer, jiffies + 60 * HZ);
2338
2339 printk(KERN_INFO "%s: now up (%d B channels)\n",
2340 card->name, card->nbchan);
2341
2342 enable_dchannel_trace(card);
2343
2344 return 0;
2345}
2346
2347static int capidrv_delcontr(u16 contr)
2348{
2349 capidrv_contr **pp, *card;
2350 unsigned long flags;
2351 isdn_ctrl cmd;
2352
2353 spin_lock_irqsave(&global_lock, flags);
2354 for (card = global.contr_list; card; card = card->next) {
2355 if (card->contrnr == contr)
2356 break;
2357 }
2358 if (!card) {
2359 spin_unlock_irqrestore(&global_lock, flags);
2360 printk(KERN_ERR "capidrv: delcontr: no contr %u\n", contr);
2361 return -1;
2362 }
2363
2364 /* FIXME: maybe a race condition the card should be removed
2365 * here from global list /kkeil
2366 */
2367 spin_unlock_irqrestore(&global_lock, flags);
2368
2369 del_timer(&card->listentimer);
2370
2371 if (debugmode)
2372 printk(KERN_DEBUG "capidrv-%d: id=%d unloading\n",
2373 card->contrnr, card->myid);
2374
2375 cmd.command = ISDN_STAT_STOP;
2376 cmd.driver = card->myid;
2377 card->interface.statcallb(&cmd);
2378
2379 while (card->nbchan) {
2380
2381 cmd.command = ISDN_STAT_DISCH;
2382 cmd.driver = card->myid;
2383 cmd.arg = card->nbchan - 1;
2384 cmd.parm.num[0] = 0;
2385 if (debugmode)
2386 printk(KERN_DEBUG "capidrv-%d: id=%d disable chan=%ld\n",
2387 card->contrnr, card->myid, cmd.arg);
2388 card->interface.statcallb(&cmd);
2389
2390 if (card->bchans[card->nbchan - 1].nccip)
2391 free_ncci(card, card->bchans[card->nbchan - 1].nccip);
2392 if (card->bchans[card->nbchan - 1].plcip)
2393 free_plci(card, card->bchans[card->nbchan - 1].plcip);
2394 if (card->plci_list)
2395 printk(KERN_ERR "capidrv: bug in free_plci()\n");
2396 card->nbchan--;
2397 }
2398 kfree(card->bchans);
2399 card->bchans = NULL;
2400
2401 if (debugmode)
2402 printk(KERN_DEBUG "capidrv-%d: id=%d isdn unload\n",
2403 card->contrnr, card->myid);
2404
2405 cmd.command = ISDN_STAT_UNLOAD;
2406 cmd.driver = card->myid;
2407 card->interface.statcallb(&cmd);
2408
2409 if (debugmode)
2410 printk(KERN_DEBUG "capidrv-%d: id=%d remove contr from list\n",
2411 card->contrnr, card->myid);
2412
2413 spin_lock_irqsave(&global_lock, flags);
2414 for (pp = &global.contr_list; *pp; pp = &(*pp)->next) {
2415 if (*pp == card) {
2416 *pp = (*pp)->next;
2417 card->next = NULL;
2418 global.ncontr--;
2419 break;
2420 }
2421 }
2422 spin_unlock_irqrestore(&global_lock, flags);
2423
2424 module_put(card->owner);
2425 printk(KERN_INFO "%s: now down.\n", card->name);
2426 kfree(card);
2427 return 0;
2428}
2429
2430
2431static int
2432lower_callback(struct notifier_block *nb, unsigned long val, void *v)
2433{
2434 capi_profile profile;
2435 u32 contr = (long)v;
2436
2437 switch (val) {
2438 case CAPICTR_UP:
2439 printk(KERN_INFO "capidrv: controller %hu up\n", contr);
2440 if (capi20_get_profile(contr, &profile) == CAPI_NOERROR)
2441 (void) capidrv_addcontr(contr, &profile);
2442 break;
2443 case CAPICTR_DOWN:
2444 printk(KERN_INFO "capidrv: controller %hu down\n", contr);
2445 (void) capidrv_delcontr(contr);
2446 break;
2447 }
2448 return NOTIFY_OK;
2449}
2450
2451/*
2452 * /proc/capi/capidrv:
2453 * nrecvctlpkt nrecvdatapkt nsendctlpkt nsenddatapkt
2454 */
2455static int __maybe_unused capidrv_proc_show(struct seq_file *m, void *v)
2456{
2457 seq_printf(m, "%lu %lu %lu %lu\n",
2458 global.ap.nrecvctlpkt,
2459 global.ap.nrecvdatapkt,
2460 global.ap.nsentctlpkt,
2461 global.ap.nsentdatapkt);
2462 return 0;
2463}
2464
2465static void __init proc_init(void)
2466{
2467 proc_create_single("capi/capidrv", 0, NULL, capidrv_proc_show);
2468}
2469
2470static void __exit proc_exit(void)
2471{
2472 remove_proc_entry("capi/capidrv", NULL);
2473}
2474
2475static struct notifier_block capictr_nb = {
2476 .notifier_call = lower_callback,
2477};
2478
2479static int __init capidrv_init(void)
2480{
2481 capi_profile profile;
2482 u32 ncontr, contr;
2483 u16 errcode;
2484
2485 global.ap.rparam.level3cnt = -2; /* number of bchannels twice */
2486 global.ap.rparam.datablkcnt = 16;
2487 global.ap.rparam.datablklen = 2048;
2488
2489 global.ap.recv_message = capidrv_recv_message;
2490 errcode = capi20_register(&global.ap);
2491 if (errcode) {
2492 return -EIO;
2493 }
2494
2495 register_capictr_notifier(&capictr_nb);
2496
2497 errcode = capi20_get_profile(0, &profile);
2498 if (errcode != CAPI_NOERROR) {
2499 unregister_capictr_notifier(&capictr_nb);
2500 capi20_release(&global.ap);
2501 return -EIO;
2502 }
2503
2504 ncontr = profile.ncontroller;
2505 for (contr = 1; contr <= ncontr; contr++) {
2506 errcode = capi20_get_profile(contr, &profile);
2507 if (errcode != CAPI_NOERROR)
2508 continue;
2509 (void) capidrv_addcontr(contr, &profile);
2510 }
2511 proc_init();
2512
2513 return 0;
2514}
2515
2516static void __exit capidrv_exit(void)
2517{
2518 unregister_capictr_notifier(&capictr_nb);
2519 capi20_release(&global.ap);
2520
2521 proc_exit();
2522}
2523
2524module_init(capidrv_init);
2525module_exit(capidrv_exit);
diff --git a/drivers/isdn/capi/capidrv.h b/drivers/isdn/capi/capidrv.h
deleted file mode 100644
index 4466b2e0176d..000000000000
--- a/drivers/isdn/capi/capidrv.h
+++ /dev/null
@@ -1,140 +0,0 @@
1/* $Id: capidrv.h,v 1.2.8.2 2001/09/23 22:24:33 kai Exp $
2 *
3 * ISDN4Linux Driver, using capi20 interface (kernelcapi)
4 *
5 * Copyright 1997 by Carsten Paeth <calle@calle.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 __CAPIDRV_H__
13#define __CAPIDRV_H__
14
15/*
16 * LISTEN state machine
17 */
18#define ST_LISTEN_NONE 0 /* L-0 */
19#define ST_LISTEN_WAIT_CONF 1 /* L-0.1 */
20#define ST_LISTEN_ACTIVE 2 /* L-1 */
21#define ST_LISTEN_ACTIVE_WAIT_CONF 3 /* L-1.1 */
22
23
24#define EV_LISTEN_REQ 1 /* L-0 -> L-0.1
25 L-1 -> L-1.1 */
26#define EV_LISTEN_CONF_ERROR 2 /* L-0.1 -> L-0
27 L-1.1 -> L-1 */
28#define EV_LISTEN_CONF_EMPTY 3 /* L-0.1 -> L-0
29 L-1.1 -> L-0 */
30#define EV_LISTEN_CONF_OK 4 /* L-0.1 -> L-1
31 L-1.1 -> L.1 */
32
33/*
34 * per plci state machine
35 */
36#define ST_PLCI_NONE 0 /* P-0 */
37#define ST_PLCI_OUTGOING 1 /* P-0.1 */
38#define ST_PLCI_ALLOCATED 2 /* P-1 */
39#define ST_PLCI_ACTIVE 3 /* P-ACT */
40#define ST_PLCI_INCOMING 4 /* P-2 */
41#define ST_PLCI_FACILITY_IND 5 /* P-3 */
42#define ST_PLCI_ACCEPTING 6 /* P-4 */
43#define ST_PLCI_DISCONNECTING 7 /* P-5 */
44#define ST_PLCI_DISCONNECTED 8 /* P-6 */
45#define ST_PLCI_RESUMEING 9 /* P-0.Res */
46#define ST_PLCI_RESUME 10 /* P-Res */
47#define ST_PLCI_HELD 11 /* P-HELD */
48
49#define EV_PLCI_CONNECT_REQ 1 /* P-0 -> P-0.1
50 */
51#define EV_PLCI_CONNECT_CONF_ERROR 2 /* P-0.1 -> P-0
52 */
53#define EV_PLCI_CONNECT_CONF_OK 3 /* P-0.1 -> P-1
54 */
55#define EV_PLCI_FACILITY_IND_UP 4 /* P-0 -> P-1
56 */
57#define EV_PLCI_CONNECT_IND 5 /* P-0 -> P-2
58 */
59#define EV_PLCI_CONNECT_ACTIVE_IND 6 /* P-1 -> P-ACT
60 */
61#define EV_PLCI_CONNECT_REJECT 7 /* P-2 -> P-5
62 P-3 -> P-5
63 */
64#define EV_PLCI_DISCONNECT_REQ 8 /* P-1 -> P-5
65 P-2 -> P-5
66 P-3 -> P-5
67 P-4 -> P-5
68 P-ACT -> P-5
69 P-Res -> P-5 (*)
70 P-HELD -> P-5 (*)
71 */
72#define EV_PLCI_DISCONNECT_IND 9 /* P-1 -> P-6
73 P-2 -> P-6
74 P-3 -> P-6
75 P-4 -> P-6
76 P-5 -> P-6
77 P-ACT -> P-6
78 P-Res -> P-6 (*)
79 P-HELD -> P-6 (*)
80 */
81#define EV_PLCI_FACILITY_IND_DOWN 10 /* P-0.1 -> P-5
82 P-1 -> P-5
83 P-ACT -> P-5
84 P-2 -> P-5
85 P-3 -> P-5
86 P-4 -> P-5
87 */
88#define EV_PLCI_DISCONNECT_RESP 11 /* P-6 -> P-0
89 */
90#define EV_PLCI_CONNECT_RESP 12 /* P-6 -> P-0
91 */
92
93#define EV_PLCI_RESUME_REQ 13 /* P-0 -> P-0.Res
94 */
95#define EV_PLCI_RESUME_CONF_OK 14 /* P-0.Res -> P-Res
96 */
97#define EV_PLCI_RESUME_CONF_ERROR 15 /* P-0.Res -> P-0
98 */
99#define EV_PLCI_RESUME_IND 16 /* P-Res -> P-ACT
100 */
101#define EV_PLCI_HOLD_IND 17 /* P-ACT -> P-HELD
102 */
103#define EV_PLCI_RETRIEVE_IND 18 /* P-HELD -> P-ACT
104 */
105#define EV_PLCI_SUSPEND_IND 19 /* P-ACT -> P-5
106 */
107#define EV_PLCI_CD_IND 20 /* P-2 -> P-5
108 */
109
110/*
111 * per ncci state machine
112 */
113#define ST_NCCI_PREVIOUS -1
114#define ST_NCCI_NONE 0 /* N-0 */
115#define ST_NCCI_OUTGOING 1 /* N-0.1 */
116#define ST_NCCI_INCOMING 2 /* N-1 */
117#define ST_NCCI_ALLOCATED 3 /* N-2 */
118#define ST_NCCI_ACTIVE 4 /* N-ACT */
119#define ST_NCCI_RESETING 5 /* N-3 */
120#define ST_NCCI_DISCONNECTING 6 /* N-4 */
121#define ST_NCCI_DISCONNECTED 7 /* N-5 */
122
123#define EV_NCCI_CONNECT_B3_REQ 1 /* N-0 -> N-0.1 */
124#define EV_NCCI_CONNECT_B3_IND 2 /* N-0 -> N.1 */
125#define EV_NCCI_CONNECT_B3_CONF_OK 3 /* N-0.1 -> N.2 */
126#define EV_NCCI_CONNECT_B3_CONF_ERROR 4 /* N-0.1 -> N.0 */
127#define EV_NCCI_CONNECT_B3_REJECT 5 /* N-1 -> N-4 */
128#define EV_NCCI_CONNECT_B3_RESP 6 /* N-1 -> N-2 */
129#define EV_NCCI_CONNECT_B3_ACTIVE_IND 7 /* N-2 -> N-ACT */
130#define EV_NCCI_RESET_B3_REQ 8 /* N-ACT -> N-3 */
131#define EV_NCCI_RESET_B3_IND 9 /* N-3 -> N-ACT */
132#define EV_NCCI_DISCONNECT_B3_IND 10 /* N-4 -> N.5 */
133#define EV_NCCI_DISCONNECT_B3_CONF_ERROR 11 /* N-4 -> previous */
134#define EV_NCCI_DISCONNECT_B3_REQ 12 /* N-1 -> N-4
135 N-2 -> N-4
136 N-3 -> N-4
137 N-ACT -> N-4 */
138#define EV_NCCI_DISCONNECT_B3_RESP 13 /* N-5 -> N-0 */
139
140#endif /* __CAPIDRV_H__ */
diff --git a/drivers/isdn/divert/Makefile b/drivers/isdn/divert/Makefile
deleted file mode 100644
index 07684fe53537..000000000000
--- a/drivers/isdn/divert/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
1# SPDX-License-Identifier: GPL-2.0-only
2# Makefile for the dss1_divert ISDN module
3
4# Each configuration option enables a list of files.
5
6obj-$(CONFIG_ISDN_DIVERSION) += dss1_divert.o
7
8# Multipart objects.
9
10dss1_divert-y := isdn_divert.o divert_procfs.o divert_init.o
diff --git a/drivers/isdn/divert/divert_init.c b/drivers/isdn/divert/divert_init.c
deleted file mode 100644
index 267dede13bfd..000000000000
--- a/drivers/isdn/divert/divert_init.c
+++ /dev/null
@@ -1,82 +0,0 @@
1/* $Id divert_init.c,v 1.5.6.2 2001/01/24 22:18:17 kai Exp $
2 *
3 * Module init for DSS1 diversion services for i4l.
4 *
5 * Copyright 1999 by Werner Cornelius (werner@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#include <linux/module.h>
13#include <linux/init.h>
14#include <linux/kernel.h>
15
16#include "isdn_divert.h"
17
18MODULE_DESCRIPTION("ISDN4Linux: Call diversion support");
19MODULE_AUTHOR("Werner Cornelius");
20MODULE_LICENSE("GPL");
21
22/****************************************/
23/* structure containing interface to hl */
24/****************************************/
25isdn_divert_if divert_if = {
26 DIVERT_IF_MAGIC, /* magic value */
27 DIVERT_CMD_REG, /* register cmd */
28 ll_callback, /* callback routine from ll */
29 NULL, /* command still not specified */
30 NULL, /* drv_to_name */
31 NULL, /* name_to_drv */
32};
33
34/*************************/
35/* Module interface code */
36/* no cmd line parms */
37/*************************/
38static int __init divert_init(void)
39{
40 int i;
41
42 if (divert_dev_init()) {
43 printk(KERN_WARNING "dss1_divert: cannot install device, not loaded\n");
44 return (-EIO);
45 }
46 if ((i = DIVERT_REG_NAME(&divert_if)) != DIVERT_NO_ERR) {
47 divert_dev_deinit();
48 printk(KERN_WARNING "dss1_divert: error %d registering module, not loaded\n", i);
49 return (-EIO);
50 }
51 printk(KERN_INFO "dss1_divert module successfully installed\n");
52 return (0);
53}
54
55/**********************/
56/* Module deinit code */
57/**********************/
58static void __exit divert_exit(void)
59{
60 unsigned long flags;
61 int i;
62
63 spin_lock_irqsave(&divert_lock, flags);
64 divert_if.cmd = DIVERT_CMD_REL; /* release */
65 if ((i = DIVERT_REG_NAME(&divert_if)) != DIVERT_NO_ERR) {
66 printk(KERN_WARNING "dss1_divert: error %d releasing module\n", i);
67 spin_unlock_irqrestore(&divert_lock, flags);
68 return;
69 }
70 if (divert_dev_deinit()) {
71 printk(KERN_WARNING "dss1_divert: device busy, remove cancelled\n");
72 spin_unlock_irqrestore(&divert_lock, flags);
73 return;
74 }
75 spin_unlock_irqrestore(&divert_lock, flags);
76 deleterule(-1); /* delete all rules and free mem */
77 deleteprocs();
78 printk(KERN_INFO "dss1_divert module successfully removed \n");
79}
80
81module_init(divert_init);
82module_exit(divert_exit);
diff --git a/drivers/isdn/divert/divert_procfs.c b/drivers/isdn/divert/divert_procfs.c
deleted file mode 100644
index 342585e04fd3..000000000000
--- a/drivers/isdn/divert/divert_procfs.c
+++ /dev/null
@@ -1,336 +0,0 @@
1/* $Id: divert_procfs.c,v 1.11.6.2 2001/09/23 22:24:36 kai Exp $
2 *
3 * Filesystem handling for the diversion supplementary services.
4 *
5 * Copyright 1998 by Werner Cornelius (werner@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#include <linux/module.h>
13#include <linux/poll.h>
14#include <linux/slab.h>
15#ifdef CONFIG_PROC_FS
16#include <linux/proc_fs.h>
17#else
18#include <linux/fs.h>
19#endif
20#include <linux/sched.h>
21#include <linux/isdnif.h>
22#include <net/net_namespace.h>
23#include <linux/mutex.h>
24#include "isdn_divert.h"
25
26
27/*********************************/
28/* Variables for interface queue */
29/*********************************/
30ulong if_used = 0; /* number of interface users */
31static DEFINE_MUTEX(isdn_divert_mutex);
32static struct divert_info *divert_info_head = NULL; /* head of queue */
33static struct divert_info *divert_info_tail = NULL; /* pointer to last entry */
34static DEFINE_SPINLOCK(divert_info_lock);/* lock for queue */
35static wait_queue_head_t rd_queue;
36
37/*********************************/
38/* put an info buffer into queue */
39/*********************************/
40void
41put_info_buffer(char *cp)
42{
43 struct divert_info *ib;
44 unsigned long flags;
45
46 if (if_used <= 0)
47 return;
48 if (!cp)
49 return;
50 if (!*cp)
51 return;
52 if (!(ib = kmalloc(sizeof(struct divert_info) + strlen(cp), GFP_ATOMIC)))
53 return; /* no memory */
54 strcpy(ib->info_start, cp); /* set output string */
55 ib->next = NULL;
56 spin_lock_irqsave(&divert_info_lock, flags);
57 ib->usage_cnt = if_used;
58 if (!divert_info_head)
59 divert_info_head = ib; /* new head */
60 else
61 divert_info_tail->next = ib; /* follows existing messages */
62 divert_info_tail = ib; /* new tail */
63
64 /* delete old entrys */
65 while (divert_info_head->next) {
66 if ((divert_info_head->usage_cnt <= 0) &&
67 (divert_info_head->next->usage_cnt <= 0)) {
68 ib = divert_info_head;
69 divert_info_head = divert_info_head->next;
70 kfree(ib);
71 } else
72 break;
73 } /* divert_info_head->next */
74 spin_unlock_irqrestore(&divert_info_lock, flags);
75 wake_up_interruptible(&(rd_queue));
76} /* put_info_buffer */
77
78#ifdef CONFIG_PROC_FS
79
80/**********************************/
81/* deflection device read routine */
82/**********************************/
83static ssize_t
84isdn_divert_read(struct file *file, char __user *buf, size_t count, loff_t *off)
85{
86 struct divert_info *inf;
87 int len;
88
89 if (!(inf = *((struct divert_info **) file->private_data))) {
90 if (file->f_flags & O_NONBLOCK)
91 return -EAGAIN;
92 wait_event_interruptible(rd_queue, (inf =
93 *((struct divert_info **) file->private_data)));
94 }
95 if (!inf)
96 return (0);
97
98 inf->usage_cnt--; /* new usage count */
99 file->private_data = &inf->next; /* next structure */
100 if ((len = strlen(inf->info_start)) <= count) {
101 if (copy_to_user(buf, inf->info_start, len))
102 return -EFAULT;
103 *off += len;
104 return (len);
105 }
106 return (0);
107} /* isdn_divert_read */
108
109/**********************************/
110/* deflection device write routine */
111/**********************************/
112static ssize_t
113isdn_divert_write(struct file *file, const char __user *buf, size_t count, loff_t *off)
114{
115 return (-ENODEV);
116} /* isdn_divert_write */
117
118
119/***************************************/
120/* select routines for various kernels */
121/***************************************/
122static __poll_t
123isdn_divert_poll(struct file *file, poll_table *wait)
124{
125 __poll_t mask = 0;
126
127 poll_wait(file, &(rd_queue), wait);
128 /* mask = EPOLLOUT | EPOLLWRNORM; */
129 if (*((struct divert_info **) file->private_data)) {
130 mask |= EPOLLIN | EPOLLRDNORM;
131 }
132 return mask;
133} /* isdn_divert_poll */
134
135/****************/
136/* Open routine */
137/****************/
138static int
139isdn_divert_open(struct inode *ino, struct file *filep)
140{
141 unsigned long flags;
142
143 spin_lock_irqsave(&divert_info_lock, flags);
144 if_used++;
145 if (divert_info_head)
146 filep->private_data = &(divert_info_tail->next);
147 else
148 filep->private_data = &divert_info_head;
149 spin_unlock_irqrestore(&divert_info_lock, flags);
150 /* start_divert(); */
151 return nonseekable_open(ino, filep);
152} /* isdn_divert_open */
153
154/*******************/
155/* close routine */
156/*******************/
157static int
158isdn_divert_close(struct inode *ino, struct file *filep)
159{
160 struct divert_info *inf;
161 unsigned long flags;
162
163 spin_lock_irqsave(&divert_info_lock, flags);
164 if_used--;
165 inf = *((struct divert_info **) filep->private_data);
166 while (inf) {
167 inf->usage_cnt--;
168 inf = inf->next;
169 }
170 if (if_used <= 0)
171 while (divert_info_head) {
172 inf = divert_info_head;
173 divert_info_head = divert_info_head->next;
174 kfree(inf);
175 }
176 spin_unlock_irqrestore(&divert_info_lock, flags);
177 return (0);
178} /* isdn_divert_close */
179
180/*********/
181/* IOCTL */
182/*********/
183static int isdn_divert_ioctl_unlocked(struct file *file, uint cmd, ulong arg)
184{
185 divert_ioctl dioctl;
186 int i;
187 unsigned long flags;
188 divert_rule *rulep;
189 char *cp;
190
191 if (copy_from_user(&dioctl, (void __user *) arg, sizeof(dioctl)))
192 return -EFAULT;
193
194 switch (cmd) {
195 case IIOCGETVER:
196 dioctl.drv_version = DIVERT_IIOC_VERSION; /* set version */
197 break;
198
199 case IIOCGETDRV:
200 if ((dioctl.getid.drvid = divert_if.name_to_drv(dioctl.getid.drvnam)) < 0)
201 return (-EINVAL);
202 break;
203
204 case IIOCGETNAM:
205 cp = divert_if.drv_to_name(dioctl.getid.drvid);
206 if (!cp)
207 return (-EINVAL);
208 if (!*cp)
209 return (-EINVAL);
210 strcpy(dioctl.getid.drvnam, cp);
211 break;
212
213 case IIOCGETRULE:
214 if (!(rulep = getruleptr(dioctl.getsetrule.ruleidx)))
215 return (-EINVAL);
216 dioctl.getsetrule.rule = *rulep; /* copy data */
217 break;
218
219 case IIOCMODRULE:
220 if (!(rulep = getruleptr(dioctl.getsetrule.ruleidx)))
221 return (-EINVAL);
222 spin_lock_irqsave(&divert_lock, flags);
223 *rulep = dioctl.getsetrule.rule; /* copy data */
224 spin_unlock_irqrestore(&divert_lock, flags);
225 return (0); /* no copy required */
226 break;
227
228 case IIOCINSRULE:
229 return (insertrule(dioctl.getsetrule.ruleidx, &dioctl.getsetrule.rule));
230 break;
231
232 case IIOCDELRULE:
233 return (deleterule(dioctl.getsetrule.ruleidx));
234 break;
235
236 case IIOCDODFACT:
237 return (deflect_extern_action(dioctl.fwd_ctrl.subcmd,
238 dioctl.fwd_ctrl.callid,
239 dioctl.fwd_ctrl.to_nr));
240
241 case IIOCDOCFACT:
242 case IIOCDOCFDIS:
243 case IIOCDOCFINT:
244 if (!divert_if.drv_to_name(dioctl.cf_ctrl.drvid))
245 return (-EINVAL); /* invalid driver */
246 if (strnlen(dioctl.cf_ctrl.msn, sizeof(dioctl.cf_ctrl.msn)) ==
247 sizeof(dioctl.cf_ctrl.msn))
248 return -EINVAL;
249 if (strnlen(dioctl.cf_ctrl.fwd_nr, sizeof(dioctl.cf_ctrl.fwd_nr)) ==
250 sizeof(dioctl.cf_ctrl.fwd_nr))
251 return -EINVAL;
252 if ((i = cf_command(dioctl.cf_ctrl.drvid,
253 (cmd == IIOCDOCFACT) ? 1 : (cmd == IIOCDOCFDIS) ? 0 : 2,
254 dioctl.cf_ctrl.cfproc,
255 dioctl.cf_ctrl.msn,
256 dioctl.cf_ctrl.service,
257 dioctl.cf_ctrl.fwd_nr,
258 &dioctl.cf_ctrl.procid)))
259 return (i);
260 break;
261
262 default:
263 return (-EINVAL);
264 } /* switch cmd */
265 return copy_to_user((void __user *)arg, &dioctl, sizeof(dioctl)) ? -EFAULT : 0;
266} /* isdn_divert_ioctl */
267
268static long isdn_divert_ioctl(struct file *file, uint cmd, ulong arg)
269{
270 long ret;
271
272 mutex_lock(&isdn_divert_mutex);
273 ret = isdn_divert_ioctl_unlocked(file, cmd, arg);
274 mutex_unlock(&isdn_divert_mutex);
275
276 return ret;
277}
278
279static const struct file_operations isdn_fops =
280{
281 .owner = THIS_MODULE,
282 .llseek = no_llseek,
283 .read = isdn_divert_read,
284 .write = isdn_divert_write,
285 .poll = isdn_divert_poll,
286 .unlocked_ioctl = isdn_divert_ioctl,
287 .open = isdn_divert_open,
288 .release = isdn_divert_close,
289};
290
291/****************************/
292/* isdn subdir in /proc/net */
293/****************************/
294static struct proc_dir_entry *isdn_proc_entry = NULL;
295static struct proc_dir_entry *isdn_divert_entry = NULL;
296#endif /* CONFIG_PROC_FS */
297
298/***************************************************************************/
299/* divert_dev_init must be called before the proc filesystem may be used */
300/***************************************************************************/
301int
302divert_dev_init(void)
303{
304
305 init_waitqueue_head(&rd_queue);
306
307#ifdef CONFIG_PROC_FS
308 isdn_proc_entry = proc_mkdir("isdn", init_net.proc_net);
309 if (!isdn_proc_entry)
310 return (-1);
311 isdn_divert_entry = proc_create("divert", S_IFREG | S_IRUGO,
312 isdn_proc_entry, &isdn_fops);
313 if (!isdn_divert_entry) {
314 remove_proc_entry("isdn", init_net.proc_net);
315 return (-1);
316 }
317#endif /* CONFIG_PROC_FS */
318
319 return (0);
320} /* divert_dev_init */
321
322/***************************************************************************/
323/* divert_dev_deinit must be called before leaving isdn when included as */
324/* a module. */
325/***************************************************************************/
326int
327divert_dev_deinit(void)
328{
329
330#ifdef CONFIG_PROC_FS
331 remove_proc_entry("divert", isdn_proc_entry);
332 remove_proc_entry("isdn", init_net.proc_net);
333#endif /* CONFIG_PROC_FS */
334
335 return (0);
336} /* divert_dev_deinit */
diff --git a/drivers/isdn/divert/isdn_divert.c b/drivers/isdn/divert/isdn_divert.c
deleted file mode 100644
index 5620fd2c6009..000000000000
--- a/drivers/isdn/divert/isdn_divert.c
+++ /dev/null
@@ -1,846 +0,0 @@
1/* $Id: isdn_divert.c,v 1.6.6.3 2001/09/23 22:24:36 kai Exp $
2 *
3 * DSS1 main diversion supplementary handling for i4l.
4 *
5 * Copyright 1999 by Werner Cornelius (werner@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#include <linux/proc_fs.h>
13#include <linux/slab.h>
14#include <linux/timer.h>
15#include <linux/jiffies.h>
16
17#include "isdn_divert.h"
18
19/**********************************/
20/* structure keeping calling info */
21/**********************************/
22struct call_struc {
23 isdn_ctrl ics; /* delivered setup + driver parameters */
24 ulong divert_id; /* Id delivered to user */
25 unsigned char akt_state; /* actual state */
26 char deflect_dest[35]; /* deflection destination */
27 struct timer_list timer; /* timer control structure */
28 char info[90]; /* device info output */
29 struct call_struc *next; /* pointer to next entry */
30 struct call_struc *prev;
31};
32
33
34/********************************************/
35/* structure keeping deflection table entry */
36/********************************************/
37struct deflect_struc {
38 struct deflect_struc *next, *prev;
39 divert_rule rule; /* used rule */
40};
41
42
43/*****************************************/
44/* variables for main diversion services */
45/*****************************************/
46/* diversion/deflection processes */
47static struct call_struc *divert_head = NULL; /* head of remembered entrys */
48static ulong next_id = 1; /* next info id */
49static struct deflect_struc *table_head = NULL;
50static struct deflect_struc *table_tail = NULL;
51static unsigned char extern_wait_max = 4; /* maximum wait in s for external process */
52
53DEFINE_SPINLOCK(divert_lock);
54
55/***************************/
56/* timer callback function */
57/***************************/
58static void deflect_timer_expire(struct timer_list *t)
59{
60 unsigned long flags;
61 struct call_struc *cs = from_timer(cs, t, timer);
62
63 spin_lock_irqsave(&divert_lock, flags);
64 del_timer(&cs->timer); /* delete active timer */
65 spin_unlock_irqrestore(&divert_lock, flags);
66
67 switch (cs->akt_state) {
68 case DEFLECT_PROCEED:
69 cs->ics.command = ISDN_CMD_HANGUP; /* cancel action */
70 divert_if.ll_cmd(&cs->ics);
71 spin_lock_irqsave(&divert_lock, flags);
72 cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
73 cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
74 add_timer(&cs->timer);
75 spin_unlock_irqrestore(&divert_lock, flags);
76 break;
77
78 case DEFLECT_ALERT:
79 cs->ics.command = ISDN_CMD_REDIR; /* protocol */
80 strlcpy(cs->ics.parm.setup.phone, cs->deflect_dest, sizeof(cs->ics.parm.setup.phone));
81 strcpy(cs->ics.parm.setup.eazmsn, "Testtext delayed");
82 divert_if.ll_cmd(&cs->ics);
83 spin_lock_irqsave(&divert_lock, flags);
84 cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
85 cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
86 add_timer(&cs->timer);
87 spin_unlock_irqrestore(&divert_lock, flags);
88 break;
89
90 case DEFLECT_AUTODEL:
91 default:
92 spin_lock_irqsave(&divert_lock, flags);
93 if (cs->prev)
94 cs->prev->next = cs->next; /* forward link */
95 else
96 divert_head = cs->next;
97 if (cs->next)
98 cs->next->prev = cs->prev; /* back link */
99 spin_unlock_irqrestore(&divert_lock, flags);
100 kfree(cs);
101 return;
102
103 } /* switch */
104} /* deflect_timer_func */
105
106
107/*****************************************/
108/* handle call forwarding de/activations */
109/* 0 = deact, 1 = act, 2 = interrogate */
110/*****************************************/
111int cf_command(int drvid, int mode,
112 u_char proc, char *msn,
113 u_char service, char *fwd_nr, ulong *procid)
114{
115 unsigned long flags;
116 int retval, msnlen;
117 int fwd_len;
118 char *p, *ielenp, tmp[60];
119 struct call_struc *cs;
120
121 if (strchr(msn, '.')) return (-EINVAL); /* subaddress not allowed in msn */
122 if ((proc & 0x7F) > 2) return (-EINVAL);
123 proc &= 3;
124 p = tmp;
125 *p++ = 0x30; /* enumeration */
126 ielenp = p++; /* remember total length position */
127 *p++ = 0xa; /* proc tag */
128 *p++ = 1; /* length */
129 *p++ = proc & 0x7F; /* procedure to de/activate/interrogate */
130 *p++ = 0xa; /* service tag */
131 *p++ = 1; /* length */
132 *p++ = service; /* service to handle */
133
134 if (mode == 1) {
135 if (!*fwd_nr) return (-EINVAL); /* destination missing */
136 if (strchr(fwd_nr, '.')) return (-EINVAL); /* subaddress not allowed */
137 fwd_len = strlen(fwd_nr);
138 *p++ = 0x30; /* number enumeration */
139 *p++ = fwd_len + 2; /* complete forward to len */
140 *p++ = 0x80; /* fwd to nr */
141 *p++ = fwd_len; /* length of number */
142 strcpy(p, fwd_nr); /* copy number */
143 p += fwd_len; /* pointer beyond fwd */
144 } /* activate */
145
146 msnlen = strlen(msn);
147 *p++ = 0x80; /* msn number */
148 if (msnlen > 1) {
149 *p++ = msnlen; /* length */
150 strcpy(p, msn);
151 p += msnlen;
152 } else
153 *p++ = 0;
154
155 *ielenp = p - ielenp - 1; /* set total IE length */
156
157 /* allocate mem for information struct */
158 if (!(cs = kmalloc(sizeof(struct call_struc), GFP_ATOMIC)))
159 return (-ENOMEM); /* no memory */
160 timer_setup(&cs->timer, deflect_timer_expire, 0);
161 cs->info[0] = '\0';
162 cs->ics.driver = drvid;
163 cs->ics.command = ISDN_CMD_PROT_IO; /* protocol specific io */
164 cs->ics.arg = DSS1_CMD_INVOKE; /* invoke supplementary service */
165 cs->ics.parm.dss1_io.proc = (mode == 1) ? 7 : (mode == 2) ? 11 : 8; /* operation */
166 cs->ics.parm.dss1_io.timeout = 4000; /* from ETS 300 207-1 */
167 cs->ics.parm.dss1_io.datalen = p - tmp; /* total len */
168 cs->ics.parm.dss1_io.data = tmp; /* start of buffer */
169
170 spin_lock_irqsave(&divert_lock, flags);
171 cs->ics.parm.dss1_io.ll_id = next_id++; /* id for callback */
172 spin_unlock_irqrestore(&divert_lock, flags);
173 *procid = cs->ics.parm.dss1_io.ll_id;
174
175 sprintf(cs->info, "%d 0x%lx %s%s 0 %s %02x %d%s%s\n",
176 (!mode) ? DIVERT_DEACTIVATE : (mode == 1) ? DIVERT_ACTIVATE : DIVERT_REPORT,
177 cs->ics.parm.dss1_io.ll_id,
178 (mode != 2) ? "" : "0 ",
179 divert_if.drv_to_name(cs->ics.driver),
180 msn,
181 service & 0xFF,
182 proc,
183 (mode != 1) ? "" : " 0 ",
184 (mode != 1) ? "" : fwd_nr);
185
186 retval = divert_if.ll_cmd(&cs->ics); /* execute command */
187
188 if (!retval) {
189 cs->prev = NULL;
190 spin_lock_irqsave(&divert_lock, flags);
191 cs->next = divert_head;
192 divert_head = cs;
193 spin_unlock_irqrestore(&divert_lock, flags);
194 } else
195 kfree(cs);
196 return (retval);
197} /* cf_command */
198
199
200/****************************************/
201/* handle a external deflection command */
202/****************************************/
203int deflect_extern_action(u_char cmd, ulong callid, char *to_nr)
204{
205 struct call_struc *cs;
206 isdn_ctrl ic;
207 unsigned long flags;
208 int i;
209
210 if ((cmd & 0x7F) > 2) return (-EINVAL); /* invalid command */
211 cs = divert_head; /* start of parameter list */
212 while (cs) {
213 if (cs->divert_id == callid) break; /* found */
214 cs = cs->next;
215 } /* search entry */
216 if (!cs) return (-EINVAL); /* invalid callid */
217
218 ic.driver = cs->ics.driver;
219 ic.arg = cs->ics.arg;
220 i = -EINVAL;
221 if (cs->akt_state == DEFLECT_AUTODEL) return (i); /* no valid call */
222 switch (cmd & 0x7F) {
223 case 0: /* hangup */
224 del_timer(&cs->timer);
225 ic.command = ISDN_CMD_HANGUP;
226 i = divert_if.ll_cmd(&ic);
227 spin_lock_irqsave(&divert_lock, flags);
228 cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
229 cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
230 add_timer(&cs->timer);
231 spin_unlock_irqrestore(&divert_lock, flags);
232 break;
233
234 case 1: /* alert */
235 if (cs->akt_state == DEFLECT_ALERT) return (0);
236 cmd &= 0x7F; /* never wait */
237 del_timer(&cs->timer);
238 ic.command = ISDN_CMD_ALERT;
239 if ((i = divert_if.ll_cmd(&ic))) {
240 spin_lock_irqsave(&divert_lock, flags);
241 cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
242 cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
243 add_timer(&cs->timer);
244 spin_unlock_irqrestore(&divert_lock, flags);
245 } else
246 cs->akt_state = DEFLECT_ALERT;
247 break;
248
249 case 2: /* redir */
250 del_timer(&cs->timer);
251 strlcpy(cs->ics.parm.setup.phone, to_nr, sizeof(cs->ics.parm.setup.phone));
252 strcpy(cs->ics.parm.setup.eazmsn, "Testtext manual");
253 ic.command = ISDN_CMD_REDIR;
254 if ((i = divert_if.ll_cmd(&ic))) {
255 spin_lock_irqsave(&divert_lock, flags);
256 cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
257 cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
258 add_timer(&cs->timer);
259 spin_unlock_irqrestore(&divert_lock, flags);
260 } else
261 cs->akt_state = DEFLECT_ALERT;
262 break;
263
264 } /* switch */
265 return (i);
266} /* deflect_extern_action */
267
268/********************************/
269/* insert a new rule before idx */
270/********************************/
271int insertrule(int idx, divert_rule *newrule)
272{
273 struct deflect_struc *ds, *ds1 = NULL;
274 unsigned long flags;
275
276 if (!(ds = kmalloc(sizeof(struct deflect_struc), GFP_KERNEL)))
277 return (-ENOMEM); /* no memory */
278
279 ds->rule = *newrule; /* set rule */
280
281 spin_lock_irqsave(&divert_lock, flags);
282
283 if (idx >= 0) {
284 ds1 = table_head;
285 while ((ds1) && (idx > 0))
286 { idx--;
287 ds1 = ds1->next;
288 }
289 if (!ds1) idx = -1;
290 }
291
292 if (idx < 0) {
293 ds->prev = table_tail; /* previous entry */
294 ds->next = NULL; /* end of chain */
295 if (ds->prev)
296 ds->prev->next = ds; /* last forward */
297 else
298 table_head = ds; /* is first entry */
299 table_tail = ds; /* end of queue */
300 } else {
301 ds->next = ds1; /* next entry */
302 ds->prev = ds1->prev; /* prev entry */
303 ds1->prev = ds; /* backward chain old element */
304 if (!ds->prev)
305 table_head = ds; /* first element */
306 }
307
308 spin_unlock_irqrestore(&divert_lock, flags);
309 return (0);
310} /* insertrule */
311
312/***********************************/
313/* delete the rule at position idx */
314/***********************************/
315int deleterule(int idx)
316{
317 struct deflect_struc *ds, *ds1;
318 unsigned long flags;
319
320 if (idx < 0) {
321 spin_lock_irqsave(&divert_lock, flags);
322 ds = table_head;
323 table_head = NULL;
324 table_tail = NULL;
325 spin_unlock_irqrestore(&divert_lock, flags);
326 while (ds) {
327 ds1 = ds;
328 ds = ds->next;
329 kfree(ds1);
330 }
331 return (0);
332 }
333
334 spin_lock_irqsave(&divert_lock, flags);
335 ds = table_head;
336
337 while ((ds) && (idx > 0)) {
338 idx--;
339 ds = ds->next;
340 }
341
342 if (!ds) {
343 spin_unlock_irqrestore(&divert_lock, flags);
344 return (-EINVAL);
345 }
346
347 if (ds->next)
348 ds->next->prev = ds->prev; /* backward chain */
349 else
350 table_tail = ds->prev; /* end of chain */
351
352 if (ds->prev)
353 ds->prev->next = ds->next; /* forward chain */
354 else
355 table_head = ds->next; /* start of chain */
356
357 spin_unlock_irqrestore(&divert_lock, flags);
358 kfree(ds);
359 return (0);
360} /* deleterule */
361
362/*******************************************/
363/* get a pointer to a specific rule number */
364/*******************************************/
365divert_rule *getruleptr(int idx)
366{
367 struct deflect_struc *ds = table_head;
368
369 if (idx < 0) return (NULL);
370 while ((ds) && (idx >= 0)) {
371 if (!(idx--)) {
372 return (&ds->rule);
373 break;
374 }
375 ds = ds->next;
376 }
377 return (NULL);
378} /* getruleptr */
379
380/*************************************************/
381/* called from common module on an incoming call */
382/*************************************************/
383static int isdn_divert_icall(isdn_ctrl *ic)
384{
385 int retval = 0;
386 unsigned long flags;
387 struct call_struc *cs = NULL;
388 struct deflect_struc *dv;
389 char *p, *p1;
390 u_char accept;
391
392 /* first check the internal deflection table */
393 for (dv = table_head; dv; dv = dv->next) {
394 /* scan table */
395 if (((dv->rule.callopt == 1) && (ic->command == ISDN_STAT_ICALLW)) ||
396 ((dv->rule.callopt == 2) && (ic->command == ISDN_STAT_ICALL)))
397 continue; /* call option check */
398 if (!(dv->rule.drvid & (1L << ic->driver)))
399 continue; /* driver not matching */
400 if ((dv->rule.si1) && (dv->rule.si1 != ic->parm.setup.si1))
401 continue; /* si1 not matching */
402 if ((dv->rule.si2) && (dv->rule.si2 != ic->parm.setup.si2))
403 continue; /* si2 not matching */
404
405 p = dv->rule.my_msn;
406 p1 = ic->parm.setup.eazmsn;
407 accept = 0;
408 while (*p) {
409 /* complete compare */
410 if (*p == '-') {
411 accept = 1; /* call accepted */
412 break;
413 }
414 if (*p++ != *p1++)
415 break; /* not accepted */
416 if ((!*p) && (!*p1))
417 accept = 1;
418 } /* complete compare */
419 if (!accept) continue; /* not accepted */
420
421 if ((strcmp(dv->rule.caller, "0")) ||
422 (ic->parm.setup.phone[0])) {
423 p = dv->rule.caller;
424 p1 = ic->parm.setup.phone;
425 accept = 0;
426 while (*p) {
427 /* complete compare */
428 if (*p == '-') {
429 accept = 1; /* call accepted */
430 break;
431 }
432 if (*p++ != *p1++)
433 break; /* not accepted */
434 if ((!*p) && (!*p1))
435 accept = 1;
436 } /* complete compare */
437 if (!accept) continue; /* not accepted */
438 }
439
440 switch (dv->rule.action) {
441 case DEFLECT_IGNORE:
442 return 0;
443
444 case DEFLECT_ALERT:
445 case DEFLECT_PROCEED:
446 case DEFLECT_REPORT:
447 case DEFLECT_REJECT:
448 if (dv->rule.action == DEFLECT_PROCEED)
449 if ((!if_used) || ((!extern_wait_max) && (!dv->rule.waittime)))
450 return (0); /* no external deflection needed */
451 if (!(cs = kmalloc(sizeof(struct call_struc), GFP_ATOMIC)))
452 return (0); /* no memory */
453 timer_setup(&cs->timer, deflect_timer_expire, 0);
454 cs->info[0] = '\0';
455
456 cs->ics = *ic; /* copy incoming data */
457 if (!cs->ics.parm.setup.phone[0]) strcpy(cs->ics.parm.setup.phone, "0");
458 if (!cs->ics.parm.setup.eazmsn[0]) strcpy(cs->ics.parm.setup.eazmsn, "0");
459 cs->ics.parm.setup.screen = dv->rule.screen;
460 if (dv->rule.waittime)
461 cs->timer.expires = jiffies + (HZ * dv->rule.waittime);
462 else if (dv->rule.action == DEFLECT_PROCEED)
463 cs->timer.expires = jiffies + (HZ * extern_wait_max);
464 else
465 cs->timer.expires = 0;
466 cs->akt_state = dv->rule.action;
467 spin_lock_irqsave(&divert_lock, flags);
468 cs->divert_id = next_id++; /* new sequence number */
469 spin_unlock_irqrestore(&divert_lock, flags);
470 cs->prev = NULL;
471 if (cs->akt_state == DEFLECT_ALERT) {
472 strcpy(cs->deflect_dest, dv->rule.to_nr);
473 if (!cs->timer.expires) {
474 strcpy(ic->parm.setup.eazmsn,
475 "Testtext direct");
476 ic->parm.setup.screen = dv->rule.screen;
477 strlcpy(ic->parm.setup.phone, dv->rule.to_nr, sizeof(ic->parm.setup.phone));
478 cs->akt_state = DEFLECT_AUTODEL; /* delete after timeout */
479 cs->timer.expires = jiffies + (HZ * AUTODEL_TIME);
480 retval = 5;
481 } else
482 retval = 1; /* alerting */
483 } else {
484 cs->deflect_dest[0] = '\0';
485 retval = 4; /* only proceed */
486 }
487 snprintf(cs->info, sizeof(cs->info),
488 "%d 0x%lx %s %s %s %s 0x%x 0x%x %d %d %s\n",
489 cs->akt_state,
490 cs->divert_id,
491 divert_if.drv_to_name(cs->ics.driver),
492 (ic->command == ISDN_STAT_ICALLW) ? "1" : "0",
493 cs->ics.parm.setup.phone,
494 cs->ics.parm.setup.eazmsn,
495 cs->ics.parm.setup.si1,
496 cs->ics.parm.setup.si2,
497 cs->ics.parm.setup.screen,
498 dv->rule.waittime,
499 cs->deflect_dest);
500 if ((dv->rule.action == DEFLECT_REPORT) ||
501 (dv->rule.action == DEFLECT_REJECT)) {
502 put_info_buffer(cs->info);
503 kfree(cs); /* remove */
504 return ((dv->rule.action == DEFLECT_REPORT) ? 0 : 2); /* nothing to do */
505 }
506 break;
507
508 default:
509 return 0; /* ignore call */
510 } /* switch action */
511 break; /* will break the 'for' looping */
512 } /* scan_table */
513
514 if (cs) {
515 cs->prev = NULL;
516 spin_lock_irqsave(&divert_lock, flags);
517 cs->next = divert_head;
518 divert_head = cs;
519 if (cs->timer.expires) add_timer(&cs->timer);
520 spin_unlock_irqrestore(&divert_lock, flags);
521
522 put_info_buffer(cs->info);
523 return (retval);
524 } else
525 return (0);
526} /* isdn_divert_icall */
527
528
529void deleteprocs(void)
530{
531 struct call_struc *cs, *cs1;
532 unsigned long flags;
533
534 spin_lock_irqsave(&divert_lock, flags);
535 cs = divert_head;
536 divert_head = NULL;
537 while (cs) {
538 del_timer(&cs->timer);
539 cs1 = cs;
540 cs = cs->next;
541 kfree(cs1);
542 }
543 spin_unlock_irqrestore(&divert_lock, flags);
544} /* deleteprocs */
545
546/****************************************************/
547/* put a address including address type into buffer */
548/****************************************************/
549static int put_address(char *st, u_char *p, int len)
550{
551 u_char retval = 0;
552 u_char adr_typ = 0; /* network standard */
553
554 if (len < 2) return (retval);
555 if (*p == 0xA1) {
556 retval = *(++p) + 2; /* total length */
557 if (retval > len) return (0); /* too short */
558 len = retval - 2; /* remaining length */
559 if (len < 3) return (0);
560 if ((*(++p) != 0x0A) || (*(++p) != 1)) return (0);
561 adr_typ = *(++p);
562 len -= 3;
563 p++;
564 if (len < 2) return (0);
565 if (*p++ != 0x12) return (0);
566 if (*p > len) return (0); /* check number length */
567 len = *p++;
568 } else if (*p == 0x80) {
569 retval = *(++p) + 2; /* total length */
570 if (retval > len) return (0);
571 len = retval - 2;
572 p++;
573 } else
574 return (0); /* invalid address information */
575
576 sprintf(st, "%d ", adr_typ);
577 st += strlen(st);
578 if (!len)
579 *st++ = '-';
580 else
581 while (len--)
582 *st++ = *p++;
583 *st = '\0';
584 return (retval);
585} /* put_address */
586
587/*************************************/
588/* report a successful interrogation */
589/*************************************/
590static int interrogate_success(isdn_ctrl *ic, struct call_struc *cs)
591{
592 char *src = ic->parm.dss1_io.data;
593 int restlen = ic->parm.dss1_io.datalen;
594 int cnt = 1;
595 u_char n, n1;
596 char st[90], *p, *stp;
597
598 if (restlen < 2) return (-100); /* frame too short */
599 if (*src++ != 0x30) return (-101);
600 if ((n = *src++) > 0x81) return (-102); /* invalid length field */
601 restlen -= 2; /* remaining bytes */
602 if (n == 0x80) {
603 if (restlen < 2) return (-103);
604 if ((*(src + restlen - 1)) || (*(src + restlen - 2))) return (-104);
605 restlen -= 2;
606 } else if (n == 0x81) {
607 n = *src++;
608 restlen--;
609 if (n > restlen) return (-105);
610 restlen = n;
611 } else if (n > restlen)
612 return (-106);
613 else
614 restlen = n; /* standard format */
615 if (restlen < 3) return (-107); /* no procedure */
616 if ((*src++ != 2) || (*src++ != 1) || (*src++ != 0x0B)) return (-108);
617 restlen -= 3;
618 if (restlen < 2) return (-109); /* list missing */
619 if (*src == 0x31) {
620 src++;
621 if ((n = *src++) > 0x81) return (-110); /* invalid length field */
622 restlen -= 2; /* remaining bytes */
623 if (n == 0x80) {
624 if (restlen < 2) return (-111);
625 if ((*(src + restlen - 1)) || (*(src + restlen - 2))) return (-112);
626 restlen -= 2;
627 } else if (n == 0x81) {
628 n = *src++;
629 restlen--;
630 if (n > restlen) return (-113);
631 restlen = n;
632 } else if (n > restlen)
633 return (-114);
634 else
635 restlen = n; /* standard format */
636 } /* result list header */
637
638 while (restlen >= 2) {
639 stp = st;
640 sprintf(stp, "%d 0x%lx %d %s ", DIVERT_REPORT, ic->parm.dss1_io.ll_id,
641 cnt++, divert_if.drv_to_name(ic->driver));
642 stp += strlen(stp);
643 if (*src++ != 0x30) return (-115); /* invalid enum */
644 n = *src++;
645 restlen -= 2;
646 if (n > restlen) return (-116); /* enum length wrong */
647 restlen -= n;
648 p = src; /* one entry */
649 src += n;
650 if (!(n1 = put_address(stp, p, n & 0xFF))) continue;
651 stp += strlen(stp);
652 p += n1;
653 n -= n1;
654 if (n < 6) continue; /* no service and proc */
655 if ((*p++ != 0x0A) || (*p++ != 1)) continue;
656 sprintf(stp, " 0x%02x ", (*p++) & 0xFF);
657 stp += strlen(stp);
658 if ((*p++ != 0x0A) || (*p++ != 1)) continue;
659 sprintf(stp, "%d ", (*p++) & 0xFF);
660 stp += strlen(stp);
661 n -= 6;
662 if (n > 2) {
663 if (*p++ != 0x30) continue;
664 if (*p > (n - 2)) continue;
665 n = *p++;
666 if (!(n1 = put_address(stp, p, n & 0xFF))) continue;
667 stp += strlen(stp);
668 }
669 sprintf(stp, "\n");
670 put_info_buffer(st);
671 } /* while restlen */
672 if (restlen) return (-117);
673 return (0);
674} /* interrogate_success */
675
676/*********************************************/
677/* callback for protocol specific extensions */
678/*********************************************/
679static int prot_stat_callback(isdn_ctrl *ic)
680{
681 struct call_struc *cs, *cs1;
682 int i;
683 unsigned long flags;
684
685 cs = divert_head; /* start of list */
686 cs1 = NULL;
687 while (cs) {
688 if (ic->driver == cs->ics.driver) {
689 switch (cs->ics.arg) {
690 case DSS1_CMD_INVOKE:
691 if ((cs->ics.parm.dss1_io.ll_id == ic->parm.dss1_io.ll_id) &&
692 (cs->ics.parm.dss1_io.hl_id == ic->parm.dss1_io.hl_id)) {
693 switch (ic->arg) {
694 case DSS1_STAT_INVOKE_ERR:
695 sprintf(cs->info, "128 0x%lx 0x%x\n",
696 ic->parm.dss1_io.ll_id,
697 ic->parm.dss1_io.timeout);
698 put_info_buffer(cs->info);
699 break;
700
701 case DSS1_STAT_INVOKE_RES:
702 switch (cs->ics.parm.dss1_io.proc) {
703 case 7:
704 case 8:
705 put_info_buffer(cs->info);
706 break;
707
708 case 11:
709 i = interrogate_success(ic, cs);
710 if (i)
711 sprintf(cs->info, "%d 0x%lx %d\n", DIVERT_REPORT,
712 ic->parm.dss1_io.ll_id, i);
713 put_info_buffer(cs->info);
714 break;
715
716 default:
717 printk(KERN_WARNING "dss1_divert: unknown proc %d\n", cs->ics.parm.dss1_io.proc);
718 break;
719 }
720
721 break;
722
723 default:
724 printk(KERN_WARNING "dss1_divert unknown invoke answer %lx\n", ic->arg);
725 break;
726 }
727 cs1 = cs; /* remember structure */
728 cs = NULL;
729 continue; /* abort search */
730 } /* id found */
731 break;
732
733 case DSS1_CMD_INVOKE_ABORT:
734 printk(KERN_WARNING "dss1_divert unhandled invoke abort\n");
735 break;
736
737 default:
738 printk(KERN_WARNING "dss1_divert unknown cmd 0x%lx\n", cs->ics.arg);
739 break;
740 } /* switch ics.arg */
741 cs = cs->next;
742 } /* driver ok */
743 }
744
745 if (!cs1) {
746 printk(KERN_WARNING "dss1_divert unhandled process\n");
747 return (0);
748 }
749
750 if (cs1->ics.driver == -1) {
751 spin_lock_irqsave(&divert_lock, flags);
752 del_timer(&cs1->timer);
753 if (cs1->prev)
754 cs1->prev->next = cs1->next; /* forward link */
755 else
756 divert_head = cs1->next;
757 if (cs1->next)
758 cs1->next->prev = cs1->prev; /* back link */
759 spin_unlock_irqrestore(&divert_lock, flags);
760 kfree(cs1);
761 }
762
763 return (0);
764} /* prot_stat_callback */
765
766
767/***************************/
768/* status callback from HL */
769/***************************/
770static int isdn_divert_stat_callback(isdn_ctrl *ic)
771{
772 struct call_struc *cs, *cs1;
773 unsigned long flags;
774 int retval;
775
776 retval = -1;
777 cs = divert_head; /* start of list */
778 while (cs) {
779 if ((ic->driver == cs->ics.driver) &&
780 (ic->arg == cs->ics.arg)) {
781 switch (ic->command) {
782 case ISDN_STAT_DHUP:
783 sprintf(cs->info, "129 0x%lx\n", cs->divert_id);
784 del_timer(&cs->timer);
785 cs->ics.driver = -1;
786 break;
787
788 case ISDN_STAT_CAUSE:
789 sprintf(cs->info, "130 0x%lx %s\n", cs->divert_id, ic->parm.num);
790 break;
791
792 case ISDN_STAT_REDIR:
793 sprintf(cs->info, "131 0x%lx\n", cs->divert_id);
794 del_timer(&cs->timer);
795 cs->ics.driver = -1;
796 break;
797
798 default:
799 sprintf(cs->info, "999 0x%lx 0x%x\n", cs->divert_id, (int)(ic->command));
800 break;
801 }
802 put_info_buffer(cs->info);
803 retval = 0;
804 }
805 cs1 = cs;
806 cs = cs->next;
807 if (cs1->ics.driver == -1) {
808 spin_lock_irqsave(&divert_lock, flags);
809 if (cs1->prev)
810 cs1->prev->next = cs1->next; /* forward link */
811 else
812 divert_head = cs1->next;
813 if (cs1->next)
814 cs1->next->prev = cs1->prev; /* back link */
815 spin_unlock_irqrestore(&divert_lock, flags);
816 kfree(cs1);
817 }
818 }
819 return (retval); /* not found */
820} /* isdn_divert_stat_callback */
821
822
823/********************/
824/* callback from ll */
825/********************/
826int ll_callback(isdn_ctrl *ic)
827{
828 switch (ic->command) {
829 case ISDN_STAT_ICALL:
830 case ISDN_STAT_ICALLW:
831 return (isdn_divert_icall(ic));
832 break;
833
834 case ISDN_STAT_PROT:
835 if ((ic->arg & 0xFF) == ISDN_PTYPE_EURO) {
836 if (ic->arg != DSS1_STAT_INVOKE_BRD)
837 return (prot_stat_callback(ic));
838 else
839 return (0); /* DSS1 invoke broadcast */
840 } else
841 return (-1); /* protocol not euro */
842
843 default:
844 return (isdn_divert_stat_callback(ic));
845 }
846} /* ll_callback */
diff --git a/drivers/isdn/divert/isdn_divert.h b/drivers/isdn/divert/isdn_divert.h
deleted file mode 100644
index 55033dd872c0..000000000000
--- a/drivers/isdn/divert/isdn_divert.h
+++ /dev/null
@@ -1,132 +0,0 @@
1/* $Id: isdn_divert.h,v 1.5.6.1 2001/09/23 22:24:36 kai Exp $
2 *
3 * Header for the diversion supplementary ioctl interface.
4 *
5 * Copyright 1998 by Werner Cornelius (werner@ikt.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/ioctl.h>
13#include <linux/types.h>
14
15/******************************************/
16/* IOCTL codes for interface to user prog */
17/******************************************/
18#define DIVERT_IIOC_VERSION 0x01 /* actual version */
19#define IIOCGETVER _IO('I', 1) /* get version of interface */
20#define IIOCGETDRV _IO('I', 2) /* get driver number */
21#define IIOCGETNAM _IO('I', 3) /* get driver name */
22#define IIOCGETRULE _IO('I', 4) /* read one rule */
23#define IIOCMODRULE _IO('I', 5) /* modify/replace a rule */
24#define IIOCINSRULE _IO('I', 6) /* insert/append one rule */
25#define IIOCDELRULE _IO('I', 7) /* delete a rule */
26#define IIOCDODFACT _IO('I', 8) /* hangup/reject/alert/immediately deflect a call */
27#define IIOCDOCFACT _IO('I', 9) /* activate control forwarding in PBX */
28#define IIOCDOCFDIS _IO('I', 10) /* deactivate control forwarding in PBX */
29#define IIOCDOCFINT _IO('I', 11) /* interrogate control forwarding in PBX */
30
31/*************************************/
32/* states reported through interface */
33/*************************************/
34#define DEFLECT_IGNORE 0 /* ignore incoming call */
35#define DEFLECT_REPORT 1 /* only report */
36#define DEFLECT_PROCEED 2 /* deflect when externally triggered */
37#define DEFLECT_ALERT 3 /* alert and deflect after delay */
38#define DEFLECT_REJECT 4 /* reject immediately */
39#define DIVERT_ACTIVATE 5 /* diversion activate */
40#define DIVERT_DEACTIVATE 6 /* diversion deactivate */
41#define DIVERT_REPORT 7 /* interrogation result */
42#define DEFLECT_AUTODEL 255 /* only for internal use */
43
44#define DEFLECT_ALL_IDS 0xFFFFFFFF /* all drivers selected */
45
46typedef struct {
47 ulong drvid; /* driver ids, bit mapped */
48 char my_msn[35]; /* desired msn, subaddr allowed */
49 char caller[35]; /* caller id, partial string with * + subaddr allowed */
50 char to_nr[35]; /* deflected to number incl. subaddress */
51 u_char si1, si2; /* service indicators, si1=bitmask, si1+2 0 = all */
52 u_char screen; /* screening: 0 = no info, 1 = info, 2 = nfo with nr */
53 u_char callopt; /* option for call handling:
54 0 = all calls
55 1 = only non waiting calls
56 2 = only waiting calls */
57 u_char action; /* desired action:
58 0 = don't report call -> ignore
59 1 = report call, do not allow/proceed for deflection
60 2 = report call, send proceed, wait max waittime secs
61 3 = report call, alert and deflect after waittime
62 4 = report call, reject immediately
63 actions 1-2 only take place if interface is opened
64 */
65 u_char waittime; /* maximum wait time for proceeding */
66} divert_rule;
67
68typedef union {
69 int drv_version; /* return of driver version */
70 struct {
71 int drvid; /* id of driver */
72 char drvnam[30]; /* name of driver */
73 } getid;
74 struct {
75 int ruleidx; /* index of rule */
76 divert_rule rule; /* rule parms */
77 } getsetrule;
78 struct {
79 u_char subcmd; /* 0 = hangup/reject,
80 1 = alert,
81 2 = deflect */
82 ulong callid; /* id of call delivered by ascii output */
83 char to_nr[35]; /* destination when deflect,
84 else uus1 string (maxlen 31),
85 data from rule used if empty */
86 } fwd_ctrl;
87 struct {
88 int drvid; /* id of driver */
89 u_char cfproc; /* cfu = 0, cfb = 1, cfnr = 2 */
90 ulong procid; /* process id returned when no error */
91 u_char service; /* basically coded service, 0 = all */
92 char msn[25]; /* desired msn, empty = all */
93 char fwd_nr[35];/* forwarded to number + subaddress */
94 } cf_ctrl;
95} divert_ioctl;
96
97#ifdef __KERNEL__
98
99#include <linux/isdnif.h>
100#include <linux/isdn_divertif.h>
101
102#define AUTODEL_TIME 30 /* timeout in s to delete internal entries */
103
104/**************************************************/
105/* structure keeping ascii info for device output */
106/**************************************************/
107struct divert_info {
108 struct divert_info *next;
109 ulong usage_cnt; /* number of files still to work */
110 char info_start[2]; /* info string start */
111};
112
113
114/**************/
115/* Prototypes */
116/**************/
117extern spinlock_t divert_lock;
118
119extern ulong if_used; /* number of interface users */
120extern int divert_dev_deinit(void);
121extern int divert_dev_init(void);
122extern void put_info_buffer(char *);
123extern int ll_callback(isdn_ctrl *);
124extern isdn_divert_if divert_if;
125extern divert_rule *getruleptr(int);
126extern int insertrule(int, divert_rule *);
127extern int deleterule(int);
128extern void deleteprocs(void);
129extern int deflect_extern_action(u_char, ulong, char *);
130extern int cf_command(int, int, u_char, char *, u_char, char *, ulong *);
131
132#endif /* __KERNEL__ */
diff --git a/drivers/isdn/i4l/Kconfig b/drivers/isdn/i4l/Kconfig
deleted file mode 100644
index cacde8de38a3..000000000000
--- a/drivers/isdn/i4l/Kconfig
+++ /dev/null
@@ -1,127 +0,0 @@
1# SPDX-License-Identifier: GPL-2.0-only
2#
3# Old ISDN4Linux config
4#
5
6if ISDN_I4L
7
8config ISDN_PPP
9 bool "Support synchronous PPP"
10 depends on INET
11 select SLHC
12 help
13 Over digital connections such as ISDN, there is no need to
14 synchronize sender and recipient's clocks with start and stop bits
15 as is done over analog telephone lines. Instead, one can use
16 "synchronous PPP". Saying Y here will include this protocol. This
17 protocol is used by Cisco and Sun for example. So you want to say Y
18 here if the other end of your ISDN connection supports it. You will
19 need a special version of pppd (called ipppd) for using this
20 feature. See <file:Documentation/isdn/README.syncppp> and
21 <file:Documentation/isdn/syncPPP.FAQ> for more information.
22
23config ISDN_PPP_VJ
24 bool "Use VJ-compression with synchronous PPP"
25 depends on ISDN_PPP
26 help
27 This enables Van Jacobson header compression for synchronous PPP.
28 Say Y if the other end of the connection supports it.
29
30config ISDN_MPP
31 bool "Support generic MP (RFC 1717)"
32 depends on ISDN_PPP
33 help
34 With synchronous PPP enabled, it is possible to increase throughput
35 by bundling several ISDN-connections, using this protocol. See
36 <file:Documentation/isdn/README.syncppp> for more information.
37
38config IPPP_FILTER
39 bool "Filtering for synchronous PPP"
40 depends on ISDN_PPP
41 help
42 Say Y here if you want to be able to filter the packets passing over
43 IPPP interfaces. This allows you to control which packets count as
44 activity (i.e. which packets will reset the idle timer or bring up
45 a demand-dialled link) and which packets are to be dropped entirely.
46 You need to say Y here if you wish to use the pass-filter and
47 active-filter options to ipppd.
48
49config ISDN_PPP_BSDCOMP
50 tristate "Support BSD compression"
51 depends on ISDN_PPP
52 help
53 Support for the BSD-Compress compression method for PPP, which uses
54 the LZW compression method to compress each PPP packet before it is
55 sent over the wire. The machine at the other end of the PPP link
56 (usually your ISP) has to support the BSD-Compress compression
57 method as well for this to be useful. Even if they don't support it,
58 it is safe to say Y here.
59
60config ISDN_AUDIO
61 bool "Support audio via ISDN"
62 help
63 If you say Y here, the modem-emulator will support a subset of the
64 EIA Class 8 Voice commands. Using a getty with voice-support
65 (mgetty+sendfax by <gert@greenie.muc.de> with an extension, available
66 with the ISDN utility package for example), you will be able to use
67 your Linux box as an ISDN-answering machine. Of course, this must be
68 supported by the lowlevel driver also. Currently, the HiSax driver
69 is the only voice-supporting driver. See
70 <file:Documentation/isdn/README.audio> for more information.
71
72config ISDN_TTY_FAX
73 bool "Support AT-Fax Class 1 and 2 commands"
74 depends on ISDN_AUDIO
75 help
76 If you say Y here, the modem-emulator will support a subset of the
77 Fax Class 1 and 2 commands. Using a getty with fax-support
78 (mgetty+sendfax, hylafax), you will be able to use your Linux box as
79 an ISDN-fax-machine. This must be supported by the lowlevel driver
80 also. See <file:Documentation/isdn/README.fax> for more information.
81
82config ISDN_X25
83 bool "X.25 PLP on top of ISDN"
84 depends on X25
85 help
86 This feature provides the X.25 protocol over ISDN connections.
87 See <file:Documentation/isdn/README.x25> for more information
88 if you are thinking about using this.
89
90
91menu "ISDN feature submodules"
92
93config ISDN_DRV_LOOP
94 tristate "isdnloop support"
95 depends on BROKEN_ON_SMP
96 help
97 This driver provides a virtual ISDN card. Its primary purpose is
98 testing of linklevel features or configuration without getting
99 charged by your service-provider for lots of phone calls.
100 You need will need the loopctrl utility from the latest isdn4k-utils
101 package to set up this driver.
102
103config ISDN_DIVERSION
104 tristate "Support isdn diversion services"
105 help
106 This option allows you to use some supplementary diversion
107 services in conjunction with the HiSax driver on an EURO/DSS1
108 line.
109
110 Supported options are CD (call deflection), CFU (Call forward
111 unconditional), CFB (Call forward when busy) and CFNR (call forward
112 not reachable). Additionally the actual CFU, CFB and CFNR state may
113 be interrogated.
114
115 The use of CFU, CFB, CFNR and interrogation may be limited to some
116 countries. The keypad protocol is still not implemented. CD should
117 work in all countries if the service has been subscribed to.
118
119 Please read the file <file:Documentation/isdn/README.diversion>.
120
121endmenu
122
123comment "ISDN4Linux hardware drivers"
124
125# end ISDN_I4L
126endif
127
diff --git a/drivers/isdn/i4l/Makefile b/drivers/isdn/i4l/Makefile
index be77500c9e86..11fe697739d5 100644
--- a/drivers/isdn/i4l/Makefile
+++ b/drivers/isdn/i4l/Makefile
@@ -3,18 +3,4 @@
3 3
4# Each configuration option enables a list of files. 4# Each configuration option enables a list of files.
5 5
6obj-$(CONFIG_ISDN_I4L) += isdn.o
7obj-$(CONFIG_ISDN_PPP_BSDCOMP) += isdn_bsdcomp.o
8obj-$(CONFIG_ISDN_HDLC) += isdnhdlc.o 6obj-$(CONFIG_ISDN_HDLC) += isdnhdlc.o
9
10# Multipart objects.
11
12isdn-y := isdn_net.o isdn_tty.o isdn_v110.o isdn_common.o
13
14# Optional parts of multipart objects.
15
16isdn-$(CONFIG_ISDN_PPP) += isdn_ppp.o
17isdn-$(CONFIG_ISDN_X25) += isdn_concap.o isdn_x25iface.o
18isdn-$(CONFIG_ISDN_AUDIO) += isdn_audio.o
19isdn-$(CONFIG_ISDN_TTY_FAX) += isdn_ttyfax.o
20
diff --git a/drivers/isdn/i4l/isdn_audio.c b/drivers/isdn/i4l/isdn_audio.c
deleted file mode 100644
index b6bcd1eca128..000000000000
--- a/drivers/isdn/i4l/isdn_audio.c
+++ /dev/null
@@ -1,711 +0,0 @@
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 <linux/slab.h>
16#include "isdn_audio.h"
17#include "isdn_common.h"
18
19char *isdn_audio_revision = "$Revision: 1.1.2.2 $";
20
21/*
22 * Misc. lookup-tables.
23 */
24
25/* ulaw -> signed 16-bit */
26static short isdn_audio_ulaw_to_s16[] =
27{
28 0x8284, 0x8684, 0x8a84, 0x8e84, 0x9284, 0x9684, 0x9a84, 0x9e84,
29 0xa284, 0xa684, 0xaa84, 0xae84, 0xb284, 0xb684, 0xba84, 0xbe84,
30 0xc184, 0xc384, 0xc584, 0xc784, 0xc984, 0xcb84, 0xcd84, 0xcf84,
31 0xd184, 0xd384, 0xd584, 0xd784, 0xd984, 0xdb84, 0xdd84, 0xdf84,
32 0xe104, 0xe204, 0xe304, 0xe404, 0xe504, 0xe604, 0xe704, 0xe804,
33 0xe904, 0xea04, 0xeb04, 0xec04, 0xed04, 0xee04, 0xef04, 0xf004,
34 0xf0c4, 0xf144, 0xf1c4, 0xf244, 0xf2c4, 0xf344, 0xf3c4, 0xf444,
35 0xf4c4, 0xf544, 0xf5c4, 0xf644, 0xf6c4, 0xf744, 0xf7c4, 0xf844,
36 0xf8a4, 0xf8e4, 0xf924, 0xf964, 0xf9a4, 0xf9e4, 0xfa24, 0xfa64,
37 0xfaa4, 0xfae4, 0xfb24, 0xfb64, 0xfba4, 0xfbe4, 0xfc24, 0xfc64,
38 0xfc94, 0xfcb4, 0xfcd4, 0xfcf4, 0xfd14, 0xfd34, 0xfd54, 0xfd74,
39 0xfd94, 0xfdb4, 0xfdd4, 0xfdf4, 0xfe14, 0xfe34, 0xfe54, 0xfe74,
40 0xfe8c, 0xfe9c, 0xfeac, 0xfebc, 0xfecc, 0xfedc, 0xfeec, 0xfefc,
41 0xff0c, 0xff1c, 0xff2c, 0xff3c, 0xff4c, 0xff5c, 0xff6c, 0xff7c,
42 0xff88, 0xff90, 0xff98, 0xffa0, 0xffa8, 0xffb0, 0xffb8, 0xffc0,
43 0xffc8, 0xffd0, 0xffd8, 0xffe0, 0xffe8, 0xfff0, 0xfff8, 0x0000,
44 0x7d7c, 0x797c, 0x757c, 0x717c, 0x6d7c, 0x697c, 0x657c, 0x617c,
45 0x5d7c, 0x597c, 0x557c, 0x517c, 0x4d7c, 0x497c, 0x457c, 0x417c,
46 0x3e7c, 0x3c7c, 0x3a7c, 0x387c, 0x367c, 0x347c, 0x327c, 0x307c,
47 0x2e7c, 0x2c7c, 0x2a7c, 0x287c, 0x267c, 0x247c, 0x227c, 0x207c,
48 0x1efc, 0x1dfc, 0x1cfc, 0x1bfc, 0x1afc, 0x19fc, 0x18fc, 0x17fc,
49 0x16fc, 0x15fc, 0x14fc, 0x13fc, 0x12fc, 0x11fc, 0x10fc, 0x0ffc,
50 0x0f3c, 0x0ebc, 0x0e3c, 0x0dbc, 0x0d3c, 0x0cbc, 0x0c3c, 0x0bbc,
51 0x0b3c, 0x0abc, 0x0a3c, 0x09bc, 0x093c, 0x08bc, 0x083c, 0x07bc,
52 0x075c, 0x071c, 0x06dc, 0x069c, 0x065c, 0x061c, 0x05dc, 0x059c,
53 0x055c, 0x051c, 0x04dc, 0x049c, 0x045c, 0x041c, 0x03dc, 0x039c,
54 0x036c, 0x034c, 0x032c, 0x030c, 0x02ec, 0x02cc, 0x02ac, 0x028c,
55 0x026c, 0x024c, 0x022c, 0x020c, 0x01ec, 0x01cc, 0x01ac, 0x018c,
56 0x0174, 0x0164, 0x0154, 0x0144, 0x0134, 0x0124, 0x0114, 0x0104,
57 0x00f4, 0x00e4, 0x00d4, 0x00c4, 0x00b4, 0x00a4, 0x0094, 0x0084,
58 0x0078, 0x0070, 0x0068, 0x0060, 0x0058, 0x0050, 0x0048, 0x0040,
59 0x0038, 0x0030, 0x0028, 0x0020, 0x0018, 0x0010, 0x0008, 0x0000
60};
61
62/* alaw -> signed 16-bit */
63static short isdn_audio_alaw_to_s16[] =
64{
65 0x13fc, 0xec04, 0x0144, 0xfebc, 0x517c, 0xae84, 0x051c, 0xfae4,
66 0x0a3c, 0xf5c4, 0x0048, 0xffb8, 0x287c, 0xd784, 0x028c, 0xfd74,
67 0x1bfc, 0xe404, 0x01cc, 0xfe34, 0x717c, 0x8e84, 0x071c, 0xf8e4,
68 0x0e3c, 0xf1c4, 0x00c4, 0xff3c, 0x387c, 0xc784, 0x039c, 0xfc64,
69 0x0ffc, 0xf004, 0x0104, 0xfefc, 0x417c, 0xbe84, 0x041c, 0xfbe4,
70 0x083c, 0xf7c4, 0x0008, 0xfff8, 0x207c, 0xdf84, 0x020c, 0xfdf4,
71 0x17fc, 0xe804, 0x018c, 0xfe74, 0x617c, 0x9e84, 0x061c, 0xf9e4,
72 0x0c3c, 0xf3c4, 0x0084, 0xff7c, 0x307c, 0xcf84, 0x030c, 0xfcf4,
73 0x15fc, 0xea04, 0x0164, 0xfe9c, 0x597c, 0xa684, 0x059c, 0xfa64,
74 0x0b3c, 0xf4c4, 0x0068, 0xff98, 0x2c7c, 0xd384, 0x02cc, 0xfd34,
75 0x1dfc, 0xe204, 0x01ec, 0xfe14, 0x797c, 0x8684, 0x07bc, 0xf844,
76 0x0f3c, 0xf0c4, 0x00e4, 0xff1c, 0x3c7c, 0xc384, 0x03dc, 0xfc24,
77 0x11fc, 0xee04, 0x0124, 0xfedc, 0x497c, 0xb684, 0x049c, 0xfb64,
78 0x093c, 0xf6c4, 0x0028, 0xffd8, 0x247c, 0xdb84, 0x024c, 0xfdb4,
79 0x19fc, 0xe604, 0x01ac, 0xfe54, 0x697c, 0x9684, 0x069c, 0xf964,
80 0x0d3c, 0xf2c4, 0x00a4, 0xff5c, 0x347c, 0xcb84, 0x034c, 0xfcb4,
81 0x12fc, 0xed04, 0x0134, 0xfecc, 0x4d7c, 0xb284, 0x04dc, 0xfb24,
82 0x09bc, 0xf644, 0x0038, 0xffc8, 0x267c, 0xd984, 0x026c, 0xfd94,
83 0x1afc, 0xe504, 0x01ac, 0xfe54, 0x6d7c, 0x9284, 0x06dc, 0xf924,
84 0x0dbc, 0xf244, 0x00b4, 0xff4c, 0x367c, 0xc984, 0x036c, 0xfc94,
85 0x0f3c, 0xf0c4, 0x00f4, 0xff0c, 0x3e7c, 0xc184, 0x03dc, 0xfc24,
86 0x07bc, 0xf844, 0x0008, 0xfff8, 0x1efc, 0xe104, 0x01ec, 0xfe14,
87 0x16fc, 0xe904, 0x0174, 0xfe8c, 0x5d7c, 0xa284, 0x05dc, 0xfa24,
88 0x0bbc, 0xf444, 0x0078, 0xff88, 0x2e7c, 0xd184, 0x02ec, 0xfd14,
89 0x14fc, 0xeb04, 0x0154, 0xfeac, 0x557c, 0xaa84, 0x055c, 0xfaa4,
90 0x0abc, 0xf544, 0x0058, 0xffa8, 0x2a7c, 0xd584, 0x02ac, 0xfd54,
91 0x1cfc, 0xe304, 0x01cc, 0xfe34, 0x757c, 0x8a84, 0x075c, 0xf8a4,
92 0x0ebc, 0xf144, 0x00d4, 0xff2c, 0x3a7c, 0xc584, 0x039c, 0xfc64,
93 0x10fc, 0xef04, 0x0114, 0xfeec, 0x457c, 0xba84, 0x045c, 0xfba4,
94 0x08bc, 0xf744, 0x0018, 0xffe8, 0x227c, 0xdd84, 0x022c, 0xfdd4,
95 0x18fc, 0xe704, 0x018c, 0xfe74, 0x657c, 0x9a84, 0x065c, 0xf9a4,
96 0x0cbc, 0xf344, 0x0094, 0xff6c, 0x327c, 0xcd84, 0x032c, 0xfcd4
97};
98
99/* alaw -> ulaw */
100static char isdn_audio_alaw_to_ulaw[] =
101{
102 0xab, 0x2b, 0xe3, 0x63, 0x8b, 0x0b, 0xc9, 0x49,
103 0xba, 0x3a, 0xf6, 0x76, 0x9b, 0x1b, 0xd7, 0x57,
104 0xa3, 0x23, 0xdd, 0x5d, 0x83, 0x03, 0xc1, 0x41,
105 0xb2, 0x32, 0xeb, 0x6b, 0x93, 0x13, 0xcf, 0x4f,
106 0xaf, 0x2f, 0xe7, 0x67, 0x8f, 0x0f, 0xcd, 0x4d,
107 0xbe, 0x3e, 0xfe, 0x7e, 0x9f, 0x1f, 0xdb, 0x5b,
108 0xa7, 0x27, 0xdf, 0x5f, 0x87, 0x07, 0xc5, 0x45,
109 0xb6, 0x36, 0xef, 0x6f, 0x97, 0x17, 0xd3, 0x53,
110 0xa9, 0x29, 0xe1, 0x61, 0x89, 0x09, 0xc7, 0x47,
111 0xb8, 0x38, 0xf2, 0x72, 0x99, 0x19, 0xd5, 0x55,
112 0xa1, 0x21, 0xdc, 0x5c, 0x81, 0x01, 0xbf, 0x3f,
113 0xb0, 0x30, 0xe9, 0x69, 0x91, 0x11, 0xce, 0x4e,
114 0xad, 0x2d, 0xe5, 0x65, 0x8d, 0x0d, 0xcb, 0x4b,
115 0xbc, 0x3c, 0xfa, 0x7a, 0x9d, 0x1d, 0xd9, 0x59,
116 0xa5, 0x25, 0xde, 0x5e, 0x85, 0x05, 0xc3, 0x43,
117 0xb4, 0x34, 0xed, 0x6d, 0x95, 0x15, 0xd1, 0x51,
118 0xac, 0x2c, 0xe4, 0x64, 0x8c, 0x0c, 0xca, 0x4a,
119 0xbb, 0x3b, 0xf8, 0x78, 0x9c, 0x1c, 0xd8, 0x58,
120 0xa4, 0x24, 0xde, 0x5e, 0x84, 0x04, 0xc2, 0x42,
121 0xb3, 0x33, 0xec, 0x6c, 0x94, 0x14, 0xd0, 0x50,
122 0xb0, 0x30, 0xe8, 0x68, 0x90, 0x10, 0xce, 0x4e,
123 0xbf, 0x3f, 0xfe, 0x7e, 0xa0, 0x20, 0xdc, 0x5c,
124 0xa8, 0x28, 0xe0, 0x60, 0x88, 0x08, 0xc6, 0x46,
125 0xb7, 0x37, 0xf0, 0x70, 0x98, 0x18, 0xd4, 0x54,
126 0xaa, 0x2a, 0xe2, 0x62, 0x8a, 0x0a, 0xc8, 0x48,
127 0xb9, 0x39, 0xf4, 0x74, 0x9a, 0x1a, 0xd6, 0x56,
128 0xa2, 0x22, 0xdd, 0x5d, 0x82, 0x02, 0xc0, 0x40,
129 0xb1, 0x31, 0xea, 0x6a, 0x92, 0x12, 0xcf, 0x4f,
130 0xae, 0x2e, 0xe6, 0x66, 0x8e, 0x0e, 0xcc, 0x4c,
131 0xbd, 0x3d, 0xfc, 0x7c, 0x9e, 0x1e, 0xda, 0x5a,
132 0xa6, 0x26, 0xdf, 0x5f, 0x86, 0x06, 0xc4, 0x44,
133 0xb5, 0x35, 0xee, 0x6e, 0x96, 0x16, 0xd2, 0x52
134};
135
136/* ulaw -> alaw */
137static char isdn_audio_ulaw_to_alaw[] =
138{
139 0xab, 0x55, 0xd5, 0x15, 0x95, 0x75, 0xf5, 0x35,
140 0xb5, 0x45, 0xc5, 0x05, 0x85, 0x65, 0xe5, 0x25,
141 0xa5, 0x5d, 0xdd, 0x1d, 0x9d, 0x7d, 0xfd, 0x3d,
142 0xbd, 0x4d, 0xcd, 0x0d, 0x8d, 0x6d, 0xed, 0x2d,
143 0xad, 0x51, 0xd1, 0x11, 0x91, 0x71, 0xf1, 0x31,
144 0xb1, 0x41, 0xc1, 0x01, 0x81, 0x61, 0xe1, 0x21,
145 0x59, 0xd9, 0x19, 0x99, 0x79, 0xf9, 0x39, 0xb9,
146 0x49, 0xc9, 0x09, 0x89, 0x69, 0xe9, 0x29, 0xa9,
147 0xd7, 0x17, 0x97, 0x77, 0xf7, 0x37, 0xb7, 0x47,
148 0xc7, 0x07, 0x87, 0x67, 0xe7, 0x27, 0xa7, 0xdf,
149 0x9f, 0x7f, 0xff, 0x3f, 0xbf, 0x4f, 0xcf, 0x0f,
150 0x8f, 0x6f, 0xef, 0x2f, 0x53, 0x13, 0x73, 0x33,
151 0xb3, 0x43, 0xc3, 0x03, 0x83, 0x63, 0xe3, 0x23,
152 0xa3, 0x5b, 0xdb, 0x1b, 0x9b, 0x7b, 0xfb, 0x3b,
153 0xbb, 0xbb, 0x4b, 0x4b, 0xcb, 0xcb, 0x0b, 0x0b,
154 0x8b, 0x8b, 0x6b, 0x6b, 0xeb, 0xeb, 0x2b, 0x2b,
155 0xab, 0x54, 0xd4, 0x14, 0x94, 0x74, 0xf4, 0x34,
156 0xb4, 0x44, 0xc4, 0x04, 0x84, 0x64, 0xe4, 0x24,
157 0xa4, 0x5c, 0xdc, 0x1c, 0x9c, 0x7c, 0xfc, 0x3c,
158 0xbc, 0x4c, 0xcc, 0x0c, 0x8c, 0x6c, 0xec, 0x2c,
159 0xac, 0x50, 0xd0, 0x10, 0x90, 0x70, 0xf0, 0x30,
160 0xb0, 0x40, 0xc0, 0x00, 0x80, 0x60, 0xe0, 0x20,
161 0x58, 0xd8, 0x18, 0x98, 0x78, 0xf8, 0x38, 0xb8,
162 0x48, 0xc8, 0x08, 0x88, 0x68, 0xe8, 0x28, 0xa8,
163 0xd6, 0x16, 0x96, 0x76, 0xf6, 0x36, 0xb6, 0x46,
164 0xc6, 0x06, 0x86, 0x66, 0xe6, 0x26, 0xa6, 0xde,
165 0x9e, 0x7e, 0xfe, 0x3e, 0xbe, 0x4e, 0xce, 0x0e,
166 0x8e, 0x6e, 0xee, 0x2e, 0x52, 0x12, 0x72, 0x32,
167 0xb2, 0x42, 0xc2, 0x02, 0x82, 0x62, 0xe2, 0x22,
168 0xa2, 0x5a, 0xda, 0x1a, 0x9a, 0x7a, 0xfa, 0x3a,
169 0xba, 0xba, 0x4a, 0x4a, 0xca, 0xca, 0x0a, 0x0a,
170 0x8a, 0x8a, 0x6a, 0x6a, 0xea, 0xea, 0x2a, 0x2a
171};
172
173#define NCOEFF 8 /* number of frequencies to be analyzed */
174#define DTMF_TRESH 4000 /* above this is dtmf */
175#define SILENCE_TRESH 200 /* below this is silence */
176#define AMP_BITS 9 /* bits per sample, reduced to avoid overflow */
177#define LOGRP 0
178#define HIGRP 1
179
180/* For DTMF recognition:
181 * 2 * cos(2 * PI * k / N) precalculated for all k
182 */
183static int cos2pik[NCOEFF] =
184{
185 55813, 53604, 51193, 48591, 38114, 33057, 25889, 18332
186};
187
188static char dtmf_matrix[4][4] =
189{
190 {'1', '2', '3', 'A'},
191 {'4', '5', '6', 'B'},
192 {'7', '8', '9', 'C'},
193 {'*', '0', '#', 'D'}
194};
195
196static inline void
197isdn_audio_tlookup(const u_char *table, u_char *buff, unsigned long n)
198{
199#ifdef __i386__
200 unsigned long d0, d1, d2, d3;
201 __asm__ __volatile__(
202 "cld\n"
203 "1:\tlodsb\n\t"
204 "xlatb\n\t"
205 "stosb\n\t"
206 "loop 1b\n\t"
207 : "=&b"(d0), "=&c"(d1), "=&D"(d2), "=&S"(d3)
208 : "0"((long) table), "1"(n), "2"((long) buff), "3"((long) buff)
209 : "memory", "ax");
210#else
211 while (n--)
212 *buff = table[*(unsigned char *)buff], buff++;
213#endif
214}
215
216void
217isdn_audio_ulaw2alaw(unsigned char *buff, unsigned long len)
218{
219 isdn_audio_tlookup(isdn_audio_ulaw_to_alaw, buff, len);
220}
221
222void
223isdn_audio_alaw2ulaw(unsigned char *buff, unsigned long len)
224{
225 isdn_audio_tlookup(isdn_audio_alaw_to_ulaw, buff, len);
226}
227
228/*
229 * linear <-> adpcm conversion stuff
230 * Most parts from the mgetty-package.
231 * (C) by Gert Doering and Klaus Weidner
232 * Used by permission of Gert Doering
233 */
234
235
236#define ZEROTRAP /* turn on the trap as per the MIL-STD */
237#undef ZEROTRAP
238#define BIAS 0x84 /* define the add-in bias for 16 bit samples */
239#define CLIP 32635
240
241static unsigned char
242isdn_audio_linear2ulaw(int sample)
243{
244 static int exp_lut[256] =
245 {
246 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
247 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
248 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
249 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
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 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
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 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
262 };
263 int sign,
264 exponent,
265 mantissa;
266 unsigned char ulawbyte;
267
268 /* Get the sample into sign-magnitude. */
269 sign = (sample >> 8) & 0x80; /* set aside the sign */
270 if (sign != 0)
271 sample = -sample; /* get magnitude */
272 if (sample > CLIP)
273 sample = CLIP; /* clip the magnitude */
274
275 /* Convert from 16 bit linear to ulaw. */
276 sample = sample + BIAS;
277 exponent = exp_lut[(sample >> 7) & 0xFF];
278 mantissa = (sample >> (exponent + 3)) & 0x0F;
279 ulawbyte = ~(sign | (exponent << 4) | mantissa);
280#ifdef ZEROTRAP
281 /* optional CCITT trap */
282 if (ulawbyte == 0)
283 ulawbyte = 0x02;
284#endif
285 return (ulawbyte);
286}
287
288
289static int Mx[3][8] =
290{
291 {0x3800, 0x5600, 0, 0, 0, 0, 0, 0},
292 {0x399a, 0x3a9f, 0x4d14, 0x6607, 0, 0, 0, 0},
293 {0x3556, 0x3556, 0x399A, 0x3A9F, 0x4200, 0x4D14, 0x6607, 0x6607},
294};
295
296static int bitmask[9] =
297{
298 0, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff
299};
300
301static int
302isdn_audio_get_bits(adpcm_state *s, unsigned char **in, int *len)
303{
304 while (s->nleft < s->nbits) {
305 int d = *((*in)++);
306 (*len)--;
307 s->word = (s->word << 8) | d;
308 s->nleft += 8;
309 }
310 s->nleft -= s->nbits;
311 return (s->word >> s->nleft) & bitmask[s->nbits];
312}
313
314static void
315isdn_audio_put_bits(int data, int nbits, adpcm_state *s,
316 unsigned char **out, int *len)
317{
318 s->word = (s->word << nbits) | (data & bitmask[nbits]);
319 s->nleft += nbits;
320 while (s->nleft >= 8) {
321 int d = (s->word >> (s->nleft - 8));
322 *(out[0]++) = d & 255;
323 (*len)++;
324 s->nleft -= 8;
325 }
326}
327
328adpcm_state *
329isdn_audio_adpcm_init(adpcm_state *s, int nbits)
330{
331 if (!s)
332 s = kmalloc(sizeof(adpcm_state), GFP_ATOMIC);
333 if (s) {
334 s->a = 0;
335 s->d = 5;
336 s->word = 0;
337 s->nleft = 0;
338 s->nbits = nbits;
339 }
340 return s;
341}
342
343dtmf_state *
344isdn_audio_dtmf_init(dtmf_state *s)
345{
346 if (!s)
347 s = kmalloc(sizeof(dtmf_state), GFP_ATOMIC);
348 if (s) {
349 s->idx = 0;
350 s->last = ' ';
351 }
352 return s;
353}
354
355/*
356 * Decompression of adpcm data to a/u-law
357 *
358 */
359
360int
361isdn_audio_adpcm2xlaw(adpcm_state *s, int fmt, unsigned char *in,
362 unsigned char *out, int len)
363{
364 int a = s->a;
365 int d = s->d;
366 int nbits = s->nbits;
367 int olen = 0;
368
369 while (len) {
370 int e = isdn_audio_get_bits(s, &in, &len);
371 int sign;
372
373 if (nbits == 4 && e == 0)
374 d = 4;
375 sign = (e >> (nbits - 1)) ? -1 : 1;
376 e &= bitmask[nbits - 1];
377 a += sign * ((e << 1) + 1) * d >> 1;
378 if (d & 1)
379 a++;
380 if (fmt)
381 *out++ = isdn_audio_ulaw_to_alaw[
382 isdn_audio_linear2ulaw(a << 2)];
383 else
384 *out++ = isdn_audio_linear2ulaw(a << 2);
385 olen++;
386 d = (d * Mx[nbits - 2][e] + 0x2000) >> 14;
387 if (d < 5)
388 d = 5;
389 }
390 s->a = a;
391 s->d = d;
392 return olen;
393}
394
395int
396isdn_audio_xlaw2adpcm(adpcm_state *s, int fmt, unsigned char *in,
397 unsigned char *out, int len)
398{
399 int a = s->a;
400 int d = s->d;
401 int nbits = s->nbits;
402 int olen = 0;
403
404 while (len--) {
405 int e = 0,
406 nmax = 1 << (nbits - 1);
407 int sign,
408 delta;
409
410 if (fmt)
411 delta = (isdn_audio_alaw_to_s16[*in++] >> 2) - a;
412 else
413 delta = (isdn_audio_ulaw_to_s16[*in++] >> 2) - a;
414 if (delta < 0) {
415 e = nmax;
416 delta = -delta;
417 }
418 while (--nmax && delta > d) {
419 delta -= d;
420 e++;
421 }
422 if (nbits == 4 && ((e & 0x0f) == 0))
423 e = 8;
424 isdn_audio_put_bits(e, nbits, s, &out, &olen);
425 sign = (e >> (nbits - 1)) ? -1 : 1;
426 e &= bitmask[nbits - 1];
427
428 a += sign * ((e << 1) + 1) * d >> 1;
429 if (d & 1)
430 a++;
431 d = (d * Mx[nbits - 2][e] + 0x2000) >> 14;
432 if (d < 5)
433 d = 5;
434 }
435 s->a = a;
436 s->d = d;
437 return olen;
438}
439
440/*
441 * Goertzel algorithm.
442 * See http://ptolemy.eecs.berkeley.edu/papers/96/dtmf_ict/
443 * for more info.
444 * Result is stored into an sk_buff and queued up for later
445 * evaluation.
446 */
447static void
448isdn_audio_goertzel(int *sample, modem_info *info)
449{
450 int sk,
451 sk1,
452 sk2;
453 int k,
454 n;
455 struct sk_buff *skb;
456 int *result;
457
458 skb = dev_alloc_skb(sizeof(int) * NCOEFF);
459 if (!skb) {
460 printk(KERN_WARNING
461 "isdn_audio: Could not alloc DTMF result for ttyI%d\n",
462 info->line);
463 return;
464 }
465 result = skb_put(skb, sizeof(int) * NCOEFF);
466 for (k = 0; k < NCOEFF; k++) {
467 sk = sk1 = sk2 = 0;
468 for (n = 0; n < DTMF_NPOINTS; n++) {
469 sk = sample[n] + ((cos2pik[k] * sk1) >> 15) - sk2;
470 sk2 = sk1;
471 sk1 = sk;
472 }
473 /* Avoid overflows */
474 sk >>= 1;
475 sk2 >>= 1;
476 /* compute |X(k)|**2 */
477 /* report overflows. This should not happen. */
478 /* Comment this out if desired */
479 if (sk < -32768 || sk > 32767)
480 printk(KERN_DEBUG
481 "isdn_audio: dtmf goertzel overflow, sk=%d\n", sk);
482 if (sk2 < -32768 || sk2 > 32767)
483 printk(KERN_DEBUG
484 "isdn_audio: dtmf goertzel overflow, sk2=%d\n", sk2);
485 result[k] =
486 ((sk * sk) >> AMP_BITS) -
487 ((((cos2pik[k] * sk) >> 15) * sk2) >> AMP_BITS) +
488 ((sk2 * sk2) >> AMP_BITS);
489 }
490 skb_queue_tail(&info->dtmf_queue, skb);
491 isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
492}
493
494void
495isdn_audio_eval_dtmf(modem_info *info)
496{
497 struct sk_buff *skb;
498 int *result;
499 dtmf_state *s;
500 int silence;
501 int i;
502 int di;
503 int ch;
504 int grp[2];
505 char what;
506 char *p;
507 int thresh;
508
509 while ((skb = skb_dequeue(&info->dtmf_queue))) {
510 result = (int *) skb->data;
511 s = info->dtmf_state;
512 grp[LOGRP] = grp[HIGRP] = -1;
513 silence = 0;
514 thresh = 0;
515 for (i = 0; i < NCOEFF; i++) {
516 if (result[i] > DTMF_TRESH) {
517 if (result[i] > thresh)
518 thresh = result[i];
519 }
520 else if (result[i] < SILENCE_TRESH)
521 silence++;
522 }
523 if (silence == NCOEFF)
524 what = ' ';
525 else {
526 if (thresh > 0) {
527 thresh = thresh >> 4; /* touchtones must match within 12 dB */
528 for (i = 0; i < NCOEFF; i++) {
529 if (result[i] < thresh)
530 continue; /* ignore */
531 /* good level found. This is allowed only one time per group */
532 if (i < NCOEFF / 2) {
533 /* lowgroup*/
534 if (grp[LOGRP] >= 0) {
535 // Bad. Another tone found. */
536 grp[LOGRP] = -1;
537 break;
538 }
539 else
540 grp[LOGRP] = i;
541 }
542 else { /* higroup */
543 if (grp[HIGRP] >= 0) { // Bad. Another tone found. */
544 grp[HIGRP] = -1;
545 break;
546 }
547 else
548 grp[HIGRP] = i - NCOEFF/2;
549 }
550 }
551 if ((grp[LOGRP] >= 0) && (grp[HIGRP] >= 0)) {
552 what = dtmf_matrix[grp[LOGRP]][grp[HIGRP]];
553 if (s->last != ' ' && s->last != '.')
554 s->last = what; /* min. 1 non-DTMF between DTMF */
555 } else
556 what = '.';
557 }
558 else
559 what = '.';
560 }
561 if ((what != s->last) && (what != ' ') && (what != '.')) {
562 printk(KERN_DEBUG "dtmf: tt='%c'\n", what);
563 p = skb->data;
564 *p++ = 0x10;
565 *p = what;
566 skb_trim(skb, 2);
567 ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;
568 ISDN_AUDIO_SKB_LOCK(skb) = 0;
569 di = info->isdn_driver;
570 ch = info->isdn_channel;
571 __skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb);
572 dev->drv[di]->rcvcount[ch] += 2;
573 /* Schedule dequeuing */
574 if ((dev->modempoll) && (info->rcvsched))
575 isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
576 wake_up_interruptible(&dev->drv[di]->rcv_waitq[ch]);
577 } else
578 kfree_skb(skb);
579 s->last = what;
580 }
581}
582
583/*
584 * Decode DTMF tones, queue result in separate sk_buf for
585 * later examination.
586 * Parameters:
587 * s = pointer to state-struct.
588 * buf = input audio data
589 * len = size of audio data.
590 * fmt = audio data format (0 = ulaw, 1 = alaw)
591 */
592void
593isdn_audio_calc_dtmf(modem_info *info, unsigned char *buf, int len, int fmt)
594{
595 dtmf_state *s = info->dtmf_state;
596 int i;
597 int c;
598
599 while (len) {
600 c = DTMF_NPOINTS - s->idx;
601 if (c > len)
602 c = len;
603 if (c <= 0)
604 break;
605 for (i = 0; i < c; i++) {
606 if (fmt)
607 s->buf[s->idx++] =
608 isdn_audio_alaw_to_s16[*buf++] >> (15 - AMP_BITS);
609 else
610 s->buf[s->idx++] =
611 isdn_audio_ulaw_to_s16[*buf++] >> (15 - AMP_BITS);
612 }
613 if (s->idx == DTMF_NPOINTS) {
614 isdn_audio_goertzel(s->buf, info);
615 s->idx = 0;
616 }
617 len -= c;
618 }
619}
620
621silence_state *
622isdn_audio_silence_init(silence_state *s)
623{
624 if (!s)
625 s = kmalloc(sizeof(silence_state), GFP_ATOMIC);
626 if (s) {
627 s->idx = 0;
628 s->state = 0;
629 }
630 return s;
631}
632
633void
634isdn_audio_calc_silence(modem_info *info, unsigned char *buf, int len, int fmt)
635{
636 silence_state *s = info->silence_state;
637 int i;
638 signed char c;
639
640 if (!info->emu.vpar[1]) return;
641
642 for (i = 0; i < len; i++) {
643 if (fmt)
644 c = isdn_audio_alaw_to_ulaw[*buf++];
645 else
646 c = *buf++;
647
648 if (c > 0) c -= 128;
649 c = abs(c);
650
651 if (c > (info->emu.vpar[1] * 4)) {
652 s->idx = 0;
653 s->state = 1;
654 } else {
655 if (s->idx < 210000) s->idx++;
656 }
657 }
658}
659
660void
661isdn_audio_put_dle_code(modem_info *info, u_char code)
662{
663 struct sk_buff *skb;
664 int di;
665 int ch;
666 char *p;
667
668 skb = dev_alloc_skb(2);
669 if (!skb) {
670 printk(KERN_WARNING
671 "isdn_audio: Could not alloc skb for ttyI%d\n",
672 info->line);
673 return;
674 }
675 p = skb_put(skb, 2);
676 p[0] = 0x10;
677 p[1] = code;
678 ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;
679 ISDN_AUDIO_SKB_LOCK(skb) = 0;
680 di = info->isdn_driver;
681 ch = info->isdn_channel;
682 __skb_queue_tail(&dev->drv[di]->rpqueue[ch], skb);
683 dev->drv[di]->rcvcount[ch] += 2;
684 /* Schedule dequeuing */
685 if ((dev->modempoll) && (info->rcvsched))
686 isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
687 wake_up_interruptible(&dev->drv[di]->rcv_waitq[ch]);
688}
689
690void
691isdn_audio_eval_silence(modem_info *info)
692{
693 silence_state *s = info->silence_state;
694 char what;
695
696 what = ' ';
697
698 if (s->idx > (info->emu.vpar[2] * 800)) {
699 s->idx = 0;
700 if (!s->state) { /* silence from beginning of rec */
701 what = 's';
702 } else {
703 what = 'q';
704 }
705 }
706 if ((what == 's') || (what == 'q')) {
707 printk(KERN_DEBUG "ttyI%d: %s\n", info->line,
708 (what == 's') ? "silence" : "quiet");
709 isdn_audio_put_dle_code(info, what);
710 }
711}
diff --git a/drivers/isdn/i4l/isdn_audio.h b/drivers/isdn/i4l/isdn_audio.h
deleted file mode 100644
index 013c3582e0d1..000000000000
--- a/drivers/isdn/i4l/isdn_audio.h
+++ /dev/null
@@ -1,44 +0,0 @@
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 void isdn_audio_calc_dtmf(modem_info *, unsigned char *, int, int);
39extern void isdn_audio_eval_dtmf(modem_info *);
40dtmf_state *isdn_audio_dtmf_init(dtmf_state *);
41extern void isdn_audio_calc_silence(modem_info *, unsigned char *, int, int);
42extern void isdn_audio_eval_silence(modem_info *);
43silence_state *isdn_audio_silence_init(silence_state *);
44extern 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
deleted file mode 100644
index 7f28b967ed19..000000000000
--- a/drivers/isdn/i4l/isdn_bsdcomp.c
+++ /dev/null
@@ -1,930 +0,0 @@
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/types.h>
60#include <linux/fcntl.h>
61#include <linux/interrupt.h>
62#include <linux/ptrace.h>
63#include <linux/ioport.h>
64#include <linux/in.h>
65#include <linux/slab.h>
66#include <linux/tty.h>
67#include <linux/errno.h>
68#include <linux/string.h> /* used in new tty drivers */
69#include <linux/signal.h> /* used in new tty drivers */
70#include <linux/bitops.h>
71
72#include <asm/byteorder.h>
73#include <asm/types.h>
74
75#include <linux/if.h>
76
77#include <linux/if_ether.h>
78#include <linux/netdevice.h>
79#include <linux/skbuff.h>
80#include <linux/inet.h>
81#include <linux/ioctl.h>
82#include <linux/vmalloc.h>
83
84#include <linux/ppp_defs.h>
85
86#include <linux/isdn.h>
87#include <linux/isdn_ppp.h>
88#include <linux/ip.h>
89#include <linux/tcp.h>
90#include <linux/if_arp.h>
91#include <linux/ppp-comp.h>
92
93#include "isdn_ppp.h"
94
95MODULE_DESCRIPTION("ISDN4Linux: BSD Compression for PPP over ISDN");
96MODULE_LICENSE("Dual BSD/GPL");
97
98#define BSD_VERSION(x) ((x) >> 5)
99#define BSD_NBITS(x) ((x) & 0x1F)
100
101#define BSD_CURRENT_VERSION 1
102
103#define DEBUG 1
104
105/*
106 * A dictionary for doing BSD compress.
107 */
108
109struct bsd_dict {
110 u32 fcode;
111 u16 codem1; /* output of hash table -1 */
112 u16 cptr; /* map code to hash table entry */
113};
114
115struct bsd_db {
116 int totlen; /* length of this structure */
117 unsigned int hsize; /* size of the hash table */
118 unsigned char hshift; /* used in hash function */
119 unsigned char n_bits; /* current bits/code */
120 unsigned char maxbits; /* maximum bits/code */
121 unsigned char debug; /* non-zero if debug desired */
122 unsigned char unit; /* ppp unit number */
123 u16 seqno; /* sequence # of next packet */
124 unsigned int mru; /* size of receive (decompress) bufr */
125 unsigned int maxmaxcode; /* largest valid code */
126 unsigned int max_ent; /* largest code in use */
127 unsigned int in_count; /* uncompressed bytes, aged */
128 unsigned int bytes_out; /* compressed bytes, aged */
129 unsigned int ratio; /* recent compression ratio */
130 unsigned int checkpoint; /* when to next check the ratio */
131 unsigned int clear_count; /* times dictionary cleared */
132 unsigned int incomp_count; /* incompressible packets */
133 unsigned int incomp_bytes; /* incompressible bytes */
134 unsigned int uncomp_count; /* uncompressed packets */
135 unsigned int uncomp_bytes; /* uncompressed bytes */
136 unsigned int comp_count; /* compressed packets */
137 unsigned int comp_bytes; /* compressed bytes */
138 unsigned short *lens; /* array of lengths of codes */
139 struct bsd_dict *dict; /* dictionary */
140 int xmit;
141};
142
143#define BSD_OVHD 2 /* BSD compress overhead/packet */
144#define MIN_BSD_BITS 9
145#define BSD_INIT_BITS MIN_BSD_BITS
146#define MAX_BSD_BITS 15
147
148/*
149 * the next two codes should not be changed lightly, as they must not
150 * lie within the contiguous general code space.
151 */
152#define CLEAR 256 /* table clear output code */
153#define FIRST 257 /* first free entry */
154#define LAST 255
155
156#define MAXCODE(b) ((1 << (b)) - 1)
157#define BADCODEM1 MAXCODE(MAX_BSD_BITS)
158
159#define BSD_HASH(prefix, suffix, hshift) ((((unsigned long)(suffix)) << (hshift)) \
160 ^ (unsigned long)(prefix))
161#define BSD_KEY(prefix, suffix) ((((unsigned long)(suffix)) << 16) \
162 + (unsigned long)(prefix))
163
164#define CHECK_GAP 10000 /* Ratio check interval */
165
166#define RATIO_SCALE_LOG 8
167#define RATIO_SCALE (1 << RATIO_SCALE_LOG)
168#define RATIO_MAX (0x7fffffff >> RATIO_SCALE_LOG)
169
170/*
171 * clear the dictionary
172 */
173
174static void bsd_clear(struct bsd_db *db)
175{
176 db->clear_count++;
177 db->max_ent = FIRST - 1;
178 db->n_bits = BSD_INIT_BITS;
179 db->bytes_out = 0;
180 db->in_count = 0;
181 db->incomp_count = 0;
182 db->ratio = 0;
183 db->checkpoint = CHECK_GAP;
184}
185
186/*
187 * If the dictionary is full, then see if it is time to reset it.
188 *
189 * Compute the compression ratio using fixed-point arithmetic
190 * with 8 fractional bits.
191 *
192 * Since we have an infinite stream instead of a single file,
193 * watch only the local compression ratio.
194 *
195 * Since both peers must reset the dictionary at the same time even in
196 * the absence of CLEAR codes (while packets are incompressible), they
197 * must compute the same ratio.
198 */
199static int bsd_check(struct bsd_db *db) /* 1=output CLEAR */
200{
201 unsigned int new_ratio;
202
203 if (db->in_count >= db->checkpoint)
204 {
205 /* age the ratio by limiting the size of the counts */
206 if (db->in_count >= RATIO_MAX || db->bytes_out >= RATIO_MAX)
207 {
208 db->in_count -= (db->in_count >> 2);
209 db->bytes_out -= (db->bytes_out >> 2);
210 }
211
212 db->checkpoint = db->in_count + CHECK_GAP;
213
214 if (db->max_ent >= db->maxmaxcode)
215 {
216 /* Reset the dictionary only if the ratio is worse,
217 * or if it looks as if it has been poisoned
218 * by incompressible data.
219 *
220 * This does not overflow, because
221 * db->in_count <= RATIO_MAX.
222 */
223
224 new_ratio = db->in_count << RATIO_SCALE_LOG;
225 if (db->bytes_out != 0)
226 {
227 new_ratio /= db->bytes_out;
228 }
229
230 if (new_ratio < db->ratio || new_ratio < 1 * RATIO_SCALE)
231 {
232 bsd_clear(db);
233 return 1;
234 }
235 db->ratio = new_ratio;
236 }
237 }
238 return 0;
239}
240
241/*
242 * Return statistics.
243 */
244
245static void bsd_stats(void *state, struct compstat *stats)
246{
247 struct bsd_db *db = (struct bsd_db *) state;
248
249 stats->unc_bytes = db->uncomp_bytes;
250 stats->unc_packets = db->uncomp_count;
251 stats->comp_bytes = db->comp_bytes;
252 stats->comp_packets = db->comp_count;
253 stats->inc_bytes = db->incomp_bytes;
254 stats->inc_packets = db->incomp_count;
255 stats->in_count = db->in_count;
256 stats->bytes_out = db->bytes_out;
257}
258
259/*
260 * Reset state, as on a CCP ResetReq.
261 */
262static void bsd_reset(void *state, unsigned char code, unsigned char id,
263 unsigned char *data, unsigned len,
264 struct isdn_ppp_resetparams *rsparm)
265{
266 struct bsd_db *db = (struct bsd_db *) state;
267
268 bsd_clear(db);
269 db->seqno = 0;
270 db->clear_count = 0;
271}
272
273/*
274 * Release the compression structure
275 */
276static void bsd_free(void *state)
277{
278 struct bsd_db *db = (struct bsd_db *) state;
279
280 if (db) {
281 /*
282 * Release the dictionary
283 */
284 vfree(db->dict);
285 db->dict = NULL;
286
287 /*
288 * Release the string buffer
289 */
290 vfree(db->lens);
291 db->lens = NULL;
292
293 /*
294 * Finally release the structure itself.
295 */
296 kfree(db);
297 }
298}
299
300
301/*
302 * Allocate space for a (de) compressor.
303 */
304static void *bsd_alloc(struct isdn_ppp_comp_data *data)
305{
306 int bits;
307 unsigned int hsize, hshift, maxmaxcode;
308 struct bsd_db *db;
309 int decomp;
310
311 static unsigned int htab[][2] = {
312 { 5003 , 4 } , { 5003 , 4 } , { 5003 , 4 } , { 5003 , 4 } ,
313 { 9001 , 5 } , { 18013 , 6 } , { 35023 , 7 } , { 69001 , 8 }
314 };
315
316 if (data->optlen != 1 || data->num != CI_BSD_COMPRESS
317 || BSD_VERSION(data->options[0]) != BSD_CURRENT_VERSION)
318 return NULL;
319
320 bits = BSD_NBITS(data->options[0]);
321
322 if (bits < 9 || bits > 15)
323 return NULL;
324
325 hsize = htab[bits - 9][0];
326 hshift = htab[bits - 9][1];
327
328 /*
329 * Allocate the main control structure for this instance.
330 */
331 maxmaxcode = MAXCODE(bits);
332 db = kzalloc(sizeof(struct bsd_db), GFP_KERNEL);
333 if (!db)
334 return NULL;
335
336 db->xmit = data->flags & IPPP_COMP_FLAG_XMIT;
337 decomp = db->xmit ? 0 : 1;
338
339 /*
340 * Allocate space for the dictionary. This may be more than one page in
341 * length.
342 */
343 db->dict = vmalloc(array_size(hsize, sizeof(struct bsd_dict)));
344 if (!db->dict) {
345 bsd_free(db);
346 return NULL;
347 }
348
349 /*
350 * If this is the compression buffer then there is no length data.
351 * For decompression, the length information is needed as well.
352 */
353 if (!decomp)
354 db->lens = NULL;
355 else {
356 db->lens = vmalloc(array_size(sizeof(db->lens[0]),
357 maxmaxcode + 1));
358 if (!db->lens) {
359 bsd_free(db);
360 return (NULL);
361 }
362 }
363
364 /*
365 * Initialize the data information for the compression code
366 */
367 db->totlen = sizeof(struct bsd_db) + (sizeof(struct bsd_dict) * hsize);
368 db->hsize = hsize;
369 db->hshift = hshift;
370 db->maxmaxcode = maxmaxcode;
371 db->maxbits = bits;
372
373 return (void *)db;
374}
375
376/*
377 * Initialize the database.
378 */
379static int bsd_init(void *state, struct isdn_ppp_comp_data *data, int unit, int debug)
380{
381 struct bsd_db *db = state;
382 int indx;
383 int decomp;
384
385 if (!state || !data) {
386 printk(KERN_ERR "isdn_bsd_init: [%d] ERR, state %lx data %lx\n", unit, (long)state, (long)data);
387 return 0;
388 }
389
390 decomp = db->xmit ? 0 : 1;
391
392 if (data->optlen != 1 || data->num != CI_BSD_COMPRESS
393 || (BSD_VERSION(data->options[0]) != BSD_CURRENT_VERSION)
394 || (BSD_NBITS(data->options[0]) != db->maxbits)
395 || (decomp && db->lens == NULL)) {
396 printk(KERN_ERR "isdn_bsd: %d %d %d %d %lx\n", data->optlen, data->num, data->options[0], decomp, (unsigned long)db->lens);
397 return 0;
398 }
399
400 if (decomp)
401 for (indx = LAST; indx >= 0; indx--)
402 db->lens[indx] = 1;
403
404 indx = db->hsize;
405 while (indx-- != 0) {
406 db->dict[indx].codem1 = BADCODEM1;
407 db->dict[indx].cptr = 0;
408 }
409
410 db->unit = unit;
411 db->mru = 0;
412
413 db->debug = 1;
414
415 bsd_reset(db, 0, 0, NULL, 0, NULL);
416
417 return 1;
418}
419
420/*
421 * Obtain pointers to the various structures in the compression tables
422 */
423
424#define dict_ptrx(p, idx) &(p->dict[idx])
425#define lens_ptrx(p, idx) &(p->lens[idx])
426
427#ifdef DEBUG
428static unsigned short *lens_ptr(struct bsd_db *db, int idx)
429{
430 if ((unsigned int) idx > (unsigned int) db->maxmaxcode) {
431 printk(KERN_DEBUG "<9>ppp: lens_ptr(%d) > max\n", idx);
432 idx = 0;
433 }
434 return lens_ptrx(db, idx);
435}
436
437static struct bsd_dict *dict_ptr(struct bsd_db *db, int idx)
438{
439 if ((unsigned int) idx >= (unsigned int) db->hsize) {
440 printk(KERN_DEBUG "<9>ppp: dict_ptr(%d) > max\n", idx);
441 idx = 0;
442 }
443 return dict_ptrx(db, idx);
444}
445
446#else
447#define lens_ptr(db, idx) lens_ptrx(db, idx)
448#define dict_ptr(db, idx) dict_ptrx(db, idx)
449#endif
450
451/*
452 * compress a packet
453 */
454static int bsd_compress(void *state, struct sk_buff *skb_in, struct sk_buff *skb_out, int proto)
455{
456 struct bsd_db *db;
457 int hshift;
458 unsigned int max_ent;
459 unsigned int n_bits;
460 unsigned int bitno;
461 unsigned long accm;
462 int ent;
463 unsigned long fcode;
464 struct bsd_dict *dictp;
465 unsigned char c;
466 int hval, disp, ilen, mxcode;
467 unsigned char *rptr = skb_in->data;
468 int isize = skb_in->len;
469
470#define OUTPUT(ent) \
471 { \
472 bitno -= n_bits; \
473 accm |= ((ent) << bitno); \
474 do { \
475 if (skb_out && skb_tailroom(skb_out) > 0) \
476 skb_put_u8(skb_out, (u8)(accm >> 24)); \
477 accm <<= 8; \
478 bitno += 8; \
479 } while (bitno <= 24); \
480 }
481
482 /*
483 * If the protocol is not in the range we're interested in,
484 * just return without compressing the packet. If it is,
485 * the protocol becomes the first byte to compress.
486 */
487 printk(KERN_DEBUG "bsd_compress called with %x\n", proto);
488
489 ent = proto;
490 if (proto < 0x21 || proto > 0xf9 || !(proto & 0x1))
491 return 0;
492
493 db = (struct bsd_db *) state;
494 hshift = db->hshift;
495 max_ent = db->max_ent;
496 n_bits = db->n_bits;
497 bitno = 32;
498 accm = 0;
499 mxcode = MAXCODE(n_bits);
500
501 /* This is the PPP header information */
502 if (skb_out && skb_tailroom(skb_out) >= 2) {
503 char *v = skb_put(skb_out, 2);
504 /* we only push our own data on the header,
505 AC,PC and protos is pushed by caller */
506 v[0] = db->seqno >> 8;
507 v[1] = db->seqno;
508 }
509
510 ilen = ++isize; /* This is off by one, but that is what is in draft! */
511
512 while (--ilen > 0) {
513 c = *rptr++;
514 fcode = BSD_KEY(ent, c);
515 hval = BSD_HASH(ent, c, hshift);
516 dictp = dict_ptr(db, hval);
517
518 /* Validate and then check the entry. */
519 if (dictp->codem1 >= max_ent)
520 goto nomatch;
521
522 if (dictp->fcode == fcode) {
523 ent = dictp->codem1 + 1;
524 continue; /* found (prefix,suffix) */
525 }
526
527 /* continue probing until a match or invalid entry */
528 disp = (hval == 0) ? 1 : hval;
529
530 do {
531 hval += disp;
532 if (hval >= db->hsize)
533 hval -= db->hsize;
534 dictp = dict_ptr(db, hval);
535 if (dictp->codem1 >= max_ent)
536 goto nomatch;
537 } while (dictp->fcode != fcode);
538
539 ent = dictp->codem1 + 1; /* finally found (prefix,suffix) */
540 continue;
541
542 nomatch:
543 OUTPUT(ent); /* output the prefix */
544
545 /* code -> hashtable */
546 if (max_ent < db->maxmaxcode) {
547 struct bsd_dict *dictp2;
548 struct bsd_dict *dictp3;
549 int indx;
550
551 /* expand code size if needed */
552 if (max_ent >= mxcode) {
553 db->n_bits = ++n_bits;
554 mxcode = MAXCODE(n_bits);
555 }
556
557 /*
558 * Invalidate old hash table entry using
559 * this code, and then take it over.
560 */
561 dictp2 = dict_ptr(db, max_ent + 1);
562 indx = dictp2->cptr;
563 dictp3 = dict_ptr(db, indx);
564
565 if (dictp3->codem1 == max_ent)
566 dictp3->codem1 = BADCODEM1;
567
568 dictp2->cptr = hval;
569 dictp->codem1 = max_ent;
570 dictp->fcode = fcode;
571 db->max_ent = ++max_ent;
572
573 if (db->lens) {
574 unsigned short *len1 = lens_ptr(db, max_ent);
575 unsigned short *len2 = lens_ptr(db, ent);
576 *len1 = *len2 + 1;
577 }
578 }
579 ent = c;
580 }
581
582 OUTPUT(ent); /* output the last code */
583
584 if (skb_out)
585 db->bytes_out += skb_out->len; /* Do not count bytes from here */
586 db->uncomp_bytes += isize;
587 db->in_count += isize;
588 ++db->uncomp_count;
589 ++db->seqno;
590
591 if (bitno < 32)
592 ++db->bytes_out; /* must be set before calling bsd_check */
593
594 /*
595 * Generate the clear command if needed
596 */
597
598 if (bsd_check(db))
599 OUTPUT(CLEAR);
600
601 /*
602 * Pad dribble bits of last code with ones.
603 * Do not emit a completely useless byte of ones.
604 */
605 if (bitno < 32 && skb_out && skb_tailroom(skb_out) > 0)
606 skb_put_u8(skb_out,
607 (unsigned char)((accm | (0xff << (bitno - 8))) >> 24));
608
609 /*
610 * Increase code size if we would have without the packet
611 * boundary because the decompressor will do so.
612 */
613 if (max_ent >= mxcode && max_ent < db->maxmaxcode)
614 db->n_bits++;
615
616 /* If output length is too large then this is an incompressible frame. */
617 if (!skb_out || skb_out->len >= skb_in->len) {
618 ++db->incomp_count;
619 db->incomp_bytes += isize;
620 return 0;
621 }
622
623 /* Count the number of compressed frames */
624 ++db->comp_count;
625 db->comp_bytes += skb_out->len;
626 return skb_out->len;
627
628#undef OUTPUT
629}
630
631/*
632 * Update the "BSD Compress" dictionary on the receiver for
633 * incompressible data by pretending to compress the incoming data.
634 */
635static void bsd_incomp(void *state, struct sk_buff *skb_in, int proto)
636{
637 bsd_compress(state, skb_in, NULL, proto);
638}
639
640/*
641 * Decompress "BSD Compress".
642 */
643static int bsd_decompress(void *state, struct sk_buff *skb_in, struct sk_buff *skb_out,
644 struct isdn_ppp_resetparams *rsparm)
645{
646 struct bsd_db *db;
647 unsigned int max_ent;
648 unsigned long accm;
649 unsigned int bitno; /* 1st valid bit in accm */
650 unsigned int n_bits;
651 unsigned int tgtbitno; /* bitno when we have a code */
652 struct bsd_dict *dictp;
653 int seq;
654 unsigned int incode;
655 unsigned int oldcode;
656 unsigned int finchar;
657 unsigned char *p, *ibuf;
658 int ilen;
659 int codelen;
660 int extra;
661
662 db = (struct bsd_db *) state;
663 max_ent = db->max_ent;
664 accm = 0;
665 bitno = 32; /* 1st valid bit in accm */
666 n_bits = db->n_bits;
667 tgtbitno = 32 - n_bits; /* bitno when we have a code */
668
669 printk(KERN_DEBUG "bsd_decompress called\n");
670
671 if (!skb_in || !skb_out) {
672 printk(KERN_ERR "bsd_decompress called with NULL parameter\n");
673 return DECOMP_ERROR;
674 }
675
676 /*
677 * Get the sequence number.
678 */
679 if ((p = skb_pull(skb_in, 2)) == NULL) {
680 return DECOMP_ERROR;
681 }
682 p -= 2;
683 seq = (p[0] << 8) + p[1];
684 ilen = skb_in->len;
685 ibuf = skb_in->data;
686
687 /*
688 * Check the sequence number and give up if it differs from
689 * the value we're expecting.
690 */
691 if (seq != db->seqno) {
692 if (db->debug) {
693 printk(KERN_DEBUG "bsd_decomp%d: bad sequence # %d, expected %d\n",
694 db->unit, seq, db->seqno - 1);
695 }
696 return DECOMP_ERROR;
697 }
698
699 ++db->seqno;
700 db->bytes_out += ilen;
701
702 if (skb_tailroom(skb_out) > 0)
703 skb_put_u8(skb_out, 0);
704 else
705 return DECOMP_ERR_NOMEM;
706
707 oldcode = CLEAR;
708
709 /*
710 * Keep the checkpoint correctly so that incompressible packets
711 * clear the dictionary at the proper times.
712 */
713
714 for (;;) {
715 if (ilen-- <= 0) {
716 db->in_count += (skb_out->len - 1); /* don't count the header */
717 break;
718 }
719
720 /*
721 * Accumulate bytes until we have a complete code.
722 * Then get the next code, relying on the 32-bit,
723 * unsigned accm to mask the result.
724 */
725
726 bitno -= 8;
727 accm |= *ibuf++ << bitno;
728 if (tgtbitno < bitno)
729 continue;
730
731 incode = accm >> tgtbitno;
732 accm <<= n_bits;
733 bitno += n_bits;
734
735 /*
736 * The dictionary must only be cleared at the end of a packet.
737 */
738
739 if (incode == CLEAR) {
740 if (ilen > 0) {
741 if (db->debug)
742 printk(KERN_DEBUG "bsd_decomp%d: bad CLEAR\n", db->unit);
743 return DECOMP_FATALERROR; /* probably a bug */
744 }
745 bsd_clear(db);
746 break;
747 }
748
749 if ((incode > max_ent + 2) || (incode > db->maxmaxcode)
750 || (incode > max_ent && oldcode == CLEAR)) {
751 if (db->debug) {
752 printk(KERN_DEBUG "bsd_decomp%d: bad code 0x%x oldcode=0x%x ",
753 db->unit, incode, oldcode);
754 printk(KERN_DEBUG "max_ent=0x%x skb->Len=%d seqno=%d\n",
755 max_ent, skb_out->len, db->seqno);
756 }
757 return DECOMP_FATALERROR; /* probably a bug */
758 }
759
760 /* Special case for KwKwK string. */
761 if (incode > max_ent) {
762 finchar = oldcode;
763 extra = 1;
764 } else {
765 finchar = incode;
766 extra = 0;
767 }
768
769 codelen = *(lens_ptr(db, finchar));
770 if (skb_tailroom(skb_out) < codelen + extra) {
771 if (db->debug) {
772 printk(KERN_DEBUG "bsd_decomp%d: ran out of mru\n", db->unit);
773#ifdef DEBUG
774 printk(KERN_DEBUG " len=%d, finchar=0x%x, codelen=%d,skblen=%d\n",
775 ilen, finchar, codelen, skb_out->len);
776#endif
777 }
778 return DECOMP_FATALERROR;
779 }
780
781 /*
782 * Decode this code and install it in the decompressed buffer.
783 */
784
785 p = skb_put(skb_out, codelen);
786 p += codelen;
787 while (finchar > LAST) {
788 struct bsd_dict *dictp2 = dict_ptr(db, finchar);
789
790 dictp = dict_ptr(db, dictp2->cptr);
791
792#ifdef DEBUG
793 if (--codelen <= 0 || dictp->codem1 != finchar - 1) {
794 if (codelen <= 0) {
795 printk(KERN_ERR "bsd_decomp%d: fell off end of chain ", db->unit);
796 printk(KERN_ERR "0x%x at 0x%x by 0x%x, max_ent=0x%x\n", incode, finchar, dictp2->cptr, max_ent);
797 } else {
798 if (dictp->codem1 != finchar - 1) {
799 printk(KERN_ERR "bsd_decomp%d: bad code chain 0x%x finchar=0x%x ", db->unit, incode, finchar);
800 printk(KERN_ERR "oldcode=0x%x cptr=0x%x codem1=0x%x\n", oldcode, dictp2->cptr, dictp->codem1);
801 }
802 }
803 return DECOMP_FATALERROR;
804 }
805#endif
806
807 {
808 u32 fcode = dictp->fcode;
809 *--p = (fcode >> 16) & 0xff;
810 finchar = fcode & 0xffff;
811 }
812 }
813 *--p = finchar;
814
815#ifdef DEBUG
816 if (--codelen != 0)
817 printk(KERN_ERR "bsd_decomp%d: short by %d after code 0x%x, max_ent=0x%x\n", db->unit, codelen, incode, max_ent);
818#endif
819
820 if (extra) /* the KwKwK case again */
821 skb_put_u8(skb_out, finchar);
822
823 /*
824 * If not first code in a packet, and
825 * if not out of code space, then allocate a new code.
826 *
827 * Keep the hash table correct so it can be used
828 * with uncompressed packets.
829 */
830 if (oldcode != CLEAR && max_ent < db->maxmaxcode) {
831 struct bsd_dict *dictp2, *dictp3;
832 u16 *lens1, *lens2;
833 unsigned long fcode;
834 int hval, disp, indx;
835
836 fcode = BSD_KEY(oldcode, finchar);
837 hval = BSD_HASH(oldcode, finchar, db->hshift);
838 dictp = dict_ptr(db, hval);
839
840 /* look for a free hash table entry */
841 if (dictp->codem1 < max_ent) {
842 disp = (hval == 0) ? 1 : hval;
843 do {
844 hval += disp;
845 if (hval >= db->hsize)
846 hval -= db->hsize;
847 dictp = dict_ptr(db, hval);
848 } while (dictp->codem1 < max_ent);
849 }
850
851 /*
852 * Invalidate previous hash table entry
853 * assigned this code, and then take it over
854 */
855
856 dictp2 = dict_ptr(db, max_ent + 1);
857 indx = dictp2->cptr;
858 dictp3 = dict_ptr(db, indx);
859
860 if (dictp3->codem1 == max_ent)
861 dictp3->codem1 = BADCODEM1;
862
863 dictp2->cptr = hval;
864 dictp->codem1 = max_ent;
865 dictp->fcode = fcode;
866 db->max_ent = ++max_ent;
867
868 /* Update the length of this string. */
869 lens1 = lens_ptr(db, max_ent);
870 lens2 = lens_ptr(db, oldcode);
871 *lens1 = *lens2 + 1;
872
873 /* Expand code size if needed. */
874 if (max_ent >= MAXCODE(n_bits) && max_ent < db->maxmaxcode) {
875 db->n_bits = ++n_bits;
876 tgtbitno = 32-n_bits;
877 }
878 }
879 oldcode = incode;
880 }
881
882 ++db->comp_count;
883 ++db->uncomp_count;
884 db->comp_bytes += skb_in->len - BSD_OVHD;
885 db->uncomp_bytes += skb_out->len;
886
887 if (bsd_check(db)) {
888 if (db->debug)
889 printk(KERN_DEBUG "bsd_decomp%d: peer should have cleared dictionary on %d\n",
890 db->unit, db->seqno - 1);
891 }
892 return skb_out->len;
893}
894
895/*************************************************************
896 * Table of addresses for the BSD compression module
897 *************************************************************/
898
899static struct isdn_ppp_compressor ippp_bsd_compress = {
900 .owner = THIS_MODULE,
901 .num = CI_BSD_COMPRESS,
902 .alloc = bsd_alloc,
903 .free = bsd_free,
904 .init = bsd_init,
905 .reset = bsd_reset,
906 .compress = bsd_compress,
907 .decompress = bsd_decompress,
908 .incomp = bsd_incomp,
909 .stat = bsd_stats,
910};
911
912/*************************************************************
913 * Module support routines
914 *************************************************************/
915
916static int __init isdn_bsdcomp_init(void)
917{
918 int answer = isdn_ppp_register_compressor(&ippp_bsd_compress);
919 if (answer == 0)
920 printk(KERN_INFO "PPP BSD Compression module registered\n");
921 return answer;
922}
923
924static void __exit isdn_bsdcomp_exit(void)
925{
926 isdn_ppp_unregister_compressor(&ippp_bsd_compress);
927}
928
929module_init(isdn_bsdcomp_init);
930module_exit(isdn_bsdcomp_exit);
diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c
deleted file mode 100644
index 74ee00f5b310..000000000000
--- a/drivers/isdn/i4l/isdn_common.c
+++ /dev/null
@@ -1,2368 +0,0 @@
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/module.h>
15#include <linux/init.h>
16#include <linux/poll.h>
17#include <linux/slab.h>
18#include <linux/vmalloc.h>
19#include <linux/isdn.h>
20#include <linux/mutex.h>
21#include "isdn_common.h"
22#include "isdn_tty.h"
23#include "isdn_net.h"
24#include "isdn_ppp.h"
25#ifdef CONFIG_ISDN_AUDIO
26#include "isdn_audio.h"
27#endif
28#ifdef CONFIG_ISDN_DIVERSION_MODULE
29#define CONFIG_ISDN_DIVERSION
30#endif
31#ifdef CONFIG_ISDN_DIVERSION
32#include <linux/isdn_divertif.h>
33#endif /* CONFIG_ISDN_DIVERSION */
34#include "isdn_v110.h"
35
36/* Debugflags */
37#undef ISDN_DEBUG_STATCALLB
38
39MODULE_DESCRIPTION("ISDN4Linux: link layer");
40MODULE_AUTHOR("Fritz Elfert");
41MODULE_LICENSE("GPL");
42
43isdn_dev *dev;
44
45static DEFINE_MUTEX(isdn_mutex);
46static char *isdn_revision = "$Revision: 1.1.2.3 $";
47
48extern char *isdn_net_revision;
49#ifdef CONFIG_ISDN_PPP
50extern char *isdn_ppp_revision;
51#else
52static char *isdn_ppp_revision = ": none $";
53#endif
54#ifdef CONFIG_ISDN_AUDIO
55extern char *isdn_audio_revision;
56#else
57static char *isdn_audio_revision = ": none $";
58#endif
59extern char *isdn_v110_revision;
60
61#ifdef CONFIG_ISDN_DIVERSION
62static isdn_divert_if *divert_if; /* = NULL */
63#endif /* CONFIG_ISDN_DIVERSION */
64
65
66static int isdn_writebuf_stub(int, int, const u_char __user *, int);
67static void set_global_features(void);
68static int isdn_wildmat(char *s, char *p);
69static int isdn_add_channels(isdn_driver_t *d, int drvidx, int n, int adding);
70
71static inline void
72isdn_lock_driver(isdn_driver_t *drv)
73{
74 try_module_get(drv->interface->owner);
75 drv->locks++;
76}
77
78void
79isdn_lock_drivers(void)
80{
81 int i;
82
83 for (i = 0; i < ISDN_MAX_DRIVERS; i++) {
84 if (!dev->drv[i])
85 continue;
86 isdn_lock_driver(dev->drv[i]);
87 }
88}
89
90static inline void
91isdn_unlock_driver(isdn_driver_t *drv)
92{
93 if (drv->locks > 0) {
94 drv->locks--;
95 module_put(drv->interface->owner);
96 }
97}
98
99void
100isdn_unlock_drivers(void)
101{
102 int i;
103
104 for (i = 0; i < ISDN_MAX_DRIVERS; i++) {
105 if (!dev->drv[i])
106 continue;
107 isdn_unlock_driver(dev->drv[i]);
108 }
109}
110
111#if defined(ISDN_DEBUG_NET_DUMP) || defined(ISDN_DEBUG_MODEM_DUMP)
112void
113isdn_dumppkt(char *s, u_char *p, int len, int dumplen)
114{
115 int dumpc;
116
117 printk(KERN_DEBUG "%s(%d) ", s, len);
118 for (dumpc = 0; (dumpc < dumplen) && (len); len--, dumpc++)
119 printk(" %02x", *p++);
120 printk("\n");
121}
122#endif
123
124/*
125 * I picked the pattern-matching-functions from an old GNU-tar version (1.10)
126 * It was originally written and put to PD by rs@mirror.TMC.COM (Rich Salz)
127 */
128static int
129isdn_star(char *s, char *p)
130{
131 while (isdn_wildmat(s, p)) {
132 if (*++s == '\0')
133 return (2);
134 }
135 return (0);
136}
137
138/*
139 * Shell-type Pattern-matching for incoming caller-Ids
140 * This function gets a string in s and checks, if it matches the pattern
141 * given in p.
142 *
143 * Return:
144 * 0 = match.
145 * 1 = no match.
146 * 2 = no match. Would eventually match, if s would be longer.
147 *
148 * Possible Patterns:
149 *
150 * '?' matches one character
151 * '*' matches zero or more characters
152 * [xyz] matches the set of characters in brackets.
153 * [^xyz] matches any single character not in the set of characters
154 */
155
156static int
157isdn_wildmat(char *s, char *p)
158{
159 register int last;
160 register int matched;
161 register int reverse;
162 register int nostar = 1;
163
164 if (!(*s) && !(*p))
165 return (1);
166 for (; *p; s++, p++)
167 switch (*p) {
168 case '\\':
169 /* Literal match with following character. */
170 p++;
171 /* fall through */
172 default:
173 if (*s != *p)
174 return (*s == '\0') ? 2 : 1;
175 continue;
176 case '?':
177 /* Match anything. */
178 if (*s == '\0')
179 return (2);
180 continue;
181 case '*':
182 nostar = 0;
183 /* Trailing star matches everything. */
184 return (*++p ? isdn_star(s, p) : 0);
185 case '[':
186 /* [^....] means inverse character class. */
187 if ((reverse = (p[1] == '^')))
188 p++;
189 for (last = 0, matched = 0; *++p && (*p != ']'); last = *p)
190 /* This next line requires a good C compiler. */
191 if (*p == '-' ? *s <= *++p && *s >= last : *s == *p)
192 matched = 1;
193 if (matched == reverse)
194 return (1);
195 continue;
196 }
197 return (*s == '\0') ? 0 : nostar;
198}
199
200int isdn_msncmp(const char *msn1, const char *msn2)
201{
202 char TmpMsn1[ISDN_MSNLEN];
203 char TmpMsn2[ISDN_MSNLEN];
204 char *p;
205
206 for (p = TmpMsn1; *msn1 && *msn1 != ':';) // Strip off a SPID
207 *p++ = *msn1++;
208 *p = '\0';
209
210 for (p = TmpMsn2; *msn2 && *msn2 != ':';) // Strip off a SPID
211 *p++ = *msn2++;
212 *p = '\0';
213
214 return isdn_wildmat(TmpMsn1, TmpMsn2);
215}
216
217int
218isdn_dc2minor(int di, int ch)
219{
220 int i;
221 for (i = 0; i < ISDN_MAX_CHANNELS; i++)
222 if (dev->chanmap[i] == ch && dev->drvmap[i] == di)
223 return i;
224 return -1;
225}
226
227static int isdn_timer_cnt1 = 0;
228static int isdn_timer_cnt2 = 0;
229static int isdn_timer_cnt3 = 0;
230
231static void
232isdn_timer_funct(struct timer_list *unused)
233{
234 int tf = dev->tflags;
235 if (tf & ISDN_TIMER_FAST) {
236 if (tf & ISDN_TIMER_MODEMREAD)
237 isdn_tty_readmodem();
238 if (tf & ISDN_TIMER_MODEMPLUS)
239 isdn_tty_modem_escape();
240 if (tf & ISDN_TIMER_MODEMXMIT)
241 isdn_tty_modem_xmit();
242 }
243 if (tf & ISDN_TIMER_SLOW) {
244 if (++isdn_timer_cnt1 >= ISDN_TIMER_02SEC) {
245 isdn_timer_cnt1 = 0;
246 if (tf & ISDN_TIMER_NETDIAL)
247 isdn_net_dial();
248 }
249 if (++isdn_timer_cnt2 >= ISDN_TIMER_1SEC) {
250 isdn_timer_cnt2 = 0;
251 if (tf & ISDN_TIMER_NETHANGUP)
252 isdn_net_autohup();
253 if (++isdn_timer_cnt3 >= ISDN_TIMER_RINGING) {
254 isdn_timer_cnt3 = 0;
255 if (tf & ISDN_TIMER_MODEMRING)
256 isdn_tty_modem_ring();
257 }
258 if (tf & ISDN_TIMER_CARRIER)
259 isdn_tty_carrier_timeout();
260 }
261 }
262 if (tf)
263 mod_timer(&dev->timer, jiffies + ISDN_TIMER_RES);
264}
265
266void
267isdn_timer_ctrl(int tf, int onoff)
268{
269 unsigned long flags;
270 int old_tflags;
271
272 spin_lock_irqsave(&dev->timerlock, flags);
273 if ((tf & ISDN_TIMER_SLOW) && (!(dev->tflags & ISDN_TIMER_SLOW))) {
274 /* If the slow-timer wasn't activated until now */
275 isdn_timer_cnt1 = 0;
276 isdn_timer_cnt2 = 0;
277 }
278 old_tflags = dev->tflags;
279 if (onoff)
280 dev->tflags |= tf;
281 else
282 dev->tflags &= ~tf;
283 if (dev->tflags && !old_tflags)
284 mod_timer(&dev->timer, jiffies + ISDN_TIMER_RES);
285 spin_unlock_irqrestore(&dev->timerlock, flags);
286}
287
288/*
289 * Receive a packet from B-Channel. (Called from low-level-module)
290 */
291static void
292isdn_receive_skb_callback(int di, int channel, struct sk_buff *skb)
293{
294 int i;
295
296 if ((i = isdn_dc2minor(di, channel)) == -1) {
297 dev_kfree_skb(skb);
298 return;
299 }
300 /* Update statistics */
301 dev->ibytes[i] += skb->len;
302
303 /* First, try to deliver data to network-device */
304 if (isdn_net_rcv_skb(i, skb))
305 return;
306
307 /* V.110 handling
308 * makes sense for async streams only, so it is
309 * called after possible net-device delivery.
310 */
311 if (dev->v110[i]) {
312 atomic_inc(&dev->v110use[i]);
313 skb = isdn_v110_decode(dev->v110[i], skb);
314 atomic_dec(&dev->v110use[i]);
315 if (!skb)
316 return;
317 }
318
319 /* No network-device found, deliver to tty or raw-channel */
320 if (skb->len) {
321 if (isdn_tty_rcv_skb(i, di, channel, skb))
322 return;
323 wake_up_interruptible(&dev->drv[di]->rcv_waitq[channel]);
324 } else
325 dev_kfree_skb(skb);
326}
327
328/*
329 * Intercept command from Linklevel to Lowlevel.
330 * If layer 2 protocol is V.110 and this is not supported by current
331 * lowlevel-driver, use driver's transparent mode and handle V.110 in
332 * linklevel instead.
333 */
334int
335isdn_command(isdn_ctrl *cmd)
336{
337 if (cmd->driver == -1) {
338 printk(KERN_WARNING "isdn_command command(%x) driver -1\n", cmd->command);
339 return (1);
340 }
341 if (!dev->drv[cmd->driver]) {
342 printk(KERN_WARNING "isdn_command command(%x) dev->drv[%d] NULL\n",
343 cmd->command, cmd->driver);
344 return (1);
345 }
346 if (!dev->drv[cmd->driver]->interface) {
347 printk(KERN_WARNING "isdn_command command(%x) dev->drv[%d]->interface NULL\n",
348 cmd->command, cmd->driver);
349 return (1);
350 }
351 if (cmd->command == ISDN_CMD_SETL2) {
352 int idx = isdn_dc2minor(cmd->driver, cmd->arg & 255);
353 unsigned long l2prot = (cmd->arg >> 8) & 255;
354 unsigned long features = (dev->drv[cmd->driver]->interface->features
355 >> ISDN_FEATURE_L2_SHIFT) &
356 ISDN_FEATURE_L2_MASK;
357 unsigned long l2_feature = (1 << l2prot);
358
359 switch (l2prot) {
360 case ISDN_PROTO_L2_V11096:
361 case ISDN_PROTO_L2_V11019:
362 case ISDN_PROTO_L2_V11038:
363 /* If V.110 requested, but not supported by
364 * HL-driver, set emulator-flag and change
365 * Layer-2 to transparent
366 */
367 if (!(features & l2_feature)) {
368 dev->v110emu[idx] = l2prot;
369 cmd->arg = (cmd->arg & 255) |
370 (ISDN_PROTO_L2_TRANS << 8);
371 } else
372 dev->v110emu[idx] = 0;
373 }
374 }
375 return dev->drv[cmd->driver]->interface->command(cmd);
376}
377
378void
379isdn_all_eaz(int di, int ch)
380{
381 isdn_ctrl cmd;
382
383 if (di < 0)
384 return;
385 cmd.driver = di;
386 cmd.arg = ch;
387 cmd.command = ISDN_CMD_SETEAZ;
388 cmd.parm.num[0] = '\0';
389 isdn_command(&cmd);
390}
391
392/*
393 * Begin of a CAPI like LL<->HL interface, currently used only for
394 * supplementary service (CAPI 2.0 part III)
395 */
396#include <linux/isdn/capicmd.h>
397
398static int
399isdn_capi_rec_hl_msg(capi_msg *cm)
400{
401 switch (cm->Command) {
402 case CAPI_FACILITY:
403 /* in the moment only handled in tty */
404 return (isdn_tty_capi_facility(cm));
405 default:
406 return (-1);
407 }
408}
409
410static int
411isdn_status_callback(isdn_ctrl *c)
412{
413 int di;
414 u_long flags;
415 int i;
416 int r;
417 int retval = 0;
418 isdn_ctrl cmd;
419 isdn_net_dev *p;
420
421 di = c->driver;
422 i = isdn_dc2minor(di, c->arg);
423 switch (c->command) {
424 case ISDN_STAT_BSENT:
425 if (i < 0)
426 return -1;
427 if (dev->global_flags & ISDN_GLOBAL_STOPPED)
428 return 0;
429 if (isdn_net_stat_callback(i, c))
430 return 0;
431 if (isdn_v110_stat_callback(i, c))
432 return 0;
433 if (isdn_tty_stat_callback(i, c))
434 return 0;
435 wake_up_interruptible(&dev->drv[di]->snd_waitq[c->arg]);
436 break;
437 case ISDN_STAT_STAVAIL:
438 dev->drv[di]->stavail += c->arg;
439 wake_up_interruptible(&dev->drv[di]->st_waitq);
440 break;
441 case ISDN_STAT_RUN:
442 dev->drv[di]->flags |= DRV_FLAG_RUNNING;
443 for (i = 0; i < ISDN_MAX_CHANNELS; i++)
444 if (dev->drvmap[i] == di)
445 isdn_all_eaz(di, dev->chanmap[i]);
446 set_global_features();
447 break;
448 case ISDN_STAT_STOP:
449 dev->drv[di]->flags &= ~DRV_FLAG_RUNNING;
450 break;
451 case ISDN_STAT_ICALL:
452 if (i < 0)
453 return -1;
454#ifdef ISDN_DEBUG_STATCALLB
455 printk(KERN_DEBUG "ICALL (net): %d %ld %s\n", di, c->arg, c->parm.num);
456#endif
457 if (dev->global_flags & ISDN_GLOBAL_STOPPED) {
458 cmd.driver = di;
459 cmd.arg = c->arg;
460 cmd.command = ISDN_CMD_HANGUP;
461 isdn_command(&cmd);
462 return 0;
463 }
464 /* Try to find a network-interface which will accept incoming call */
465 r = ((c->command == ISDN_STAT_ICALLW) ? 0 : isdn_net_find_icall(di, c->arg, i, &c->parm.setup));
466 switch (r) {
467 case 0:
468 /* No network-device replies.
469 * Try ttyI's.
470 * These return 0 on no match, 1 on match and
471 * 3 on eventually match, if CID is longer.
472 */
473 if (c->command == ISDN_STAT_ICALL)
474 if ((retval = isdn_tty_find_icall(di, c->arg, &c->parm.setup))) return (retval);
475#ifdef CONFIG_ISDN_DIVERSION
476 if (divert_if)
477 if ((retval = divert_if->stat_callback(c)))
478 return (retval); /* processed */
479#endif /* CONFIG_ISDN_DIVERSION */
480 if ((!retval) && (dev->drv[di]->flags & DRV_FLAG_REJBUS)) {
481 /* No tty responding */
482 cmd.driver = di;
483 cmd.arg = c->arg;
484 cmd.command = ISDN_CMD_HANGUP;
485 isdn_command(&cmd);
486 retval = 2;
487 }
488 break;
489 case 1:
490 /* Schedule connection-setup */
491 isdn_net_dial();
492 cmd.driver = di;
493 cmd.arg = c->arg;
494 cmd.command = ISDN_CMD_ACCEPTD;
495 for (p = dev->netdev; p; p = p->next)
496 if (p->local->isdn_channel == cmd.arg)
497 {
498 strcpy(cmd.parm.setup.eazmsn, p->local->msn);
499 isdn_command(&cmd);
500 retval = 1;
501 break;
502 }
503 break;
504
505 case 2: /* For calling back, first reject incoming call ... */
506 case 3: /* Interface found, but down, reject call actively */
507 retval = 2;
508 printk(KERN_INFO "isdn: Rejecting Call\n");
509 cmd.driver = di;
510 cmd.arg = c->arg;
511 cmd.command = ISDN_CMD_HANGUP;
512 isdn_command(&cmd);
513 if (r == 3)
514 break;
515 /* Fall through */
516 case 4:
517 /* ... then start callback. */
518 isdn_net_dial();
519 break;
520 case 5:
521 /* Number would eventually match, if longer */
522 retval = 3;
523 break;
524 }
525#ifdef ISDN_DEBUG_STATCALLB
526 printk(KERN_DEBUG "ICALL: ret=%d\n", retval);
527#endif
528 return retval;
529 break;
530 case ISDN_STAT_CINF:
531 if (i < 0)
532 return -1;
533#ifdef ISDN_DEBUG_STATCALLB
534 printk(KERN_DEBUG "CINF: %ld %s\n", c->arg, c->parm.num);
535#endif
536 if (dev->global_flags & ISDN_GLOBAL_STOPPED)
537 return 0;
538 if (strcmp(c->parm.num, "0"))
539 isdn_net_stat_callback(i, c);
540 isdn_tty_stat_callback(i, c);
541 break;
542 case ISDN_STAT_CAUSE:
543#ifdef ISDN_DEBUG_STATCALLB
544 printk(KERN_DEBUG "CAUSE: %ld %s\n", c->arg, c->parm.num);
545#endif
546 printk(KERN_INFO "isdn: %s,ch%ld cause: %s\n",
547 dev->drvid[di], c->arg, c->parm.num);
548 isdn_tty_stat_callback(i, c);
549#ifdef CONFIG_ISDN_DIVERSION
550 if (divert_if)
551 divert_if->stat_callback(c);
552#endif /* CONFIG_ISDN_DIVERSION */
553 break;
554 case ISDN_STAT_DISPLAY:
555#ifdef ISDN_DEBUG_STATCALLB
556 printk(KERN_DEBUG "DISPLAY: %ld %s\n", c->arg, c->parm.display);
557#endif
558 isdn_tty_stat_callback(i, c);
559#ifdef CONFIG_ISDN_DIVERSION
560 if (divert_if)
561 divert_if->stat_callback(c);
562#endif /* CONFIG_ISDN_DIVERSION */
563 break;
564 case ISDN_STAT_DCONN:
565 if (i < 0)
566 return -1;
567#ifdef ISDN_DEBUG_STATCALLB
568 printk(KERN_DEBUG "DCONN: %ld\n", c->arg);
569#endif
570 if (dev->global_flags & ISDN_GLOBAL_STOPPED)
571 return 0;
572 /* Find any net-device, waiting for D-channel setup */
573 if (isdn_net_stat_callback(i, c))
574 break;
575 isdn_v110_stat_callback(i, c);
576 /* Find any ttyI, waiting for D-channel setup */
577 if (isdn_tty_stat_callback(i, c)) {
578 cmd.driver = di;
579 cmd.arg = c->arg;
580 cmd.command = ISDN_CMD_ACCEPTB;
581 isdn_command(&cmd);
582 break;
583 }
584 break;
585 case ISDN_STAT_DHUP:
586 if (i < 0)
587 return -1;
588#ifdef ISDN_DEBUG_STATCALLB
589 printk(KERN_DEBUG "DHUP: %ld\n", c->arg);
590#endif
591 if (dev->global_flags & ISDN_GLOBAL_STOPPED)
592 return 0;
593 dev->drv[di]->online &= ~(1 << (c->arg));
594 isdn_info_update();
595 /* Signal hangup to network-devices */
596 if (isdn_net_stat_callback(i, c))
597 break;
598 isdn_v110_stat_callback(i, c);
599 if (isdn_tty_stat_callback(i, c))
600 break;
601#ifdef CONFIG_ISDN_DIVERSION
602 if (divert_if)
603 divert_if->stat_callback(c);
604#endif /* CONFIG_ISDN_DIVERSION */
605 break;
606 break;
607 case ISDN_STAT_BCONN:
608 if (i < 0)
609 return -1;
610#ifdef ISDN_DEBUG_STATCALLB
611 printk(KERN_DEBUG "BCONN: %ld\n", c->arg);
612#endif
613 /* Signal B-channel-connect to network-devices */
614 if (dev->global_flags & ISDN_GLOBAL_STOPPED)
615 return 0;
616 dev->drv[di]->online |= (1 << (c->arg));
617 isdn_info_update();
618 if (isdn_net_stat_callback(i, c))
619 break;
620 isdn_v110_stat_callback(i, c);
621 if (isdn_tty_stat_callback(i, c))
622 break;
623 break;
624 case ISDN_STAT_BHUP:
625 if (i < 0)
626 return -1;
627#ifdef ISDN_DEBUG_STATCALLB
628 printk(KERN_DEBUG "BHUP: %ld\n", c->arg);
629#endif
630 if (dev->global_flags & ISDN_GLOBAL_STOPPED)
631 return 0;
632 dev->drv[di]->online &= ~(1 << (c->arg));
633 isdn_info_update();
634#ifdef CONFIG_ISDN_X25
635 /* Signal hangup to network-devices */
636 if (isdn_net_stat_callback(i, c))
637 break;
638#endif
639 isdn_v110_stat_callback(i, c);
640 if (isdn_tty_stat_callback(i, c))
641 break;
642 break;
643 case ISDN_STAT_NODCH:
644 if (i < 0)
645 return -1;
646#ifdef ISDN_DEBUG_STATCALLB
647 printk(KERN_DEBUG "NODCH: %ld\n", c->arg);
648#endif
649 if (dev->global_flags & ISDN_GLOBAL_STOPPED)
650 return 0;
651 if (isdn_net_stat_callback(i, c))
652 break;
653 if (isdn_tty_stat_callback(i, c))
654 break;
655 break;
656 case ISDN_STAT_ADDCH:
657 spin_lock_irqsave(&dev->lock, flags);
658 if (isdn_add_channels(dev->drv[di], di, c->arg, 1)) {
659 spin_unlock_irqrestore(&dev->lock, flags);
660 return -1;
661 }
662 spin_unlock_irqrestore(&dev->lock, flags);
663 isdn_info_update();
664 break;
665 case ISDN_STAT_DISCH:
666 spin_lock_irqsave(&dev->lock, flags);
667 for (i = 0; i < ISDN_MAX_CHANNELS; i++)
668 if ((dev->drvmap[i] == di) &&
669 (dev->chanmap[i] == c->arg)) {
670 if (c->parm.num[0])
671 dev->usage[i] &= ~ISDN_USAGE_DISABLED;
672 else
673 if (USG_NONE(dev->usage[i])) {
674 dev->usage[i] |= ISDN_USAGE_DISABLED;
675 }
676 else
677 retval = -1;
678 break;
679 }
680 spin_unlock_irqrestore(&dev->lock, flags);
681 isdn_info_update();
682 break;
683 case ISDN_STAT_UNLOAD:
684 while (dev->drv[di]->locks > 0) {
685 isdn_unlock_driver(dev->drv[di]);
686 }
687 spin_lock_irqsave(&dev->lock, flags);
688 isdn_tty_stat_callback(i, c);
689 for (i = 0; i < ISDN_MAX_CHANNELS; i++)
690 if (dev->drvmap[i] == di) {
691 dev->drvmap[i] = -1;
692 dev->chanmap[i] = -1;
693 dev->usage[i] &= ~ISDN_USAGE_DISABLED;
694 }
695 dev->drivers--;
696 dev->channels -= dev->drv[di]->channels;
697 kfree(dev->drv[di]->rcverr);
698 kfree(dev->drv[di]->rcvcount);
699 for (i = 0; i < dev->drv[di]->channels; i++)
700 skb_queue_purge(&dev->drv[di]->rpqueue[i]);
701 kfree(dev->drv[di]->rpqueue);
702 kfree(dev->drv[di]->rcv_waitq);
703 kfree(dev->drv[di]);
704 dev->drv[di] = NULL;
705 dev->drvid[di][0] = '\0';
706 isdn_info_update();
707 set_global_features();
708 spin_unlock_irqrestore(&dev->lock, flags);
709 return 0;
710 case ISDN_STAT_L1ERR:
711 break;
712 case CAPI_PUT_MESSAGE:
713 return (isdn_capi_rec_hl_msg(&c->parm.cmsg));
714#ifdef CONFIG_ISDN_TTY_FAX
715 case ISDN_STAT_FAXIND:
716 isdn_tty_stat_callback(i, c);
717 break;
718#endif
719#ifdef CONFIG_ISDN_AUDIO
720 case ISDN_STAT_AUDIO:
721 isdn_tty_stat_callback(i, c);
722 break;
723#endif
724#ifdef CONFIG_ISDN_DIVERSION
725 case ISDN_STAT_PROT:
726 case ISDN_STAT_REDIR:
727 if (divert_if)
728 return (divert_if->stat_callback(c));
729#endif /* CONFIG_ISDN_DIVERSION */
730 /* fall through */
731 default:
732 return -1;
733 }
734 return 0;
735}
736
737/*
738 * Get integer from char-pointer, set pointer to end of number
739 */
740int
741isdn_getnum(char **p)
742{
743 int v = -1;
744
745 while (*p[0] >= '0' && *p[0] <= '9')
746 v = ((v < 0) ? 0 : (v * 10)) + (int) ((*p[0]++) - '0');
747 return v;
748}
749
750#define DLE 0x10
751
752/*
753 * isdn_readbchan() tries to get data from the read-queue.
754 * It MUST be called with interrupts off.
755 *
756 * Be aware that this is not an atomic operation when sleep != 0, even though
757 * interrupts are turned off! Well, like that we are currently only called
758 * on behalf of a read system call on raw device files (which are documented
759 * to be dangerous and for debugging purpose only). The inode semaphore
760 * takes care that this is not called for the same minor device number while
761 * we are sleeping, but access is not serialized against simultaneous read()
762 * from the corresponding ttyI device. Can other ugly events, like changes
763 * of the mapping (di,ch)<->minor, happen during the sleep? --he
764 */
765int
766isdn_readbchan(int di, int channel, u_char *buf, u_char *fp, int len, wait_queue_head_t *sleep)
767{
768 int count;
769 int count_pull;
770 int count_put;
771 int dflag;
772 struct sk_buff *skb;
773 u_char *cp;
774
775 if (!dev->drv[di])
776 return 0;
777 if (skb_queue_empty(&dev->drv[di]->rpqueue[channel])) {
778 if (sleep)
779 wait_event_interruptible(*sleep,
780 !skb_queue_empty(&dev->drv[di]->rpqueue[channel]));
781 else
782 return 0;
783 }
784 if (len > dev->drv[di]->rcvcount[channel])
785 len = dev->drv[di]->rcvcount[channel];
786 cp = buf;
787 count = 0;
788 while (len) {
789 if (!(skb = skb_peek(&dev->drv[di]->rpqueue[channel])))
790 break;
791#ifdef CONFIG_ISDN_AUDIO
792 if (ISDN_AUDIO_SKB_LOCK(skb))
793 break;
794 ISDN_AUDIO_SKB_LOCK(skb) = 1;
795 if ((ISDN_AUDIO_SKB_DLECOUNT(skb)) || (dev->drv[di]->DLEflag & (1 << channel))) {
796 char *p = skb->data;
797 unsigned long DLEmask = (1 << channel);
798
799 dflag = 0;
800 count_pull = count_put = 0;
801 while ((count_pull < skb->len) && (len > 0)) {
802 len--;
803 if (dev->drv[di]->DLEflag & DLEmask) {
804 *cp++ = DLE;
805 dev->drv[di]->DLEflag &= ~DLEmask;
806 } else {
807 *cp++ = *p;
808 if (*p == DLE) {
809 dev->drv[di]->DLEflag |= DLEmask;
810 (ISDN_AUDIO_SKB_DLECOUNT(skb))--;
811 }
812 p++;
813 count_pull++;
814 }
815 count_put++;
816 }
817 if (count_pull >= skb->len)
818 dflag = 1;
819 } else {
820#endif
821 /* No DLE's in buff, so simply copy it */
822 dflag = 1;
823 if ((count_pull = skb->len) > len) {
824 count_pull = len;
825 dflag = 0;
826 }
827 count_put = count_pull;
828 skb_copy_from_linear_data(skb, cp, count_put);
829 cp += count_put;
830 len -= count_put;
831#ifdef CONFIG_ISDN_AUDIO
832 }
833#endif
834 count += count_put;
835 if (fp) {
836 memset(fp, 0, count_put);
837 fp += count_put;
838 }
839 if (dflag) {
840 /* We got all the data in this buff.
841 * Now we can dequeue it.
842 */
843 if (fp)
844 *(fp - 1) = 0xff;
845#ifdef CONFIG_ISDN_AUDIO
846 ISDN_AUDIO_SKB_LOCK(skb) = 0;
847#endif
848 skb = skb_dequeue(&dev->drv[di]->rpqueue[channel]);
849 dev_kfree_skb(skb);
850 } else {
851 /* Not yet emptied this buff, so it
852 * must stay in the queue, for further calls
853 * but we pull off the data we got until now.
854 */
855 skb_pull(skb, count_pull);
856#ifdef CONFIG_ISDN_AUDIO
857 ISDN_AUDIO_SKB_LOCK(skb) = 0;
858#endif
859 }
860 dev->drv[di]->rcvcount[channel] -= count_put;
861 }
862 return count;
863}
864
865/*
866 * isdn_readbchan_tty() tries to get data from the read-queue.
867 * It MUST be called with interrupts off.
868 *
869 * Be aware that this is not an atomic operation when sleep != 0, even though
870 * interrupts are turned off! Well, like that we are currently only called
871 * on behalf of a read system call on raw device files (which are documented
872 * to be dangerous and for debugging purpose only). The inode semaphore
873 * takes care that this is not called for the same minor device number while
874 * we are sleeping, but access is not serialized against simultaneous read()
875 * from the corresponding ttyI device. Can other ugly events, like changes
876 * of the mapping (di,ch)<->minor, happen during the sleep? --he
877 */
878int
879isdn_readbchan_tty(int di, int channel, struct tty_port *port, int cisco_hack)
880{
881 int count;
882 int count_pull;
883 int count_put;
884 int dflag;
885 struct sk_buff *skb;
886 char last = 0;
887 int len;
888
889 if (!dev->drv[di])
890 return 0;
891 if (skb_queue_empty(&dev->drv[di]->rpqueue[channel]))
892 return 0;
893
894 len = tty_buffer_request_room(port, dev->drv[di]->rcvcount[channel]);
895 if (len == 0)
896 return len;
897
898 count = 0;
899 while (len) {
900 if (!(skb = skb_peek(&dev->drv[di]->rpqueue[channel])))
901 break;
902#ifdef CONFIG_ISDN_AUDIO
903 if (ISDN_AUDIO_SKB_LOCK(skb))
904 break;
905 ISDN_AUDIO_SKB_LOCK(skb) = 1;
906 if ((ISDN_AUDIO_SKB_DLECOUNT(skb)) || (dev->drv[di]->DLEflag & (1 << channel))) {
907 char *p = skb->data;
908 unsigned long DLEmask = (1 << channel);
909
910 dflag = 0;
911 count_pull = count_put = 0;
912 while ((count_pull < skb->len) && (len > 0)) {
913 /* push every character but the last to the tty buffer directly */
914 if (count_put)
915 tty_insert_flip_char(port, last, TTY_NORMAL);
916 len--;
917 if (dev->drv[di]->DLEflag & DLEmask) {
918 last = DLE;
919 dev->drv[di]->DLEflag &= ~DLEmask;
920 } else {
921 last = *p;
922 if (last == DLE) {
923 dev->drv[di]->DLEflag |= DLEmask;
924 (ISDN_AUDIO_SKB_DLECOUNT(skb))--;
925 }
926 p++;
927 count_pull++;
928 }
929 count_put++;
930 }
931 if (count_pull >= skb->len)
932 dflag = 1;
933 } else {
934#endif
935 /* No DLE's in buff, so simply copy it */
936 dflag = 1;
937 if ((count_pull = skb->len) > len) {
938 count_pull = len;
939 dflag = 0;
940 }
941 count_put = count_pull;
942 if (count_put > 1)
943 tty_insert_flip_string(port, skb->data, count_put - 1);
944 last = skb->data[count_put - 1];
945 len -= count_put;
946#ifdef CONFIG_ISDN_AUDIO
947 }
948#endif
949 count += count_put;
950 if (dflag) {
951 /* We got all the data in this buff.
952 * Now we can dequeue it.
953 */
954 if (cisco_hack)
955 tty_insert_flip_char(port, last, 0xFF);
956 else
957 tty_insert_flip_char(port, last, TTY_NORMAL);
958#ifdef CONFIG_ISDN_AUDIO
959 ISDN_AUDIO_SKB_LOCK(skb) = 0;
960#endif
961 skb = skb_dequeue(&dev->drv[di]->rpqueue[channel]);
962 dev_kfree_skb(skb);
963 } else {
964 tty_insert_flip_char(port, last, TTY_NORMAL);
965 /* Not yet emptied this buff, so it
966 * must stay in the queue, for further calls
967 * but we pull off the data we got until now.
968 */
969 skb_pull(skb, count_pull);
970#ifdef CONFIG_ISDN_AUDIO
971 ISDN_AUDIO_SKB_LOCK(skb) = 0;
972#endif
973 }
974 dev->drv[di]->rcvcount[channel] -= count_put;
975 }
976 return count;
977}
978
979
980static inline int
981isdn_minor2drv(int minor)
982{
983 return (dev->drvmap[minor]);
984}
985
986static inline int
987isdn_minor2chan(int minor)
988{
989 return (dev->chanmap[minor]);
990}
991
992static char *
993isdn_statstr(void)
994{
995 static char istatbuf[2048];
996 char *p;
997 int i;
998
999 sprintf(istatbuf, "idmap:\t");
1000 p = istatbuf + strlen(istatbuf);
1001 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
1002 sprintf(p, "%s ", (dev->drvmap[i] < 0) ? "-" : dev->drvid[dev->drvmap[i]]);
1003 p = istatbuf + strlen(istatbuf);
1004 }
1005 sprintf(p, "\nchmap:\t");
1006 p = istatbuf + strlen(istatbuf);
1007 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
1008 sprintf(p, "%d ", dev->chanmap[i]);
1009 p = istatbuf + strlen(istatbuf);
1010 }
1011 sprintf(p, "\ndrmap:\t");
1012 p = istatbuf + strlen(istatbuf);
1013 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
1014 sprintf(p, "%d ", dev->drvmap[i]);
1015 p = istatbuf + strlen(istatbuf);
1016 }
1017 sprintf(p, "\nusage:\t");
1018 p = istatbuf + strlen(istatbuf);
1019 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
1020 sprintf(p, "%d ", dev->usage[i]);
1021 p = istatbuf + strlen(istatbuf);
1022 }
1023 sprintf(p, "\nflags:\t");
1024 p = istatbuf + strlen(istatbuf);
1025 for (i = 0; i < ISDN_MAX_DRIVERS; i++) {
1026 if (dev->drv[i]) {
1027 sprintf(p, "%ld ", dev->drv[i]->online);
1028 p = istatbuf + strlen(istatbuf);
1029 } else {
1030 sprintf(p, "? ");
1031 p = istatbuf + strlen(istatbuf);
1032 }
1033 }
1034 sprintf(p, "\nphone:\t");
1035 p = istatbuf + strlen(istatbuf);
1036 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
1037 sprintf(p, "%s ", dev->num[i]);
1038 p = istatbuf + strlen(istatbuf);
1039 }
1040 sprintf(p, "\n");
1041 return istatbuf;
1042}
1043
1044/* Module interface-code */
1045
1046void
1047isdn_info_update(void)
1048{
1049 infostruct *p = dev->infochain;
1050
1051 while (p) {
1052 *(p->private) = 1;
1053 p = (infostruct *) p->next;
1054 }
1055 wake_up_interruptible(&(dev->info_waitq));
1056}
1057
1058static ssize_t
1059isdn_read(struct file *file, char __user *buf, size_t count, loff_t *off)
1060{
1061 uint minor = iminor(file_inode(file));
1062 int len = 0;
1063 int drvidx;
1064 int chidx;
1065 int retval;
1066 char *p;
1067
1068 mutex_lock(&isdn_mutex);
1069 if (minor == ISDN_MINOR_STATUS) {
1070 if (!file->private_data) {
1071 if (file->f_flags & O_NONBLOCK) {
1072 retval = -EAGAIN;
1073 goto out;
1074 }
1075 wait_event_interruptible(dev->info_waitq,
1076 file->private_data);
1077 }
1078 p = isdn_statstr();
1079 file->private_data = NULL;
1080 if ((len = strlen(p)) <= count) {
1081 if (copy_to_user(buf, p, len)) {
1082 retval = -EFAULT;
1083 goto out;
1084 }
1085 *off += len;
1086 retval = len;
1087 goto out;
1088 }
1089 retval = 0;
1090 goto out;
1091 }
1092 if (!dev->drivers) {
1093 retval = -ENODEV;
1094 goto out;
1095 }
1096 if (minor <= ISDN_MINOR_BMAX) {
1097 printk(KERN_WARNING "isdn_read minor %d obsolete!\n", minor);
1098 drvidx = isdn_minor2drv(minor);
1099 if (drvidx < 0) {
1100 retval = -ENODEV;
1101 goto out;
1102 }
1103 if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING)) {
1104 retval = -ENODEV;
1105 goto out;
1106 }
1107 chidx = isdn_minor2chan(minor);
1108 if (!(p = kmalloc(count, GFP_KERNEL))) {
1109 retval = -ENOMEM;
1110 goto out;
1111 }
1112 len = isdn_readbchan(drvidx, chidx, p, NULL, count,
1113 &dev->drv[drvidx]->rcv_waitq[chidx]);
1114 *off += len;
1115 if (copy_to_user(buf, p, len))
1116 len = -EFAULT;
1117 kfree(p);
1118 retval = len;
1119 goto out;
1120 }
1121 if (minor <= ISDN_MINOR_CTRLMAX) {
1122 drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
1123 if (drvidx < 0) {
1124 retval = -ENODEV;
1125 goto out;
1126 }
1127 if (!dev->drv[drvidx]->stavail) {
1128 if (file->f_flags & O_NONBLOCK) {
1129 retval = -EAGAIN;
1130 goto out;
1131 }
1132 wait_event_interruptible(dev->drv[drvidx]->st_waitq,
1133 dev->drv[drvidx]->stavail);
1134 }
1135 if (dev->drv[drvidx]->interface->readstat) {
1136 if (count > dev->drv[drvidx]->stavail)
1137 count = dev->drv[drvidx]->stavail;
1138 len = dev->drv[drvidx]->interface->readstat(buf, count,
1139 drvidx, isdn_minor2chan(minor - ISDN_MINOR_CTRL));
1140 if (len < 0) {
1141 retval = len;
1142 goto out;
1143 }
1144 } else {
1145 len = 0;
1146 }
1147 if (len)
1148 dev->drv[drvidx]->stavail -= len;
1149 else
1150 dev->drv[drvidx]->stavail = 0;
1151 *off += len;
1152 retval = len;
1153 goto out;
1154 }
1155#ifdef CONFIG_ISDN_PPP
1156 if (minor <= ISDN_MINOR_PPPMAX) {
1157 retval = isdn_ppp_read(minor - ISDN_MINOR_PPP, file, buf, count);
1158 goto out;
1159 }
1160#endif
1161 retval = -ENODEV;
1162out:
1163 mutex_unlock(&isdn_mutex);
1164 return retval;
1165}
1166
1167static ssize_t
1168isdn_write(struct file *file, const char __user *buf, size_t count, loff_t *off)
1169{
1170 uint minor = iminor(file_inode(file));
1171 int drvidx;
1172 int chidx;
1173 int retval;
1174
1175 if (minor == ISDN_MINOR_STATUS)
1176 return -EPERM;
1177 if (!dev->drivers)
1178 return -ENODEV;
1179
1180 mutex_lock(&isdn_mutex);
1181 if (minor <= ISDN_MINOR_BMAX) {
1182 printk(KERN_WARNING "isdn_write minor %d obsolete!\n", minor);
1183 drvidx = isdn_minor2drv(minor);
1184 if (drvidx < 0) {
1185 retval = -ENODEV;
1186 goto out;
1187 }
1188 if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING)) {
1189 retval = -ENODEV;
1190 goto out;
1191 }
1192 chidx = isdn_minor2chan(minor);
1193 wait_event_interruptible(dev->drv[drvidx]->snd_waitq[chidx],
1194 (retval = isdn_writebuf_stub(drvidx, chidx, buf, count)));
1195 goto out;
1196 }
1197 if (minor <= ISDN_MINOR_CTRLMAX) {
1198 drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
1199 if (drvidx < 0) {
1200 retval = -ENODEV;
1201 goto out;
1202 }
1203 /*
1204 * We want to use the isdnctrl device to load the firmware
1205 *
1206 if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING))
1207 return -ENODEV;
1208 */
1209 if (dev->drv[drvidx]->interface->writecmd)
1210 retval = dev->drv[drvidx]->interface->
1211 writecmd(buf, count, drvidx,
1212 isdn_minor2chan(minor - ISDN_MINOR_CTRL));
1213 else
1214 retval = count;
1215 goto out;
1216 }
1217#ifdef CONFIG_ISDN_PPP
1218 if (minor <= ISDN_MINOR_PPPMAX) {
1219 retval = isdn_ppp_write(minor - ISDN_MINOR_PPP, file, buf, count);
1220 goto out;
1221 }
1222#endif
1223 retval = -ENODEV;
1224out:
1225 mutex_unlock(&isdn_mutex);
1226 return retval;
1227}
1228
1229static __poll_t
1230isdn_poll(struct file *file, poll_table *wait)
1231{
1232 __poll_t mask = 0;
1233 unsigned int minor = iminor(file_inode(file));
1234 int drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
1235
1236 mutex_lock(&isdn_mutex);
1237 if (minor == ISDN_MINOR_STATUS) {
1238 poll_wait(file, &(dev->info_waitq), wait);
1239 /* mask = EPOLLOUT | EPOLLWRNORM; */
1240 if (file->private_data) {
1241 mask |= EPOLLIN | EPOLLRDNORM;
1242 }
1243 goto out;
1244 }
1245 if (minor >= ISDN_MINOR_CTRL && minor <= ISDN_MINOR_CTRLMAX) {
1246 if (drvidx < 0) {
1247 /* driver deregistered while file open */
1248 mask = EPOLLHUP;
1249 goto out;
1250 }
1251 poll_wait(file, &(dev->drv[drvidx]->st_waitq), wait);
1252 mask = EPOLLOUT | EPOLLWRNORM;
1253 if (dev->drv[drvidx]->stavail) {
1254 mask |= EPOLLIN | EPOLLRDNORM;
1255 }
1256 goto out;
1257 }
1258#ifdef CONFIG_ISDN_PPP
1259 if (minor <= ISDN_MINOR_PPPMAX) {
1260 mask = isdn_ppp_poll(file, wait);
1261 goto out;
1262 }
1263#endif
1264 mask = EPOLLERR;
1265out:
1266 mutex_unlock(&isdn_mutex);
1267 return mask;
1268}
1269
1270
1271static int
1272isdn_ioctl(struct file *file, uint cmd, ulong arg)
1273{
1274 uint minor = iminor(file_inode(file));
1275 isdn_ctrl c;
1276 int drvidx;
1277 int ret;
1278 int i;
1279 char __user *p;
1280 char *s;
1281 union iocpar {
1282 char name[10];
1283 char bname[22];
1284 isdn_ioctl_struct iocts;
1285 isdn_net_ioctl_phone phone;
1286 isdn_net_ioctl_cfg cfg;
1287 } iocpar;
1288 void __user *argp = (void __user *)arg;
1289
1290#define name iocpar.name
1291#define bname iocpar.bname
1292#define iocts iocpar.iocts
1293#define phone iocpar.phone
1294#define cfg iocpar.cfg
1295
1296 if (minor == ISDN_MINOR_STATUS) {
1297 switch (cmd) {
1298 case IIOCGETDVR:
1299 return (TTY_DV +
1300 (NET_DV << 8) +
1301 (INF_DV << 16));
1302 case IIOCGETCPS:
1303 if (arg) {
1304 ulong __user *p = argp;
1305 int i;
1306 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
1307 put_user(dev->ibytes[i], p++);
1308 put_user(dev->obytes[i], p++);
1309 }
1310 return 0;
1311 } else
1312 return -EINVAL;
1313 break;
1314 case IIOCNETGPN:
1315 /* Get peer phone number of a connected
1316 * isdn network interface */
1317 if (arg) {
1318 if (copy_from_user(&phone, argp, sizeof(phone)))
1319 return -EFAULT;
1320 return isdn_net_getpeer(&phone, argp);
1321 } else
1322 return -EINVAL;
1323 default:
1324 return -EINVAL;
1325 }
1326 }
1327 if (!dev->drivers)
1328 return -ENODEV;
1329 if (minor <= ISDN_MINOR_BMAX) {
1330 drvidx = isdn_minor2drv(minor);
1331 if (drvidx < 0)
1332 return -ENODEV;
1333 if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING))
1334 return -ENODEV;
1335 return 0;
1336 }
1337 if (minor <= ISDN_MINOR_CTRLMAX) {
1338/*
1339 * isdn net devices manage lots of configuration variables as linked lists.
1340 * Those lists must only be manipulated from user space. Some of the ioctl's
1341 * service routines access user space and are not atomic. Therefore, ioctl's
1342 * manipulating the lists and ioctl's sleeping while accessing the lists
1343 * are serialized by means of a semaphore.
1344 */
1345 switch (cmd) {
1346 case IIOCNETDWRSET:
1347 printk(KERN_INFO "INFO: ISDN_DW_ABC_EXTENSION not enabled\n");
1348 return (-EINVAL);
1349 case IIOCNETLCR:
1350 printk(KERN_INFO "INFO: ISDN_ABC_LCR_SUPPORT not enabled\n");
1351 return -ENODEV;
1352 case IIOCNETAIF:
1353 /* Add a network-interface */
1354 if (arg) {
1355 if (copy_from_user(name, argp, sizeof(name)))
1356 return -EFAULT;
1357 s = name;
1358 } else {
1359 s = NULL;
1360 }
1361 ret = mutex_lock_interruptible(&dev->mtx);
1362 if (ret) return ret;
1363 if ((s = isdn_net_new(s, NULL))) {
1364 if (copy_to_user(argp, s, strlen(s) + 1)) {
1365 ret = -EFAULT;
1366 } else {
1367 ret = 0;
1368 }
1369 } else
1370 ret = -ENODEV;
1371 mutex_unlock(&dev->mtx);
1372 return ret;
1373 case IIOCNETASL:
1374 /* Add a slave to a network-interface */
1375 if (arg) {
1376 if (copy_from_user(bname, argp, sizeof(bname) - 1))
1377 return -EFAULT;
1378 bname[sizeof(bname)-1] = 0;
1379 } else
1380 return -EINVAL;
1381 ret = mutex_lock_interruptible(&dev->mtx);
1382 if (ret) return ret;
1383 if ((s = isdn_net_newslave(bname))) {
1384 if (copy_to_user(argp, s, strlen(s) + 1)) {
1385 ret = -EFAULT;
1386 } else {
1387 ret = 0;
1388 }
1389 } else
1390 ret = -ENODEV;
1391 mutex_unlock(&dev->mtx);
1392 return ret;
1393 case IIOCNETDIF:
1394 /* Delete a network-interface */
1395 if (arg) {
1396 if (copy_from_user(name, argp, sizeof(name)))
1397 return -EFAULT;
1398 ret = mutex_lock_interruptible(&dev->mtx);
1399 if (ret) return ret;
1400 ret = isdn_net_rm(name);
1401 mutex_unlock(&dev->mtx);
1402 return ret;
1403 } else
1404 return -EINVAL;
1405 case IIOCNETSCF:
1406 /* Set configurable parameters of a network-interface */
1407 if (arg) {
1408 if (copy_from_user(&cfg, argp, sizeof(cfg)))
1409 return -EFAULT;
1410 return isdn_net_setcfg(&cfg);
1411 } else
1412 return -EINVAL;
1413 case IIOCNETGCF:
1414 /* Get configurable parameters of a network-interface */
1415 if (arg) {
1416 if (copy_from_user(&cfg, argp, sizeof(cfg)))
1417 return -EFAULT;
1418 if (!(ret = isdn_net_getcfg(&cfg))) {
1419 if (copy_to_user(argp, &cfg, sizeof(cfg)))
1420 return -EFAULT;
1421 }
1422 return ret;
1423 } else
1424 return -EINVAL;
1425 case IIOCNETANM:
1426 /* Add a phone-number to a network-interface */
1427 if (arg) {
1428 if (copy_from_user(&phone, argp, sizeof(phone)))
1429 return -EFAULT;
1430 ret = mutex_lock_interruptible(&dev->mtx);
1431 if (ret) return ret;
1432 ret = isdn_net_addphone(&phone);
1433 mutex_unlock(&dev->mtx);
1434 return ret;
1435 } else
1436 return -EINVAL;
1437 case IIOCNETGNM:
1438 /* Get list of phone-numbers of a network-interface */
1439 if (arg) {
1440 if (copy_from_user(&phone, argp, sizeof(phone)))
1441 return -EFAULT;
1442 ret = mutex_lock_interruptible(&dev->mtx);
1443 if (ret) return ret;
1444 ret = isdn_net_getphones(&phone, argp);
1445 mutex_unlock(&dev->mtx);
1446 return ret;
1447 } else
1448 return -EINVAL;
1449 case IIOCNETDNM:
1450 /* Delete a phone-number of a network-interface */
1451 if (arg) {
1452 if (copy_from_user(&phone, argp, sizeof(phone)))
1453 return -EFAULT;
1454 ret = mutex_lock_interruptible(&dev->mtx);
1455 if (ret) return ret;
1456 ret = isdn_net_delphone(&phone);
1457 mutex_unlock(&dev->mtx);
1458 return ret;
1459 } else
1460 return -EINVAL;
1461 case IIOCNETDIL:
1462 /* Force dialing of a network-interface */
1463 if (arg) {
1464 if (copy_from_user(name, argp, sizeof(name)))
1465 return -EFAULT;
1466 return isdn_net_force_dial(name);
1467 } else
1468 return -EINVAL;
1469#ifdef CONFIG_ISDN_PPP
1470 case IIOCNETALN:
1471 if (!arg)
1472 return -EINVAL;
1473 if (copy_from_user(name, argp, sizeof(name)))
1474 return -EFAULT;
1475 return isdn_ppp_dial_slave(name);
1476 case IIOCNETDLN:
1477 if (!arg)
1478 return -EINVAL;
1479 if (copy_from_user(name, argp, sizeof(name)))
1480 return -EFAULT;
1481 return isdn_ppp_hangup_slave(name);
1482#endif
1483 case IIOCNETHUP:
1484 /* Force hangup of a network-interface */
1485 if (!arg)
1486 return -EINVAL;
1487 if (copy_from_user(name, argp, sizeof(name)))
1488 return -EFAULT;
1489 return isdn_net_force_hangup(name);
1490 break;
1491 case IIOCSETVER:
1492 dev->net_verbose = arg;
1493 printk(KERN_INFO "isdn: Verbose-Level is %d\n", dev->net_verbose);
1494 return 0;
1495 case IIOCSETGST:
1496 if (arg)
1497 dev->global_flags |= ISDN_GLOBAL_STOPPED;
1498 else
1499 dev->global_flags &= ~ISDN_GLOBAL_STOPPED;
1500 printk(KERN_INFO "isdn: Global Mode %s\n",
1501 (dev->global_flags & ISDN_GLOBAL_STOPPED) ? "stopped" : "running");
1502 return 0;
1503 case IIOCSETBRJ:
1504 drvidx = -1;
1505 if (arg) {
1506 int i;
1507 char *p;
1508 if (copy_from_user(&iocts, argp,
1509 sizeof(isdn_ioctl_struct)))
1510 return -EFAULT;
1511 iocts.drvid[sizeof(iocts.drvid) - 1] = 0;
1512 if (strlen(iocts.drvid)) {
1513 if ((p = strchr(iocts.drvid, ',')))
1514 *p = 0;
1515 drvidx = -1;
1516 for (i = 0; i < ISDN_MAX_DRIVERS; i++)
1517 if (!(strcmp(dev->drvid[i], iocts.drvid))) {
1518 drvidx = i;
1519 break;
1520 }
1521 }
1522 }
1523 if (drvidx == -1)
1524 return -ENODEV;
1525 if (iocts.arg)
1526 dev->drv[drvidx]->flags |= DRV_FLAG_REJBUS;
1527 else
1528 dev->drv[drvidx]->flags &= ~DRV_FLAG_REJBUS;
1529 return 0;
1530 case IIOCSIGPRF:
1531 dev->profd = current;
1532 return 0;
1533 break;
1534 case IIOCGETPRF:
1535 /* Get all Modem-Profiles */
1536 if (arg) {
1537 char __user *p = argp;
1538 int i;
1539
1540 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
1541 if (copy_to_user(p, dev->mdm.info[i].emu.profile,
1542 ISDN_MODEM_NUMREG))
1543 return -EFAULT;
1544 p += ISDN_MODEM_NUMREG;
1545 if (copy_to_user(p, dev->mdm.info[i].emu.pmsn, ISDN_MSNLEN))
1546 return -EFAULT;
1547 p += ISDN_MSNLEN;
1548 if (copy_to_user(p, dev->mdm.info[i].emu.plmsn, ISDN_LMSNLEN))
1549 return -EFAULT;
1550 p += ISDN_LMSNLEN;
1551 }
1552 return (ISDN_MODEM_NUMREG + ISDN_MSNLEN + ISDN_LMSNLEN) * ISDN_MAX_CHANNELS;
1553 } else
1554 return -EINVAL;
1555 break;
1556 case IIOCSETPRF:
1557 /* Set all Modem-Profiles */
1558 if (arg) {
1559 char __user *p = argp;
1560 int i;
1561
1562 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
1563 if (copy_from_user(dev->mdm.info[i].emu.profile, p,
1564 ISDN_MODEM_NUMREG))
1565 return -EFAULT;
1566 p += ISDN_MODEM_NUMREG;
1567 if (copy_from_user(dev->mdm.info[i].emu.plmsn, p, ISDN_LMSNLEN))
1568 return -EFAULT;
1569 p += ISDN_LMSNLEN;
1570 if (copy_from_user(dev->mdm.info[i].emu.pmsn, p, ISDN_MSNLEN))
1571 return -EFAULT;
1572 p += ISDN_MSNLEN;
1573 }
1574 return 0;
1575 } else
1576 return -EINVAL;
1577 break;
1578 case IIOCSETMAP:
1579 case IIOCGETMAP:
1580 /* Set/Get MSN->EAZ-Mapping for a driver */
1581 if (arg) {
1582
1583 if (copy_from_user(&iocts, argp,
1584 sizeof(isdn_ioctl_struct)))
1585 return -EFAULT;
1586 iocts.drvid[sizeof(iocts.drvid) - 1] = 0;
1587 if (strlen(iocts.drvid)) {
1588 drvidx = -1;
1589 for (i = 0; i < ISDN_MAX_DRIVERS; i++)
1590 if (!(strcmp(dev->drvid[i], iocts.drvid))) {
1591 drvidx = i;
1592 break;
1593 }
1594 } else
1595 drvidx = 0;
1596 if (drvidx == -1)
1597 return -ENODEV;
1598 if (cmd == IIOCSETMAP) {
1599 int loop = 1;
1600
1601 p = (char __user *) iocts.arg;
1602 i = 0;
1603 while (loop) {
1604 int j = 0;
1605
1606 while (1) {
1607 get_user(bname[j], p++);
1608 switch (bname[j]) {
1609 case '\0':
1610 loop = 0;
1611 /* Fall through */
1612 case ',':
1613 bname[j] = '\0';
1614 strcpy(dev->drv[drvidx]->msn2eaz[i], bname);
1615 j = ISDN_MSNLEN;
1616 break;
1617 default:
1618 j++;
1619 }
1620 if (j >= ISDN_MSNLEN)
1621 break;
1622 }
1623 if (++i > 9)
1624 break;
1625 }
1626 } else {
1627 p = (char __user *) iocts.arg;
1628 for (i = 0; i < 10; i++) {
1629 snprintf(bname, sizeof(bname), "%s%s",
1630 strlen(dev->drv[drvidx]->msn2eaz[i]) ?
1631 dev->drv[drvidx]->msn2eaz[i] : "_",
1632 (i < 9) ? "," : "\0");
1633 if (copy_to_user(p, bname, strlen(bname) + 1))
1634 return -EFAULT;
1635 p += strlen(bname);
1636 }
1637 }
1638 return 0;
1639 } else
1640 return -EINVAL;
1641 case IIOCDBGVAR:
1642 return -EINVAL;
1643 default:
1644 if ((cmd & IIOCDRVCTL) == IIOCDRVCTL)
1645 cmd = ((cmd >> _IOC_NRSHIFT) & _IOC_NRMASK) & ISDN_DRVIOCTL_MASK;
1646 else
1647 return -EINVAL;
1648 if (arg) {
1649 int i;
1650 char *p;
1651 if (copy_from_user(&iocts, argp, sizeof(isdn_ioctl_struct)))
1652 return -EFAULT;
1653 iocts.drvid[sizeof(iocts.drvid) - 1] = 0;
1654 if (strlen(iocts.drvid)) {
1655 if ((p = strchr(iocts.drvid, ',')))
1656 *p = 0;
1657 drvidx = -1;
1658 for (i = 0; i < ISDN_MAX_DRIVERS; i++)
1659 if (!(strcmp(dev->drvid[i], iocts.drvid))) {
1660 drvidx = i;
1661 break;
1662 }
1663 } else
1664 drvidx = 0;
1665 if (drvidx == -1)
1666 return -ENODEV;
1667 c.driver = drvidx;
1668 c.command = ISDN_CMD_IOCTL;
1669 c.arg = cmd;
1670 memcpy(c.parm.num, &iocts.arg, sizeof(ulong));
1671 ret = isdn_command(&c);
1672 memcpy(&iocts.arg, c.parm.num, sizeof(ulong));
1673 if (copy_to_user(argp, &iocts, sizeof(isdn_ioctl_struct)))
1674 return -EFAULT;
1675 return ret;
1676 } else
1677 return -EINVAL;
1678 }
1679 }
1680#ifdef CONFIG_ISDN_PPP
1681 if (minor <= ISDN_MINOR_PPPMAX)
1682 return (isdn_ppp_ioctl(minor - ISDN_MINOR_PPP, file, cmd, arg));
1683#endif
1684 return -ENODEV;
1685
1686#undef name
1687#undef bname
1688#undef iocts
1689#undef phone
1690#undef cfg
1691}
1692
1693static long
1694isdn_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
1695{
1696 int ret;
1697
1698 mutex_lock(&isdn_mutex);
1699 ret = isdn_ioctl(file, cmd, arg);
1700 mutex_unlock(&isdn_mutex);
1701
1702 return ret;
1703}
1704
1705/*
1706 * Open the device code.
1707 */
1708static int
1709isdn_open(struct inode *ino, struct file *filep)
1710{
1711 uint minor = iminor(ino);
1712 int drvidx;
1713 int chidx;
1714 int retval = -ENODEV;
1715
1716 mutex_lock(&isdn_mutex);
1717 if (minor == ISDN_MINOR_STATUS) {
1718 infostruct *p;
1719
1720 if ((p = kmalloc(sizeof(infostruct), GFP_KERNEL))) {
1721 p->next = (char *) dev->infochain;
1722 p->private = (char *) &(filep->private_data);
1723 dev->infochain = p;
1724 /* At opening we allow a single update */
1725 filep->private_data = (char *) 1;
1726 retval = 0;
1727 goto out;
1728 } else {
1729 retval = -ENOMEM;
1730 goto out;
1731 }
1732 }
1733 if (!dev->channels)
1734 goto out;
1735 if (minor <= ISDN_MINOR_BMAX) {
1736 printk(KERN_WARNING "isdn_open minor %d obsolete!\n", minor);
1737 drvidx = isdn_minor2drv(minor);
1738 if (drvidx < 0)
1739 goto out;
1740 chidx = isdn_minor2chan(minor);
1741 if (!(dev->drv[drvidx]->flags & DRV_FLAG_RUNNING))
1742 goto out;
1743 if (!(dev->drv[drvidx]->online & (1 << chidx)))
1744 goto out;
1745 isdn_lock_drivers();
1746 retval = 0;
1747 goto out;
1748 }
1749 if (minor <= ISDN_MINOR_CTRLMAX) {
1750 drvidx = isdn_minor2drv(minor - ISDN_MINOR_CTRL);
1751 if (drvidx < 0)
1752 goto out;
1753 isdn_lock_drivers();
1754 retval = 0;
1755 goto out;
1756 }
1757#ifdef CONFIG_ISDN_PPP
1758 if (minor <= ISDN_MINOR_PPPMAX) {
1759 retval = isdn_ppp_open(minor - ISDN_MINOR_PPP, filep);
1760 if (retval == 0)
1761 isdn_lock_drivers();
1762 goto out;
1763 }
1764#endif
1765out:
1766 nonseekable_open(ino, filep);
1767 mutex_unlock(&isdn_mutex);
1768 return retval;
1769}
1770
1771static int
1772isdn_close(struct inode *ino, struct file *filep)
1773{
1774 uint minor = iminor(ino);
1775
1776 mutex_lock(&isdn_mutex);
1777 if (minor == ISDN_MINOR_STATUS) {
1778 infostruct *p = dev->infochain;
1779 infostruct *q = NULL;
1780
1781 while (p) {
1782 if (p->private == (char *) &(filep->private_data)) {
1783 if (q)
1784 q->next = p->next;
1785 else
1786 dev->infochain = (infostruct *) (p->next);
1787 kfree(p);
1788 goto out;
1789 }
1790 q = p;
1791 p = (infostruct *) (p->next);
1792 }
1793 printk(KERN_WARNING "isdn: No private data while closing isdnctrl\n");
1794 goto out;
1795 }
1796 isdn_unlock_drivers();
1797 if (minor <= ISDN_MINOR_BMAX)
1798 goto out;
1799 if (minor <= ISDN_MINOR_CTRLMAX) {
1800 if (dev->profd == current)
1801 dev->profd = NULL;
1802 goto out;
1803 }
1804#ifdef CONFIG_ISDN_PPP
1805 if (minor <= ISDN_MINOR_PPPMAX)
1806 isdn_ppp_release(minor - ISDN_MINOR_PPP, filep);
1807#endif
1808
1809out:
1810 mutex_unlock(&isdn_mutex);
1811 return 0;
1812}
1813
1814static const struct file_operations isdn_fops =
1815{
1816 .owner = THIS_MODULE,
1817 .llseek = no_llseek,
1818 .read = isdn_read,
1819 .write = isdn_write,
1820 .poll = isdn_poll,
1821 .unlocked_ioctl = isdn_unlocked_ioctl,
1822 .open = isdn_open,
1823 .release = isdn_close,
1824};
1825
1826char *
1827isdn_map_eaz2msn(char *msn, int di)
1828{
1829 isdn_driver_t *this = dev->drv[di];
1830 int i;
1831
1832 if (strlen(msn) == 1) {
1833 i = msn[0] - '0';
1834 if ((i >= 0) && (i <= 9))
1835 if (strlen(this->msn2eaz[i]))
1836 return (this->msn2eaz[i]);
1837 }
1838 return (msn);
1839}
1840
1841/*
1842 * Find an unused ISDN-channel, whose feature-flags match the
1843 * given L2- and L3-protocols.
1844 */
1845#define L2V (~(ISDN_FEATURE_L2_V11096 | ISDN_FEATURE_L2_V11019 | ISDN_FEATURE_L2_V11038))
1846
1847/*
1848 * This function must be called with holding the dev->lock.
1849 */
1850int
1851isdn_get_free_channel(int usage, int l2_proto, int l3_proto, int pre_dev
1852 , int pre_chan, char *msn)
1853{
1854 int i;
1855 ulong features;
1856 ulong vfeatures;
1857
1858 features = ((1 << l2_proto) | (0x10000 << l3_proto));
1859 vfeatures = (((1 << l2_proto) | (0x10000 << l3_proto)) &
1860 ~(ISDN_FEATURE_L2_V11096 | ISDN_FEATURE_L2_V11019 | ISDN_FEATURE_L2_V11038));
1861 /* If Layer-2 protocol is V.110, accept drivers with
1862 * transparent feature even if these don't support V.110
1863 * because we can emulate this in linklevel.
1864 */
1865 for (i = 0; i < ISDN_MAX_CHANNELS; i++)
1866 if (USG_NONE(dev->usage[i]) &&
1867 (dev->drvmap[i] != -1)) {
1868 int d = dev->drvmap[i];
1869 if ((dev->usage[i] & ISDN_USAGE_EXCLUSIVE) &&
1870 ((pre_dev != d) || (pre_chan != dev->chanmap[i])))
1871 continue;
1872 if (!strcmp(isdn_map_eaz2msn(msn, d), "-"))
1873 continue;
1874 if (dev->usage[i] & ISDN_USAGE_DISABLED)
1875 continue; /* usage not allowed */
1876 if (dev->drv[d]->flags & DRV_FLAG_RUNNING) {
1877 if (((dev->drv[d]->interface->features & features) == features) ||
1878 (((dev->drv[d]->interface->features & vfeatures) == vfeatures) &&
1879 (dev->drv[d]->interface->features & ISDN_FEATURE_L2_TRANS))) {
1880 if ((pre_dev < 0) || (pre_chan < 0)) {
1881 dev->usage[i] &= ISDN_USAGE_EXCLUSIVE;
1882 dev->usage[i] |= usage;
1883 isdn_info_update();
1884 return i;
1885 } else {
1886 if ((pre_dev == d) && (pre_chan == dev->chanmap[i])) {
1887 dev->usage[i] &= ISDN_USAGE_EXCLUSIVE;
1888 dev->usage[i] |= usage;
1889 isdn_info_update();
1890 return i;
1891 }
1892 }
1893 }
1894 }
1895 }
1896 return -1;
1897}
1898
1899/*
1900 * Set state of ISDN-channel to 'unused'
1901 */
1902void
1903isdn_free_channel(int di, int ch, int usage)
1904{
1905 int i;
1906
1907 if ((di < 0) || (ch < 0)) {
1908 printk(KERN_WARNING "%s: called with invalid drv(%d) or channel(%d)\n",
1909 __func__, di, ch);
1910 return;
1911 }
1912 for (i = 0; i < ISDN_MAX_CHANNELS; i++)
1913 if (((!usage) || ((dev->usage[i] & ISDN_USAGE_MASK) == usage)) &&
1914 (dev->drvmap[i] == di) &&
1915 (dev->chanmap[i] == ch)) {
1916 dev->usage[i] &= (ISDN_USAGE_NONE | ISDN_USAGE_EXCLUSIVE);
1917 strcpy(dev->num[i], "???");
1918 dev->ibytes[i] = 0;
1919 dev->obytes[i] = 0;
1920// 20.10.99 JIM, try to reinitialize v110 !
1921 dev->v110emu[i] = 0;
1922 atomic_set(&(dev->v110use[i]), 0);
1923 isdn_v110_close(dev->v110[i]);
1924 dev->v110[i] = NULL;
1925// 20.10.99 JIM, try to reinitialize v110 !
1926 isdn_info_update();
1927 if (dev->drv[di])
1928 skb_queue_purge(&dev->drv[di]->rpqueue[ch]);
1929 }
1930}
1931
1932/*
1933 * Cancel Exclusive-Flag for ISDN-channel
1934 */
1935void
1936isdn_unexclusive_channel(int di, int ch)
1937{
1938 int i;
1939
1940 for (i = 0; i < ISDN_MAX_CHANNELS; i++)
1941 if ((dev->drvmap[i] == di) &&
1942 (dev->chanmap[i] == ch)) {
1943 dev->usage[i] &= ~ISDN_USAGE_EXCLUSIVE;
1944 isdn_info_update();
1945 return;
1946 }
1947}
1948
1949/*
1950 * writebuf replacement for SKB_ABLE drivers
1951 */
1952static int
1953isdn_writebuf_stub(int drvidx, int chan, const u_char __user *buf, int len)
1954{
1955 int ret;
1956 int hl = dev->drv[drvidx]->interface->hl_hdrlen;
1957 struct sk_buff *skb = alloc_skb(hl + len, GFP_ATOMIC);
1958
1959 if (!skb)
1960 return -ENOMEM;
1961 skb_reserve(skb, hl);
1962 if (copy_from_user(skb_put(skb, len), buf, len)) {
1963 dev_kfree_skb(skb);
1964 return -EFAULT;
1965 }
1966 ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, 1, skb);
1967 if (ret <= 0)
1968 dev_kfree_skb(skb);
1969 if (ret > 0)
1970 dev->obytes[isdn_dc2minor(drvidx, chan)] += ret;
1971 return ret;
1972}
1973
1974/*
1975 * Return: length of data on success, -ERRcode on failure.
1976 */
1977int
1978isdn_writebuf_skb_stub(int drvidx, int chan, int ack, struct sk_buff *skb)
1979{
1980 int ret;
1981 struct sk_buff *nskb = NULL;
1982 int v110_ret = skb->len;
1983 int idx = isdn_dc2minor(drvidx, chan);
1984
1985 if (dev->v110[idx]) {
1986 atomic_inc(&dev->v110use[idx]);
1987 nskb = isdn_v110_encode(dev->v110[idx], skb);
1988 atomic_dec(&dev->v110use[idx]);
1989 if (!nskb)
1990 return 0;
1991 v110_ret = *((int *)nskb->data);
1992 skb_pull(nskb, sizeof(int));
1993 if (!nskb->len) {
1994 dev_kfree_skb(nskb);
1995 return v110_ret;
1996 }
1997 /* V.110 must always be acknowledged */
1998 ack = 1;
1999 ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, ack, nskb);
2000 } else {
2001 int hl = dev->drv[drvidx]->interface->hl_hdrlen;
2002
2003 if (skb_headroom(skb) < hl) {
2004 /*
2005 * This should only occur when new HL driver with
2006 * increased hl_hdrlen was loaded after netdevice
2007 * was created and connected to the new driver.
2008 *
2009 * The V.110 branch (re-allocates on its own) does
2010 * not need this
2011 */
2012 struct sk_buff *skb_tmp;
2013
2014 skb_tmp = skb_realloc_headroom(skb, hl);
2015 printk(KERN_DEBUG "isdn_writebuf_skb_stub: reallocating headroom%s\n", skb_tmp ? "" : " failed");
2016 if (!skb_tmp) return -ENOMEM; /* 0 better? */
2017 ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, ack, skb_tmp);
2018 if (ret > 0) {
2019 dev_kfree_skb(skb);
2020 } else {
2021 dev_kfree_skb(skb_tmp);
2022 }
2023 } else {
2024 ret = dev->drv[drvidx]->interface->writebuf_skb(drvidx, chan, ack, skb);
2025 }
2026 }
2027 if (ret > 0) {
2028 dev->obytes[idx] += ret;
2029 if (dev->v110[idx]) {
2030 atomic_inc(&dev->v110use[idx]);
2031 dev->v110[idx]->skbuser++;
2032 atomic_dec(&dev->v110use[idx]);
2033 /* For V.110 return unencoded data length */
2034 ret = v110_ret;
2035 /* if the complete frame was send we free the skb;
2036 if not upper function will requeue the skb */
2037 if (ret == skb->len)
2038 dev_kfree_skb(skb);
2039 }
2040 } else
2041 if (dev->v110[idx])
2042 dev_kfree_skb(nskb);
2043 return ret;
2044}
2045
2046static int
2047isdn_add_channels(isdn_driver_t *d, int drvidx, int n, int adding)
2048{
2049 int j, k, m;
2050
2051 init_waitqueue_head(&d->st_waitq);
2052 if (d->flags & DRV_FLAG_RUNNING)
2053 return -1;
2054 if (n < 1) return 0;
2055
2056 m = (adding) ? d->channels + n : n;
2057
2058 if (dev->channels + n > ISDN_MAX_CHANNELS) {
2059 printk(KERN_WARNING "register_isdn: Max. %d channels supported\n",
2060 ISDN_MAX_CHANNELS);
2061 return -1;
2062 }
2063
2064 if ((adding) && (d->rcverr))
2065 kfree(d->rcverr);
2066 if (!(d->rcverr = kcalloc(m, sizeof(int), GFP_ATOMIC))) {
2067 printk(KERN_WARNING "register_isdn: Could not alloc rcverr\n");
2068 return -1;
2069 }
2070
2071 if ((adding) && (d->rcvcount))
2072 kfree(d->rcvcount);
2073 if (!(d->rcvcount = kcalloc(m, sizeof(int), GFP_ATOMIC))) {
2074 printk(KERN_WARNING "register_isdn: Could not alloc rcvcount\n");
2075 if (!adding)
2076 kfree(d->rcverr);
2077 return -1;
2078 }
2079
2080 if ((adding) && (d->rpqueue)) {
2081 for (j = 0; j < d->channels; j++)
2082 skb_queue_purge(&d->rpqueue[j]);
2083 kfree(d->rpqueue);
2084 }
2085 d->rpqueue = kmalloc_array(m, sizeof(struct sk_buff_head), GFP_ATOMIC);
2086 if (!d->rpqueue) {
2087 printk(KERN_WARNING "register_isdn: Could not alloc rpqueue\n");
2088 if (!adding) {
2089 kfree(d->rcvcount);
2090 kfree(d->rcverr);
2091 }
2092 return -1;
2093 }
2094 for (j = 0; j < m; j++) {
2095 skb_queue_head_init(&d->rpqueue[j]);
2096 }
2097
2098 if ((adding) && (d->rcv_waitq))
2099 kfree(d->rcv_waitq);
2100 d->rcv_waitq = kmalloc(array3_size(sizeof(wait_queue_head_t), 2, m),
2101 GFP_ATOMIC);
2102 if (!d->rcv_waitq) {
2103 printk(KERN_WARNING "register_isdn: Could not alloc rcv_waitq\n");
2104 if (!adding) {
2105 kfree(d->rpqueue);
2106 kfree(d->rcvcount);
2107 kfree(d->rcverr);
2108 }
2109 return -1;
2110 }
2111 d->snd_waitq = d->rcv_waitq + m;
2112 for (j = 0; j < m; j++) {
2113 init_waitqueue_head(&d->rcv_waitq[j]);
2114 init_waitqueue_head(&d->snd_waitq[j]);
2115 }
2116
2117 dev->channels += n;
2118 for (j = d->channels; j < m; j++)
2119 for (k = 0; k < ISDN_MAX_CHANNELS; k++)
2120 if (dev->chanmap[k] < 0) {
2121 dev->chanmap[k] = j;
2122 dev->drvmap[k] = drvidx;
2123 break;
2124 }
2125 d->channels = m;
2126 return 0;
2127}
2128
2129/*
2130 * Low-level-driver registration
2131 */
2132
2133static void
2134set_global_features(void)
2135{
2136 int drvidx;
2137
2138 dev->global_features = 0;
2139 for (drvidx = 0; drvidx < ISDN_MAX_DRIVERS; drvidx++) {
2140 if (!dev->drv[drvidx])
2141 continue;
2142 if (dev->drv[drvidx]->interface)
2143 dev->global_features |= dev->drv[drvidx]->interface->features;
2144 }
2145}
2146
2147#ifdef CONFIG_ISDN_DIVERSION
2148
2149static char *map_drvname(int di)
2150{
2151 if ((di < 0) || (di >= ISDN_MAX_DRIVERS))
2152 return (NULL);
2153 return (dev->drvid[di]); /* driver name */
2154} /* map_drvname */
2155
2156static int map_namedrv(char *id)
2157{ int i;
2158
2159 for (i = 0; i < ISDN_MAX_DRIVERS; i++)
2160 { if (!strcmp(dev->drvid[i], id))
2161 return (i);
2162 }
2163 return (-1);
2164} /* map_namedrv */
2165
2166int DIVERT_REG_NAME(isdn_divert_if *i_div)
2167{
2168 if (i_div->if_magic != DIVERT_IF_MAGIC)
2169 return (DIVERT_VER_ERR);
2170 switch (i_div->cmd)
2171 {
2172 case DIVERT_CMD_REL:
2173 if (divert_if != i_div)
2174 return (DIVERT_REL_ERR);
2175 divert_if = NULL; /* free interface */
2176 return (DIVERT_NO_ERR);
2177
2178 case DIVERT_CMD_REG:
2179 if (divert_if)
2180 return (DIVERT_REG_ERR);
2181 i_div->ll_cmd = isdn_command; /* set command function */
2182 i_div->drv_to_name = map_drvname;
2183 i_div->name_to_drv = map_namedrv;
2184 divert_if = i_div; /* remember interface */
2185 return (DIVERT_NO_ERR);
2186
2187 default:
2188 return (DIVERT_CMD_ERR);
2189 }
2190} /* DIVERT_REG_NAME */
2191
2192EXPORT_SYMBOL(DIVERT_REG_NAME);
2193
2194#endif /* CONFIG_ISDN_DIVERSION */
2195
2196
2197EXPORT_SYMBOL(register_isdn);
2198#ifdef CONFIG_ISDN_PPP
2199EXPORT_SYMBOL(isdn_ppp_register_compressor);
2200EXPORT_SYMBOL(isdn_ppp_unregister_compressor);
2201#endif
2202
2203int
2204register_isdn(isdn_if *i)
2205{
2206 isdn_driver_t *d;
2207 int j;
2208 ulong flags;
2209 int drvidx;
2210
2211 if (dev->drivers >= ISDN_MAX_DRIVERS) {
2212 printk(KERN_WARNING "register_isdn: Max. %d drivers supported\n",
2213 ISDN_MAX_DRIVERS);
2214 return 0;
2215 }
2216 if (!i->writebuf_skb) {
2217 printk(KERN_WARNING "register_isdn: No write routine given.\n");
2218 return 0;
2219 }
2220 if (!(d = kzalloc(sizeof(isdn_driver_t), GFP_KERNEL))) {
2221 printk(KERN_WARNING "register_isdn: Could not alloc driver-struct\n");
2222 return 0;
2223 }
2224
2225 d->maxbufsize = i->maxbufsize;
2226 d->pktcount = 0;
2227 d->stavail = 0;
2228 d->flags = DRV_FLAG_LOADED;
2229 d->online = 0;
2230 d->interface = i;
2231 d->channels = 0;
2232 spin_lock_irqsave(&dev->lock, flags);
2233 for (drvidx = 0; drvidx < ISDN_MAX_DRIVERS; drvidx++)
2234 if (!dev->drv[drvidx])
2235 break;
2236 if (isdn_add_channels(d, drvidx, i->channels, 0)) {
2237 spin_unlock_irqrestore(&dev->lock, flags);
2238 kfree(d);
2239 return 0;
2240 }
2241 i->channels = drvidx;
2242 i->rcvcallb_skb = isdn_receive_skb_callback;
2243 i->statcallb = isdn_status_callback;
2244 if (!strlen(i->id))
2245 sprintf(i->id, "line%d", drvidx);
2246 for (j = 0; j < drvidx; j++)
2247 if (!strcmp(i->id, dev->drvid[j]))
2248 sprintf(i->id, "line%d", drvidx);
2249 dev->drv[drvidx] = d;
2250 strcpy(dev->drvid[drvidx], i->id);
2251 isdn_info_update();
2252 dev->drivers++;
2253 set_global_features();
2254 spin_unlock_irqrestore(&dev->lock, flags);
2255 return 1;
2256}
2257
2258/*
2259*****************************************************************************
2260* And now the modules code.
2261*****************************************************************************
2262*/
2263
2264static char *
2265isdn_getrev(const char *revision)
2266{
2267 char *rev;
2268 char *p;
2269
2270 if ((p = strchr(revision, ':'))) {
2271 rev = p + 2;
2272 p = strchr(rev, '$');
2273 *--p = 0;
2274 } else
2275 rev = "???";
2276 return rev;
2277}
2278
2279/*
2280 * Allocate and initialize all data, register modem-devices
2281 */
2282static int __init isdn_init(void)
2283{
2284 int i;
2285 char tmprev[50];
2286
2287 dev = vzalloc(sizeof(isdn_dev));
2288 if (!dev) {
2289 printk(KERN_WARNING "isdn: Could not allocate device-struct.\n");
2290 return -EIO;
2291 }
2292 timer_setup(&dev->timer, isdn_timer_funct, 0);
2293 spin_lock_init(&dev->lock);
2294 spin_lock_init(&dev->timerlock);
2295#ifdef MODULE
2296 dev->owner = THIS_MODULE;
2297#endif
2298 mutex_init(&dev->mtx);
2299 init_waitqueue_head(&dev->info_waitq);
2300 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
2301 dev->drvmap[i] = -1;
2302 dev->chanmap[i] = -1;
2303 dev->m_idx[i] = -1;
2304 strcpy(dev->num[i], "???");
2305 }
2306 if (register_chrdev(ISDN_MAJOR, "isdn", &isdn_fops)) {
2307 printk(KERN_WARNING "isdn: Could not register control devices\n");
2308 vfree(dev);
2309 return -EIO;
2310 }
2311 if ((isdn_tty_modem_init()) < 0) {
2312 printk(KERN_WARNING "isdn: Could not register tty devices\n");
2313 vfree(dev);
2314 unregister_chrdev(ISDN_MAJOR, "isdn");
2315 return -EIO;
2316 }
2317#ifdef CONFIG_ISDN_PPP
2318 if (isdn_ppp_init() < 0) {
2319 printk(KERN_WARNING "isdn: Could not create PPP-device-structs\n");
2320 isdn_tty_exit();
2321 unregister_chrdev(ISDN_MAJOR, "isdn");
2322 vfree(dev);
2323 return -EIO;
2324 }
2325#endif /* CONFIG_ISDN_PPP */
2326
2327 strcpy(tmprev, isdn_revision);
2328 printk(KERN_NOTICE "ISDN subsystem Rev: %s/", isdn_getrev(tmprev));
2329 strcpy(tmprev, isdn_net_revision);
2330 printk("%s/", isdn_getrev(tmprev));
2331 strcpy(tmprev, isdn_ppp_revision);
2332 printk("%s/", isdn_getrev(tmprev));
2333 strcpy(tmprev, isdn_audio_revision);
2334 printk("%s/", isdn_getrev(tmprev));
2335 strcpy(tmprev, isdn_v110_revision);
2336 printk("%s", isdn_getrev(tmprev));
2337
2338#ifdef MODULE
2339 printk(" loaded\n");
2340#else
2341 printk("\n");
2342#endif
2343 isdn_info_update();
2344 return 0;
2345}
2346
2347/*
2348 * Unload module
2349 */
2350static void __exit isdn_exit(void)
2351{
2352#ifdef CONFIG_ISDN_PPP
2353 isdn_ppp_cleanup();
2354#endif
2355 if (isdn_net_rmall() < 0) {
2356 printk(KERN_WARNING "isdn: net-device busy, remove cancelled\n");
2357 return;
2358 }
2359 isdn_tty_exit();
2360 unregister_chrdev(ISDN_MAJOR, "isdn");
2361 del_timer_sync(&dev->timer);
2362 /* call vfree with interrupts enabled, else it will hang */
2363 vfree(dev);
2364 printk(KERN_NOTICE "ISDN-subsystem unloaded\n");
2365}
2366
2367module_init(isdn_init);
2368module_exit(isdn_exit);
diff --git a/drivers/isdn/i4l/isdn_common.h b/drivers/isdn/i4l/isdn_common.h
deleted file mode 100644
index 2260ef07ab9c..000000000000
--- a/drivers/isdn/i4l/isdn_common.h
+++ /dev/null
@@ -1,47 +0,0 @@
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_readbchan_tty(int, int, struct tty_port *, int);
41extern int isdn_get_free_channel(int, int, int, int, int, char *);
42extern int isdn_writebuf_skb_stub(int, int, int, struct sk_buff *);
43extern int register_isdn(isdn_if *i);
44extern int isdn_msncmp(const char *, const char *);
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
deleted file mode 100644
index 336523ec077c..000000000000
--- a/drivers/isdn/i4l/isdn_concap.c
+++ /dev/null
@@ -1,99 +0,0 @@
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
42static int 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 *) netdev_priv(ndev))->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
61static int isdn_concap_dl_connect_req(struct concap_proto *concap)
62{
63 struct net_device *ndev = concap->net_dev;
64 isdn_net_local *lp = netdev_priv(ndev);
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
74static int 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 .data_req = &isdn_concap_dl_data_req,
84 .connect_req = &isdn_concap_dl_connect_req,
85 .disconn_req = &isdn_concap_dl_disconn_req
86};
87
88/* The following should better go into a dedicated source file such that
89 this sourcefile does not need to include any protocol specific header
90 files. For now:
91*/
92struct concap_proto *isdn_concap_new(int encap)
93{
94 switch (encap) {
95 case ISDN_NET_ENCAP_X25IFACE:
96 return isdn_x25iface_proto_new();
97 }
98 return NULL;
99}
diff --git a/drivers/isdn/i4l/isdn_concap.h b/drivers/isdn/i4l/isdn_concap.h
deleted file mode 100644
index cd7e3ba74e25..000000000000
--- a/drivers/isdn/i4l/isdn_concap.h
+++ /dev/null
@@ -1,11 +0,0 @@
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_proto *isdn_concap_new(int);
diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c
deleted file mode 100644
index c138f66f2659..000000000000
--- a/drivers/isdn/i4l/isdn_net.c
+++ /dev/null
@@ -1,3198 +0,0 @@
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/isdn.h>
26#include <linux/slab.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 it 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_MASTER_PRIV(lp)->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
179static int isdn_net_force_dial_lp(isdn_net_local *);
180static netdev_tx_t isdn_net_start_xmit(struct sk_buff *,
181 struct net_device *);
182
183static void isdn_net_ciscohdlck_connected(isdn_net_local *lp);
184static void isdn_net_ciscohdlck_disconnected(isdn_net_local *lp);
185
186char *isdn_net_revision = "$Revision: 1.1.2.2 $";
187
188/*
189 * Code for raw-networking over ISDN
190 */
191
192static void
193isdn_net_unreachable(struct net_device *dev, struct sk_buff *skb, char *reason)
194{
195 if (skb) {
196
197 u_short proto = ntohs(skb->protocol);
198
199 printk(KERN_DEBUG "isdn_net: %s: %s, signalling dst_link_failure %s\n",
200 dev->name,
201 (reason != NULL) ? reason : "unknown",
202 (proto != ETH_P_IP) ? "Protocol != ETH_P_IP" : "");
203
204 dst_link_failure(skb);
205 }
206 else { /* dial not triggered by rawIP packet */
207 printk(KERN_DEBUG "isdn_net: %s: %s\n",
208 dev->name,
209 (reason != NULL) ? reason : "reason unknown");
210 }
211}
212
213static void
214isdn_net_reset(struct net_device *dev)
215{
216#ifdef CONFIG_ISDN_X25
217 struct concap_device_ops *dops =
218 ((isdn_net_local *)netdev_priv(dev))->dops;
219 struct concap_proto *cprot =
220 ((isdn_net_local *)netdev_priv(dev))->netdev->cprot;
221#endif
222#ifdef CONFIG_ISDN_X25
223 if (cprot && cprot->pops && dops)
224 cprot->pops->restart(cprot, dev, dops);
225#endif
226}
227
228/* Open/initialize the board. */
229static int
230isdn_net_open(struct net_device *dev)
231{
232 int i;
233 struct net_device *p;
234 struct in_device *in_dev;
235
236 /* moved here from isdn_net_reset, because only the master has an
237 interface associated which is supposed to be started. BTW:
238 we need to call netif_start_queue, not netif_wake_queue here */
239 netif_start_queue(dev);
240
241 isdn_net_reset(dev);
242 /* Fill in the MAC-level header (not needed, but for compatibility... */
243 for (i = 0; i < ETH_ALEN - sizeof(u32); i++)
244 dev->dev_addr[i] = 0xfc;
245 if ((in_dev = dev->ip_ptr) != NULL) {
246 /*
247 * Any address will do - we take the first
248 */
249 struct in_ifaddr *ifa = in_dev->ifa_list;
250 if (ifa != NULL)
251 memcpy(dev->dev_addr + 2, &ifa->ifa_local, 4);
252 }
253
254 /* If this interface has slaves, start them also */
255 p = MASTER_TO_SLAVE(dev);
256 if (p) {
257 while (p) {
258 isdn_net_reset(p);
259 p = MASTER_TO_SLAVE(p);
260 }
261 }
262 isdn_lock_drivers();
263 return 0;
264}
265
266/*
267 * Assign an ISDN-channel to a net-interface
268 */
269static void
270isdn_net_bind_channel(isdn_net_local *lp, int idx)
271{
272 lp->flags |= ISDN_NET_CONNECTED;
273 lp->isdn_device = dev->drvmap[idx];
274 lp->isdn_channel = dev->chanmap[idx];
275 dev->rx_netdev[idx] = lp->netdev;
276 dev->st_netdev[idx] = lp->netdev;
277}
278
279/*
280 * unbind a net-interface (resets interface after an error)
281 */
282static void
283isdn_net_unbind_channel(isdn_net_local *lp)
284{
285 skb_queue_purge(&lp->super_tx_queue);
286
287 if (!lp->master) { /* reset only master device */
288 /* Moral equivalent of dev_purge_queues():
289 BEWARE! This chunk of code cannot be called from hardware
290 interrupt handler. I hope it is true. --ANK
291 */
292 qdisc_reset_all_tx(lp->netdev->dev);
293 }
294 lp->dialstate = 0;
295 dev->rx_netdev[isdn_dc2minor(lp->isdn_device, lp->isdn_channel)] = NULL;
296 dev->st_netdev[isdn_dc2minor(lp->isdn_device, lp->isdn_channel)] = NULL;
297 if (lp->isdn_device != -1 && lp->isdn_channel != -1)
298 isdn_free_channel(lp->isdn_device, lp->isdn_channel,
299 ISDN_USAGE_NET);
300 lp->flags &= ~ISDN_NET_CONNECTED;
301 lp->isdn_device = -1;
302 lp->isdn_channel = -1;
303}
304
305/*
306 * Perform auto-hangup and cps-calculation for net-interfaces.
307 *
308 * auto-hangup:
309 * Increment idle-counter (this counter is reset on any incoming or
310 * outgoing packet), if counter exceeds configured limit either do a
311 * hangup immediately or - if configured - wait until just before the next
312 * charge-info.
313 *
314 * cps-calculation (needed for dynamic channel-bundling):
315 * Since this function is called every second, simply reset the
316 * byte-counter of the interface after copying it to the cps-variable.
317 */
318static unsigned long last_jiffies = -HZ;
319
320void
321isdn_net_autohup(void)
322{
323 isdn_net_dev *p = dev->netdev;
324 int anymore;
325
326 anymore = 0;
327 while (p) {
328 isdn_net_local *l = p->local;
329 if (jiffies == last_jiffies)
330 l->cps = l->transcount;
331 else
332 l->cps = (l->transcount * HZ) / (jiffies - last_jiffies);
333 l->transcount = 0;
334 if (dev->net_verbose > 3)
335 printk(KERN_DEBUG "%s: %d bogocps\n", p->dev->name, l->cps);
336 if ((l->flags & ISDN_NET_CONNECTED) && (!l->dialstate)) {
337 anymore = 1;
338 l->huptimer++;
339 /*
340 * if there is some dialmode where timeout-hangup
341 * should _not_ be done, check for that here
342 */
343 if ((l->onhtime) &&
344 (l->huptimer > l->onhtime))
345 {
346 if (l->hupflags & ISDN_MANCHARGE &&
347 l->hupflags & ISDN_CHARGEHUP) {
348 while (time_after(jiffies, l->chargetime + l->chargeint))
349 l->chargetime += l->chargeint;
350 if (time_after(jiffies, l->chargetime + l->chargeint - 2 * HZ))
351 if (l->outgoing || l->hupflags & ISDN_INHUP)
352 isdn_net_hangup(p->dev);
353 } else if (l->outgoing) {
354 if (l->hupflags & ISDN_CHARGEHUP) {
355 if (l->hupflags & ISDN_WAITCHARGE) {
356 printk(KERN_DEBUG "isdn_net: Hupflags of %s are %X\n",
357 p->dev->name, l->hupflags);
358 isdn_net_hangup(p->dev);
359 } else if (time_after(jiffies, l->chargetime + l->chargeint)) {
360 printk(KERN_DEBUG
361 "isdn_net: %s: chtime = %lu, chint = %d\n",
362 p->dev->name, l->chargetime, l->chargeint);
363 isdn_net_hangup(p->dev);
364 }
365 } else
366 isdn_net_hangup(p->dev);
367 } else if (l->hupflags & ISDN_INHUP)
368 isdn_net_hangup(p->dev);
369 }
370
371 if (dev->global_flags & ISDN_GLOBAL_STOPPED || (ISDN_NET_DIALMODE(*l) == ISDN_NET_DM_OFF)) {
372 isdn_net_hangup(p->dev);
373 break;
374 }
375 }
376 p = (isdn_net_dev *) p->next;
377 }
378 last_jiffies = jiffies;
379 isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, anymore);
380}
381
382static void isdn_net_lp_disconnected(isdn_net_local *lp)
383{
384 isdn_net_rm_from_bundle(lp);
385}
386
387/*
388 * Handle status-messages from ISDN-interfacecard.
389 * This function is called from within the main-status-dispatcher
390 * isdn_status_callback, which itself is called from the low-level driver.
391 * Return: 1 = Event handled, 0 = not for us or unknown Event.
392 */
393int
394isdn_net_stat_callback(int idx, isdn_ctrl *c)
395{
396 isdn_net_dev *p = dev->st_netdev[idx];
397 int cmd = c->command;
398
399 if (p) {
400 isdn_net_local *lp = p->local;
401#ifdef CONFIG_ISDN_X25
402 struct concap_proto *cprot = lp->netdev->cprot;
403 struct concap_proto_ops *pops = cprot ? cprot->pops : NULL;
404#endif
405 switch (cmd) {
406 case ISDN_STAT_BSENT:
407 /* A packet has successfully been sent out */
408 if ((lp->flags & ISDN_NET_CONNECTED) &&
409 (!lp->dialstate)) {
410 isdn_net_dec_frame_cnt(lp);
411 lp->stats.tx_packets++;
412 lp->stats.tx_bytes += c->parm.length;
413 }
414 return 1;
415 case ISDN_STAT_DCONN:
416 /* D-Channel is up */
417 switch (lp->dialstate) {
418 case 4:
419 case 7:
420 case 8:
421 lp->dialstate++;
422 return 1;
423 case 12:
424 lp->dialstate = 5;
425 return 1;
426 }
427 break;
428 case ISDN_STAT_DHUP:
429 /* Either D-Channel-hangup or error during dialout */
430#ifdef CONFIG_ISDN_X25
431 /* If we are not connencted then dialing had
432 failed. If there are generic encap protocol
433 receiver routines signal the closure of
434 the link*/
435
436 if (!(lp->flags & ISDN_NET_CONNECTED)
437 && pops && pops->disconn_ind)
438 pops->disconn_ind(cprot);
439#endif /* CONFIG_ISDN_X25 */
440 if ((!lp->dialstate) && (lp->flags & ISDN_NET_CONNECTED)) {
441 if (lp->p_encap == ISDN_NET_ENCAP_CISCOHDLCK)
442 isdn_net_ciscohdlck_disconnected(lp);
443#ifdef CONFIG_ISDN_PPP
444 if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
445 isdn_ppp_free(lp);
446#endif
447 isdn_net_lp_disconnected(lp);
448 isdn_all_eaz(lp->isdn_device, lp->isdn_channel);
449 printk(KERN_INFO "%s: remote hangup\n", p->dev->name);
450 printk(KERN_INFO "%s: Chargesum is %d\n", p->dev->name,
451 lp->charge);
452 isdn_net_unbind_channel(lp);
453 return 1;
454 }
455 break;
456#ifdef CONFIG_ISDN_X25
457 case ISDN_STAT_BHUP:
458 /* B-Channel-hangup */
459 /* try if there are generic encap protocol
460 receiver routines and signal the closure of
461 the link */
462 if (pops && pops->disconn_ind) {
463 pops->disconn_ind(cprot);
464 return 1;
465 }
466 break;
467#endif /* CONFIG_ISDN_X25 */
468 case ISDN_STAT_BCONN:
469 /* B-Channel is up */
470 isdn_net_zero_frame_cnt(lp);
471 switch (lp->dialstate) {
472 case 5:
473 case 6:
474 case 7:
475 case 8:
476 case 9:
477 case 10:
478 case 12:
479 if (lp->dialstate <= 6) {
480 dev->usage[idx] |= ISDN_USAGE_OUTGOING;
481 isdn_info_update();
482 } else
483 dev->rx_netdev[idx] = p;
484 lp->dialstate = 0;
485 isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, 1);
486 if (lp->p_encap == ISDN_NET_ENCAP_CISCOHDLCK)
487 isdn_net_ciscohdlck_connected(lp);
488 if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP) {
489 if (lp->master) { /* is lp a slave? */
490 isdn_net_dev *nd = ISDN_MASTER_PRIV(lp)->netdev;
491 isdn_net_add_to_bundle(nd, lp);
492 }
493 }
494 printk(KERN_INFO "isdn_net: %s connected\n", p->dev->name);
495 /* If first Chargeinfo comes before B-Channel connect,
496 * we correct the timestamp here.
497 */
498 lp->chargetime = jiffies;
499
500 /* reset dial-timeout */
501 lp->dialstarted = 0;
502 lp->dialwait_timer = 0;
503
504#ifdef CONFIG_ISDN_PPP
505 if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
506 isdn_ppp_wakeup_daemon(lp);
507#endif
508#ifdef CONFIG_ISDN_X25
509 /* try if there are generic concap receiver routines */
510 if (pops)
511 if (pops->connect_ind)
512 pops->connect_ind(cprot);
513#endif /* CONFIG_ISDN_X25 */
514 /* ppp needs to do negotiations first */
515 if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP)
516 isdn_net_device_wake_queue(lp);
517 return 1;
518 }
519 break;
520 case ISDN_STAT_NODCH:
521 /* No D-Channel avail. */
522 if (lp->dialstate == 4) {
523 lp->dialstate--;
524 return 1;
525 }
526 break;
527 case ISDN_STAT_CINF:
528 /* Charge-info from TelCo. Calculate interval between
529 * charge-infos and set timestamp for last info for
530 * usage by isdn_net_autohup()
531 */
532 lp->charge++;
533 if (lp->hupflags & ISDN_HAVECHARGE) {
534 lp->hupflags &= ~ISDN_WAITCHARGE;
535 lp->chargeint = jiffies - lp->chargetime - (2 * HZ);
536 }
537 if (lp->hupflags & ISDN_WAITCHARGE)
538 lp->hupflags |= ISDN_HAVECHARGE;
539 lp->chargetime = jiffies;
540 printk(KERN_DEBUG "isdn_net: Got CINF chargetime of %s now %lu\n",
541 p->dev->name, lp->chargetime);
542 return 1;
543 }
544 }
545 return 0;
546}
547
548/*
549 * Perform dialout for net-interfaces and timeout-handling for
550 * D-Channel-up and B-Channel-up Messages.
551 * This function is initially called from within isdn_net_start_xmit() or
552 * or isdn_net_find_icall() after initializing the dialstate for an
553 * interface. If further calls are needed, the function schedules itself
554 * for a timer-callback via isdn_timer_function().
555 * The dialstate is also affected by incoming status-messages from
556 * the ISDN-Channel which are handled in isdn_net_stat_callback() above.
557 */
558void
559isdn_net_dial(void)
560{
561 isdn_net_dev *p = dev->netdev;
562 int anymore = 0;
563 int i;
564 isdn_ctrl cmd;
565 u_char *phone_number;
566
567 while (p) {
568 isdn_net_local *lp = p->local;
569
570#ifdef ISDN_DEBUG_NET_DIAL
571 if (lp->dialstate)
572 printk(KERN_DEBUG "%s: dialstate=%d\n", p->dev->name, lp->dialstate);
573#endif
574 switch (lp->dialstate) {
575 case 0:
576 /* Nothing to do for this interface */
577 break;
578 case 1:
579 /* Initiate dialout. Set phone-number-pointer to first number
580 * of interface.
581 */
582 lp->dial = lp->phone[1];
583 if (!lp->dial) {
584 printk(KERN_WARNING "%s: phone number deleted?\n",
585 p->dev->name);
586 isdn_net_hangup(p->dev);
587 break;
588 }
589 anymore = 1;
590
591 if (lp->dialtimeout > 0)
592 if (lp->dialstarted == 0 || time_after(jiffies, lp->dialstarted + lp->dialtimeout + lp->dialwait)) {
593 lp->dialstarted = jiffies;
594 lp->dialwait_timer = 0;
595 }
596
597 lp->dialstate++;
598 /* Fall through */
599 case 2:
600 /* Prepare dialing. Clear EAZ, then set EAZ. */
601 cmd.driver = lp->isdn_device;
602 cmd.arg = lp->isdn_channel;
603 cmd.command = ISDN_CMD_CLREAZ;
604 isdn_command(&cmd);
605 sprintf(cmd.parm.num, "%s", isdn_map_eaz2msn(lp->msn, cmd.driver));
606 cmd.command = ISDN_CMD_SETEAZ;
607 isdn_command(&cmd);
608 lp->dialretry = 0;
609 anymore = 1;
610 lp->dialstate++;
611 /* Fall through */
612 case 3:
613 /* Setup interface, dial current phone-number, switch to next number.
614 * If list of phone-numbers is exhausted, increment
615 * retry-counter.
616 */
617 if (dev->global_flags & ISDN_GLOBAL_STOPPED || (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF)) {
618 char *s;
619 if (dev->global_flags & ISDN_GLOBAL_STOPPED)
620 s = "dial suppressed: isdn system stopped";
621 else
622 s = "dial suppressed: dialmode `off'";
623 isdn_net_unreachable(p->dev, NULL, s);
624 isdn_net_hangup(p->dev);
625 break;
626 }
627 cmd.driver = lp->isdn_device;
628 cmd.command = ISDN_CMD_SETL2;
629 cmd.arg = lp->isdn_channel + (lp->l2_proto << 8);
630 isdn_command(&cmd);
631 cmd.driver = lp->isdn_device;
632 cmd.command = ISDN_CMD_SETL3;
633 cmd.arg = lp->isdn_channel + (lp->l3_proto << 8);
634 isdn_command(&cmd);
635 cmd.driver = lp->isdn_device;
636 cmd.arg = lp->isdn_channel;
637 if (!lp->dial) {
638 printk(KERN_WARNING "%s: phone number deleted?\n",
639 p->dev->name);
640 isdn_net_hangup(p->dev);
641 break;
642 }
643 if (!strncmp(lp->dial->num, "LEASED", strlen("LEASED"))) {
644 lp->dialstate = 4;
645 printk(KERN_INFO "%s: Open leased line ...\n", p->dev->name);
646 } else {
647 if (lp->dialtimeout > 0)
648 if (time_after(jiffies, lp->dialstarted + lp->dialtimeout)) {
649 lp->dialwait_timer = jiffies + lp->dialwait;
650 lp->dialstarted = 0;
651 isdn_net_unreachable(p->dev, NULL, "dial: timed out");
652 isdn_net_hangup(p->dev);
653 break;
654 }
655
656 cmd.driver = lp->isdn_device;
657 cmd.command = ISDN_CMD_DIAL;
658 cmd.parm.setup.si2 = 0;
659
660 /* check for DOV */
661 phone_number = lp->dial->num;
662 if ((*phone_number == 'v') ||
663 (*phone_number == 'V')) { /* DOV call */
664 cmd.parm.setup.si1 = 1;
665 } else { /* DATA call */
666 cmd.parm.setup.si1 = 7;
667 }
668
669 strcpy(cmd.parm.setup.phone, phone_number);
670 /*
671 * Switch to next number or back to start if at end of list.
672 */
673 if (!(lp->dial = (isdn_net_phone *) lp->dial->next)) {
674 lp->dial = lp->phone[1];
675 lp->dialretry++;
676
677 if (lp->dialretry > lp->dialmax) {
678 if (lp->dialtimeout == 0) {
679 lp->dialwait_timer = jiffies + lp->dialwait;
680 lp->dialstarted = 0;
681 isdn_net_unreachable(p->dev, NULL, "dial: tried all numbers dialmax times");
682 }
683 isdn_net_hangup(p->dev);
684 break;
685 }
686 }
687 sprintf(cmd.parm.setup.eazmsn, "%s",
688 isdn_map_eaz2msn(lp->msn, cmd.driver));
689 i = isdn_dc2minor(lp->isdn_device, lp->isdn_channel);
690 if (i >= 0) {
691 strcpy(dev->num[i], cmd.parm.setup.phone);
692 dev->usage[i] |= ISDN_USAGE_OUTGOING;
693 isdn_info_update();
694 }
695 printk(KERN_INFO "%s: dialing %d %s... %s\n", p->dev->name,
696 lp->dialretry, cmd.parm.setup.phone,
697 (cmd.parm.setup.si1 == 1) ? "DOV" : "");
698 lp->dtimer = 0;
699#ifdef ISDN_DEBUG_NET_DIAL
700 printk(KERN_DEBUG "dial: d=%d c=%d\n", lp->isdn_device,
701 lp->isdn_channel);
702#endif
703 isdn_command(&cmd);
704 }
705 lp->huptimer = 0;
706 lp->outgoing = 1;
707 if (lp->chargeint) {
708 lp->hupflags |= ISDN_HAVECHARGE;
709 lp->hupflags &= ~ISDN_WAITCHARGE;
710 } else {
711 lp->hupflags |= ISDN_WAITCHARGE;
712 lp->hupflags &= ~ISDN_HAVECHARGE;
713 }
714 anymore = 1;
715 lp->dialstate =
716 (lp->cbdelay &&
717 (lp->flags & ISDN_NET_CBOUT)) ? 12 : 4;
718 break;
719 case 4:
720 /* Wait for D-Channel-connect.
721 * If timeout, switch back to state 3.
722 * Dialmax-handling moved to state 3.
723 */
724 if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT10)
725 lp->dialstate = 3;
726 anymore = 1;
727 break;
728 case 5:
729 /* Got D-Channel-Connect, send B-Channel-request */
730 cmd.driver = lp->isdn_device;
731 cmd.arg = lp->isdn_channel;
732 cmd.command = ISDN_CMD_ACCEPTB;
733 anymore = 1;
734 lp->dtimer = 0;
735 lp->dialstate++;
736 isdn_command(&cmd);
737 break;
738 case 6:
739 /* Wait for B- or D-Channel-connect. If timeout,
740 * switch back to state 3.
741 */
742#ifdef ISDN_DEBUG_NET_DIAL
743 printk(KERN_DEBUG "dialtimer2: %d\n", lp->dtimer);
744#endif
745 if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT10)
746 lp->dialstate = 3;
747 anymore = 1;
748 break;
749 case 7:
750 /* Got incoming Call, setup L2 and L3 protocols,
751 * then wait for D-Channel-connect
752 */
753#ifdef ISDN_DEBUG_NET_DIAL
754 printk(KERN_DEBUG "dialtimer4: %d\n", lp->dtimer);
755#endif
756 cmd.driver = lp->isdn_device;
757 cmd.command = ISDN_CMD_SETL2;
758 cmd.arg = lp->isdn_channel + (lp->l2_proto << 8);
759 isdn_command(&cmd);
760 cmd.driver = lp->isdn_device;
761 cmd.command = ISDN_CMD_SETL3;
762 cmd.arg = lp->isdn_channel + (lp->l3_proto << 8);
763 isdn_command(&cmd);
764 if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT15)
765 isdn_net_hangup(p->dev);
766 else {
767 anymore = 1;
768 lp->dialstate++;
769 }
770 break;
771 case 9:
772 /* Got incoming D-Channel-Connect, send B-Channel-request */
773 cmd.driver = lp->isdn_device;
774 cmd.arg = lp->isdn_channel;
775 cmd.command = ISDN_CMD_ACCEPTB;
776 isdn_command(&cmd);
777 anymore = 1;
778 lp->dtimer = 0;
779 lp->dialstate++;
780 break;
781 case 8:
782 case 10:
783 /* Wait for B- or D-channel-connect */
784#ifdef ISDN_DEBUG_NET_DIAL
785 printk(KERN_DEBUG "dialtimer4: %d\n", lp->dtimer);
786#endif
787 if (lp->dtimer++ > ISDN_TIMER_DTIMEOUT10)
788 isdn_net_hangup(p->dev);
789 else
790 anymore = 1;
791 break;
792 case 11:
793 /* Callback Delay */
794 if (lp->dtimer++ > lp->cbdelay)
795 lp->dialstate = 1;
796 anymore = 1;
797 break;
798 case 12:
799 /* Remote does callback. Hangup after cbdelay, then wait for incoming
800 * call (in state 4).
801 */
802 if (lp->dtimer++ > lp->cbdelay)
803 {
804 printk(KERN_INFO "%s: hangup waiting for callback ...\n", p->dev->name);
805 lp->dtimer = 0;
806 lp->dialstate = 4;
807 cmd.driver = lp->isdn_device;
808 cmd.command = ISDN_CMD_HANGUP;
809 cmd.arg = lp->isdn_channel;
810 isdn_command(&cmd);
811 isdn_all_eaz(lp->isdn_device, lp->isdn_channel);
812 }
813 anymore = 1;
814 break;
815 default:
816 printk(KERN_WARNING "isdn_net: Illegal dialstate %d for device %s\n",
817 lp->dialstate, p->dev->name);
818 }
819 p = (isdn_net_dev *) p->next;
820 }
821 isdn_timer_ctrl(ISDN_TIMER_NETDIAL, anymore);
822}
823
824/*
825 * Perform hangup for a net-interface.
826 */
827void
828isdn_net_hangup(struct net_device *d)
829{
830 isdn_net_local *lp = netdev_priv(d);
831 isdn_ctrl cmd;
832#ifdef CONFIG_ISDN_X25
833 struct concap_proto *cprot = lp->netdev->cprot;
834 struct concap_proto_ops *pops = cprot ? cprot->pops : NULL;
835#endif
836
837 if (lp->flags & ISDN_NET_CONNECTED) {
838 if (lp->slave != NULL) {
839 isdn_net_local *slp = ISDN_SLAVE_PRIV(lp);
840 if (slp->flags & ISDN_NET_CONNECTED) {
841 printk(KERN_INFO
842 "isdn_net: hang up slave %s before %s\n",
843 lp->slave->name, d->name);
844 isdn_net_hangup(lp->slave);
845 }
846 }
847 printk(KERN_INFO "isdn_net: local hangup %s\n", d->name);
848#ifdef CONFIG_ISDN_PPP
849 if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
850 isdn_ppp_free(lp);
851#endif
852 isdn_net_lp_disconnected(lp);
853#ifdef CONFIG_ISDN_X25
854 /* try if there are generic encap protocol
855 receiver routines and signal the closure of
856 the link */
857 if (pops && pops->disconn_ind)
858 pops->disconn_ind(cprot);
859#endif /* CONFIG_ISDN_X25 */
860
861 cmd.driver = lp->isdn_device;
862 cmd.command = ISDN_CMD_HANGUP;
863 cmd.arg = lp->isdn_channel;
864 isdn_command(&cmd);
865 printk(KERN_INFO "%s: Chargesum is %d\n", d->name, lp->charge);
866 isdn_all_eaz(lp->isdn_device, lp->isdn_channel);
867 }
868 isdn_net_unbind_channel(lp);
869}
870
871typedef struct {
872 __be16 source;
873 __be16 dest;
874} ip_ports;
875
876static void
877isdn_net_log_skb(struct sk_buff *skb, isdn_net_local *lp)
878{
879 /* hopefully, this was set correctly */
880 const u_char *p = skb_network_header(skb);
881 unsigned short proto = ntohs(skb->protocol);
882 int data_ofs;
883 ip_ports *ipp;
884 char addinfo[100];
885
886 addinfo[0] = '\0';
887 /* This check stolen from 2.1.72 dev_queue_xmit_nit() */
888 if (p < skb->data || skb_network_header(skb) >= skb_tail_pointer(skb)) {
889 /* fall back to old isdn_net_log_packet method() */
890 char *buf = skb->data;
891
892 printk(KERN_DEBUG "isdn_net: protocol %04x is buggy, dev %s\n", skb->protocol, lp->netdev->dev->name);
893 p = buf;
894 proto = ETH_P_IP;
895 switch (lp->p_encap) {
896 case ISDN_NET_ENCAP_IPTYP:
897 proto = ntohs(*(__be16 *)&buf[0]);
898 p = &buf[2];
899 break;
900 case ISDN_NET_ENCAP_ETHER:
901 proto = ntohs(*(__be16 *)&buf[12]);
902 p = &buf[14];
903 break;
904 case ISDN_NET_ENCAP_CISCOHDLC:
905 proto = ntohs(*(__be16 *)&buf[2]);
906 p = &buf[4];
907 break;
908#ifdef CONFIG_ISDN_PPP
909 case ISDN_NET_ENCAP_SYNCPPP:
910 proto = ntohs(skb->protocol);
911 p = &buf[IPPP_MAX_HEADER];
912 break;
913#endif
914 }
915 }
916 data_ofs = ((p[0] & 15) * 4);
917 switch (proto) {
918 case ETH_P_IP:
919 switch (p[9]) {
920 case 1:
921 strcpy(addinfo, " ICMP");
922 break;
923 case 2:
924 strcpy(addinfo, " IGMP");
925 break;
926 case 4:
927 strcpy(addinfo, " IPIP");
928 break;
929 case 6:
930 ipp = (ip_ports *) (&p[data_ofs]);
931 sprintf(addinfo, " TCP, port: %d -> %d", ntohs(ipp->source),
932 ntohs(ipp->dest));
933 break;
934 case 8:
935 strcpy(addinfo, " EGP");
936 break;
937 case 12:
938 strcpy(addinfo, " PUP");
939 break;
940 case 17:
941 ipp = (ip_ports *) (&p[data_ofs]);
942 sprintf(addinfo, " UDP, port: %d -> %d", ntohs(ipp->source),
943 ntohs(ipp->dest));
944 break;
945 case 22:
946 strcpy(addinfo, " IDP");
947 break;
948 }
949 printk(KERN_INFO "OPEN: %pI4 -> %pI4%s\n",
950 p + 12, p + 16, addinfo);
951 break;
952 case ETH_P_ARP:
953 printk(KERN_INFO "OPEN: ARP %pI4 -> *.*.*.* ?%pI4\n",
954 p + 14, p + 24);
955 break;
956 }
957}
958
959/*
960 * this function is used to send supervisory data, i.e. data which was
961 * not received from the network layer, but e.g. frames from ipppd, CCP
962 * reset frames etc.
963 */
964void isdn_net_write_super(isdn_net_local *lp, struct sk_buff *skb)
965{
966 if (in_irq()) {
967 // we can't grab the lock from irq context,
968 // so we just queue the packet
969 skb_queue_tail(&lp->super_tx_queue, skb);
970 schedule_work(&lp->tqueue);
971 return;
972 }
973
974 spin_lock_bh(&lp->xmit_lock);
975 if (!isdn_net_lp_busy(lp)) {
976 isdn_net_writebuf_skb(lp, skb);
977 } else {
978 skb_queue_tail(&lp->super_tx_queue, skb);
979 }
980 spin_unlock_bh(&lp->xmit_lock);
981}
982
983/*
984 * called from tq_immediate
985 */
986static void isdn_net_softint(struct work_struct *work)
987{
988 isdn_net_local *lp = container_of(work, isdn_net_local, tqueue);
989 struct sk_buff *skb;
990
991 spin_lock_bh(&lp->xmit_lock);
992 while (!isdn_net_lp_busy(lp)) {
993 skb = skb_dequeue(&lp->super_tx_queue);
994 if (!skb)
995 break;
996 isdn_net_writebuf_skb(lp, skb);
997 }
998 spin_unlock_bh(&lp->xmit_lock);
999}
1000
1001/*
1002 * all frames sent from the (net) LL to a HL driver should go via this function
1003 * it's serialized by the caller holding the lp->xmit_lock spinlock
1004 */
1005void isdn_net_writebuf_skb(isdn_net_local *lp, struct sk_buff *skb)
1006{
1007 int ret;
1008 int len = skb->len; /* save len */
1009
1010 /* before obtaining the lock the caller should have checked that
1011 the lp isn't busy */
1012 if (isdn_net_lp_busy(lp)) {
1013 printk("isdn BUG at %s:%d!\n", __FILE__, __LINE__);
1014 goto error;
1015 }
1016
1017 if (!(lp->flags & ISDN_NET_CONNECTED)) {
1018 printk("isdn BUG at %s:%d!\n", __FILE__, __LINE__);
1019 goto error;
1020 }
1021 ret = isdn_writebuf_skb_stub(lp->isdn_device, lp->isdn_channel, 1, skb);
1022 if (ret != len) {
1023 /* we should never get here */
1024 printk(KERN_WARNING "%s: HL driver queue full\n", lp->netdev->dev->name);
1025 goto error;
1026 }
1027
1028 lp->transcount += len;
1029 isdn_net_inc_frame_cnt(lp);
1030 return;
1031
1032error:
1033 dev_kfree_skb(skb);
1034 lp->stats.tx_errors++;
1035
1036}
1037
1038
1039/*
1040 * Helper function for isdn_net_start_xmit.
1041 * When called, the connection is already established.
1042 * Based on cps-calculation, check if device is overloaded.
1043 * If so, and if a slave exists, trigger dialing for it.
1044 * If any slave is online, deliver packets using a simple round robin
1045 * scheme.
1046 *
1047 * Return: 0 on success, !0 on failure.
1048 */
1049
1050static int
1051isdn_net_xmit(struct net_device *ndev, struct sk_buff *skb)
1052{
1053 isdn_net_dev *nd;
1054 isdn_net_local *slp;
1055 isdn_net_local *lp = netdev_priv(ndev);
1056 int retv = NETDEV_TX_OK;
1057
1058 if (((isdn_net_local *) netdev_priv(ndev))->master) {
1059 printk("isdn BUG at %s:%d!\n", __FILE__, __LINE__);
1060 dev_kfree_skb(skb);
1061 return NETDEV_TX_OK;
1062 }
1063
1064 /* For the other encaps the header has already been built */
1065#ifdef CONFIG_ISDN_PPP
1066 if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) {
1067 return isdn_ppp_xmit(skb, ndev);
1068 }
1069#endif
1070 nd = ((isdn_net_local *) netdev_priv(ndev))->netdev;
1071 lp = isdn_net_get_locked_lp(nd);
1072 if (!lp) {
1073 printk(KERN_WARNING "%s: all channels busy - requeuing!\n", ndev->name);
1074 return NETDEV_TX_BUSY;
1075 }
1076 /* we have our lp locked from now on */
1077
1078 /* Reset hangup-timeout */
1079 lp->huptimer = 0; // FIXME?
1080 isdn_net_writebuf_skb(lp, skb);
1081 spin_unlock_bh(&lp->xmit_lock);
1082
1083 /* the following stuff is here for backwards compatibility.
1084 * in future, start-up and hangup of slaves (based on current load)
1085 * should move to userspace and get based on an overall cps
1086 * calculation
1087 */
1088 if (lp->cps > lp->triggercps) {
1089 if (lp->slave) {
1090 if (!lp->sqfull) {
1091 /* First time overload: set timestamp only */
1092 lp->sqfull = 1;
1093 lp->sqfull_stamp = jiffies;
1094 } else {
1095 /* subsequent overload: if slavedelay exceeded, start dialing */
1096 if (time_after(jiffies, lp->sqfull_stamp + lp->slavedelay)) {
1097 slp = ISDN_SLAVE_PRIV(lp);
1098 if (!(slp->flags & ISDN_NET_CONNECTED)) {
1099 isdn_net_force_dial_lp(ISDN_SLAVE_PRIV(lp));
1100 }
1101 }
1102 }
1103 }
1104 } else {
1105 if (lp->sqfull && time_after(jiffies, lp->sqfull_stamp + lp->slavedelay + (10 * HZ))) {
1106 lp->sqfull = 0;
1107 }
1108 /* this is a hack to allow auto-hangup for slaves on moderate loads */
1109 nd->queue = nd->local;
1110 }
1111
1112 return retv;
1113
1114}
1115
1116static void
1117isdn_net_adjust_hdr(struct sk_buff *skb, struct net_device *dev)
1118{
1119 isdn_net_local *lp = netdev_priv(dev);
1120 if (!skb)
1121 return;
1122 if (lp->p_encap == ISDN_NET_ENCAP_ETHER) {
1123 const int pullsize = skb_network_offset(skb) - ETH_HLEN;
1124 if (pullsize > 0) {
1125 printk(KERN_DEBUG "isdn_net: Pull junk %d\n", pullsize);
1126 skb_pull(skb, pullsize);
1127 }
1128 }
1129}
1130
1131
1132static void isdn_net_tx_timeout(struct net_device *ndev)
1133{
1134 isdn_net_local *lp = netdev_priv(ndev);
1135
1136 printk(KERN_WARNING "isdn_tx_timeout dev %s dialstate %d\n", ndev->name, lp->dialstate);
1137 if (!lp->dialstate) {
1138 lp->stats.tx_errors++;
1139 /*
1140 * There is a certain probability that this currently
1141 * works at all because if we always wake up the interface,
1142 * then upper layer will try to send the next packet
1143 * immediately. And then, the old clean_up logic in the
1144 * driver will hopefully continue to work as it used to do.
1145 *
1146 * This is rather primitive right know, we better should
1147 * clean internal queues here, in particular for multilink and
1148 * ppp, and reset HL driver's channel, too. --HE
1149 *
1150 * actually, this may not matter at all, because ISDN hardware
1151 * should not see transmitter hangs at all IMO
1152 * changed KERN_DEBUG to KERN_WARNING to find out if this is
1153 * ever called --KG
1154 */
1155 }
1156 netif_trans_update(ndev);
1157 netif_wake_queue(ndev);
1158}
1159
1160/*
1161 * Try sending a packet.
1162 * If this interface isn't connected to a ISDN-Channel, find a free channel,
1163 * and start dialing.
1164 */
1165static netdev_tx_t
1166isdn_net_start_xmit(struct sk_buff *skb, struct net_device *ndev)
1167{
1168 isdn_net_local *lp = netdev_priv(ndev);
1169#ifdef CONFIG_ISDN_X25
1170 struct concap_proto *cprot = lp->netdev->cprot;
1171/* At this point hard_start_xmit() passes control to the encapsulation
1172 protocol (if present).
1173 For X.25 auto-dialing is completly bypassed because:
1174 - It does not conform with the semantics of a reliable datalink
1175 service as needed by X.25 PLP.
1176 - I don't want that the interface starts dialing when the network layer
1177 sends a message which requests to disconnect the lapb link (or if it
1178 sends any other message not resulting in data transmission).
1179 Instead, dialing will be initiated by the encapsulation protocol entity
1180 when a dl_establish request is received from the upper layer.
1181*/
1182 if (cprot && cprot->pops) {
1183 int ret = cprot->pops->encap_and_xmit(cprot, skb);
1184
1185 if (ret)
1186 netif_stop_queue(ndev);
1187 return ret;
1188 } else
1189#endif
1190 /* auto-dialing xmit function */
1191 {
1192#ifdef ISDN_DEBUG_NET_DUMP
1193 u_char *buf;
1194#endif
1195 isdn_net_adjust_hdr(skb, ndev);
1196#ifdef ISDN_DEBUG_NET_DUMP
1197 buf = skb->data;
1198 isdn_dumppkt("S:", buf, skb->len, 40);
1199#endif
1200
1201 if (!(lp->flags & ISDN_NET_CONNECTED)) {
1202 int chi;
1203 /* only do autodial if allowed by config */
1204 if (!(ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_AUTO)) {
1205 isdn_net_unreachable(ndev, skb, "dial rejected: interface not in dialmode `auto'");
1206 dev_kfree_skb(skb);
1207 return NETDEV_TX_OK;
1208 }
1209 if (lp->phone[1]) {
1210 ulong flags;
1211
1212 if (lp->dialwait_timer <= 0)
1213 if (lp->dialstarted > 0 && lp->dialtimeout > 0 && time_before(jiffies, lp->dialstarted + lp->dialtimeout + lp->dialwait))
1214 lp->dialwait_timer = lp->dialstarted + lp->dialtimeout + lp->dialwait;
1215
1216 if (lp->dialwait_timer > 0) {
1217 if (time_before(jiffies, lp->dialwait_timer)) {
1218 isdn_net_unreachable(ndev, skb, "dial rejected: retry-time not reached");
1219 dev_kfree_skb(skb);
1220 return NETDEV_TX_OK;
1221 } else
1222 lp->dialwait_timer = 0;
1223 }
1224 /* Grab a free ISDN-Channel */
1225 spin_lock_irqsave(&dev->lock, flags);
1226 if (((chi =
1227 isdn_get_free_channel(
1228 ISDN_USAGE_NET,
1229 lp->l2_proto,
1230 lp->l3_proto,
1231 lp->pre_device,
1232 lp->pre_channel,
1233 lp->msn)
1234 ) < 0) &&
1235 ((chi =
1236 isdn_get_free_channel(
1237 ISDN_USAGE_NET,
1238 lp->l2_proto,
1239 lp->l3_proto,
1240 lp->pre_device,
1241 lp->pre_channel^1,
1242 lp->msn)
1243 ) < 0)) {
1244 spin_unlock_irqrestore(&dev->lock, flags);
1245 isdn_net_unreachable(ndev, skb,
1246 "No channel");
1247 dev_kfree_skb(skb);
1248 return NETDEV_TX_OK;
1249 }
1250 /* Log packet, which triggered dialing */
1251 if (dev->net_verbose)
1252 isdn_net_log_skb(skb, lp);
1253 lp->dialstate = 1;
1254 /* Connect interface with channel */
1255 isdn_net_bind_channel(lp, chi);
1256#ifdef CONFIG_ISDN_PPP
1257 if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) {
1258 /* no 'first_skb' handling for syncPPP */
1259 if (isdn_ppp_bind(lp) < 0) {
1260 dev_kfree_skb(skb);
1261 isdn_net_unbind_channel(lp);
1262 spin_unlock_irqrestore(&dev->lock, flags);
1263 return NETDEV_TX_OK; /* STN (skb to nirvana) ;) */
1264 }
1265#ifdef CONFIG_IPPP_FILTER
1266 if (isdn_ppp_autodial_filter(skb, lp)) {
1267 isdn_ppp_free(lp);
1268 isdn_net_unbind_channel(lp);
1269 spin_unlock_irqrestore(&dev->lock, flags);
1270 isdn_net_unreachable(ndev, skb, "dial rejected: packet filtered");
1271 dev_kfree_skb(skb);
1272 return NETDEV_TX_OK;
1273 }
1274#endif
1275 spin_unlock_irqrestore(&dev->lock, flags);
1276 isdn_net_dial(); /* Initiate dialing */
1277 netif_stop_queue(ndev);
1278 return NETDEV_TX_BUSY; /* let upper layer requeue skb packet */
1279 }
1280#endif
1281 /* Initiate dialing */
1282 spin_unlock_irqrestore(&dev->lock, flags);
1283 isdn_net_dial();
1284 isdn_net_device_stop_queue(lp);
1285 return NETDEV_TX_BUSY;
1286 } else {
1287 isdn_net_unreachable(ndev, skb,
1288 "No phone number");
1289 dev_kfree_skb(skb);
1290 return NETDEV_TX_OK;
1291 }
1292 } else {
1293 /* Device is connected to an ISDN channel */
1294 netif_trans_update(ndev);
1295 if (!lp->dialstate) {
1296 /* ISDN connection is established, try sending */
1297 int ret;
1298 ret = (isdn_net_xmit(ndev, skb));
1299 if (ret) netif_stop_queue(ndev);
1300 return ret;
1301 } else
1302 netif_stop_queue(ndev);
1303 }
1304 }
1305 return NETDEV_TX_BUSY;
1306}
1307
1308/*
1309 * Shutdown a net-interface.
1310 */
1311static int
1312isdn_net_close(struct net_device *dev)
1313{
1314 struct net_device *p;
1315#ifdef CONFIG_ISDN_X25
1316 struct concap_proto *cprot =
1317 ((isdn_net_local *)netdev_priv(dev))->netdev->cprot;
1318 /* printk(KERN_DEBUG "isdn_net_close %s\n" , dev-> name); */
1319#endif
1320
1321#ifdef CONFIG_ISDN_X25
1322 if (cprot && cprot->pops) cprot->pops->close(cprot);
1323#endif
1324 netif_stop_queue(dev);
1325 p = MASTER_TO_SLAVE(dev);
1326 if (p) {
1327 /* If this interface has slaves, stop them also */
1328 while (p) {
1329#ifdef CONFIG_ISDN_X25
1330 cprot = ((isdn_net_local *)netdev_priv(p))
1331 ->netdev->cprot;
1332 if (cprot && cprot->pops)
1333 cprot->pops->close(cprot);
1334#endif
1335 isdn_net_hangup(p);
1336 p = MASTER_TO_SLAVE(p);
1337 }
1338 }
1339 isdn_net_hangup(dev);
1340 isdn_unlock_drivers();
1341 return 0;
1342}
1343
1344/*
1345 * Get statistics
1346 */
1347static struct net_device_stats *
1348isdn_net_get_stats(struct net_device *dev)
1349{
1350 isdn_net_local *lp = netdev_priv(dev);
1351 return &lp->stats;
1352}
1353
1354/* This is simply a copy from std. eth.c EXCEPT we pull ETH_HLEN
1355 * instead of dev->hard_header_len off. This is done because the
1356 * lowlevel-driver has already pulled off its stuff when we get
1357 * here and this routine only gets called with p_encap == ETHER.
1358 * Determine the packet's protocol ID. The rule here is that we
1359 * assume 802.3 if the type field is short enough to be a length.
1360 * This is normal practice and works for any 'now in use' protocol.
1361 */
1362
1363static __be16
1364isdn_net_type_trans(struct sk_buff *skb, struct net_device *dev)
1365{
1366 struct ethhdr *eth;
1367 unsigned char *rawp;
1368
1369 skb_reset_mac_header(skb);
1370 skb_pull(skb, ETH_HLEN);
1371 eth = eth_hdr(skb);
1372
1373 if (*eth->h_dest & 1) {
1374 if (ether_addr_equal(eth->h_dest, dev->broadcast))
1375 skb->pkt_type = PACKET_BROADCAST;
1376 else
1377 skb->pkt_type = PACKET_MULTICAST;
1378 }
1379 /*
1380 * This ALLMULTI check should be redundant by 1.4
1381 * so don't forget to remove it.
1382 */
1383
1384 else if (dev->flags & (IFF_PROMISC /*| IFF_ALLMULTI*/)) {
1385 if (!ether_addr_equal(eth->h_dest, dev->dev_addr))
1386 skb->pkt_type = PACKET_OTHERHOST;
1387 }
1388 if (ntohs(eth->h_proto) >= ETH_P_802_3_MIN)
1389 return eth->h_proto;
1390
1391 rawp = skb->data;
1392
1393 /*
1394 * This is a magic hack to spot IPX packets. Older Novell breaks
1395 * the protocol design and runs IPX over 802.3 without an 802.2 LLC
1396 * layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This
1397 * won't work for fault tolerant netware but does for the rest.
1398 */
1399 if (*(unsigned short *) rawp == 0xFFFF)
1400 return htons(ETH_P_802_3);
1401 /*
1402 * Real 802.2 LLC
1403 */
1404 return htons(ETH_P_802_2);
1405}
1406
1407
1408/*
1409 * CISCO HDLC keepalive specific stuff
1410 */
1411static struct sk_buff*
1412isdn_net_ciscohdlck_alloc_skb(isdn_net_local *lp, int len)
1413{
1414 unsigned short hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen;
1415 struct sk_buff *skb;
1416
1417 skb = alloc_skb(hl + len, GFP_ATOMIC);
1418 if (skb)
1419 skb_reserve(skb, hl);
1420 else
1421 printk("isdn out of mem at %s:%d!\n", __FILE__, __LINE__);
1422 return skb;
1423}
1424
1425/* cisco hdlck device private ioctls */
1426static int
1427isdn_ciscohdlck_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1428{
1429 isdn_net_local *lp = netdev_priv(dev);
1430 unsigned long len = 0;
1431 unsigned long expires = 0;
1432 int tmp = 0;
1433 int period = lp->cisco_keepalive_period;
1434 s8 debserint = lp->cisco_debserint;
1435 int rc = 0;
1436
1437 if (lp->p_encap != ISDN_NET_ENCAP_CISCOHDLCK)
1438 return -EINVAL;
1439
1440 switch (cmd) {
1441 /* get/set keepalive period */
1442 case SIOCGKEEPPERIOD:
1443 len = (unsigned long)sizeof(lp->cisco_keepalive_period);
1444 if (copy_to_user(ifr->ifr_data,
1445 &lp->cisco_keepalive_period, len))
1446 rc = -EFAULT;
1447 break;
1448 case SIOCSKEEPPERIOD:
1449 tmp = lp->cisco_keepalive_period;
1450 len = (unsigned long)sizeof(lp->cisco_keepalive_period);
1451 if (copy_from_user(&period, ifr->ifr_data, len))
1452 rc = -EFAULT;
1453 if ((period > 0) && (period <= 32767))
1454 lp->cisco_keepalive_period = period;
1455 else
1456 rc = -EINVAL;
1457 if (!rc && (tmp != lp->cisco_keepalive_period)) {
1458 expires = (unsigned long)(jiffies +
1459 lp->cisco_keepalive_period * HZ);
1460 mod_timer(&lp->cisco_timer, expires);
1461 printk(KERN_INFO "%s: Keepalive period set "
1462 "to %d seconds.\n",
1463 dev->name, lp->cisco_keepalive_period);
1464 }
1465 break;
1466
1467 /* get/set debugging */
1468 case SIOCGDEBSERINT:
1469 len = (unsigned long)sizeof(lp->cisco_debserint);
1470 if (copy_to_user(ifr->ifr_data,
1471 &lp->cisco_debserint, len))
1472 rc = -EFAULT;
1473 break;
1474 case SIOCSDEBSERINT:
1475 len = (unsigned long)sizeof(lp->cisco_debserint);
1476 if (copy_from_user(&debserint,
1477 ifr->ifr_data, len))
1478 rc = -EFAULT;
1479 if ((debserint >= 0) && (debserint <= 64))
1480 lp->cisco_debserint = debserint;
1481 else
1482 rc = -EINVAL;
1483 break;
1484
1485 default:
1486 rc = -EINVAL;
1487 break;
1488 }
1489 return (rc);
1490}
1491
1492
1493static int isdn_net_ioctl(struct net_device *dev,
1494 struct ifreq *ifr, int cmd)
1495{
1496 isdn_net_local *lp = netdev_priv(dev);
1497
1498 switch (lp->p_encap) {
1499#ifdef CONFIG_ISDN_PPP
1500 case ISDN_NET_ENCAP_SYNCPPP:
1501 return isdn_ppp_dev_ioctl(dev, ifr, cmd);
1502#endif
1503 case ISDN_NET_ENCAP_CISCOHDLCK:
1504 return isdn_ciscohdlck_dev_ioctl(dev, ifr, cmd);
1505 default:
1506 return -EINVAL;
1507 }
1508}
1509
1510/* called via cisco_timer.function */
1511static void
1512isdn_net_ciscohdlck_slarp_send_keepalive(struct timer_list *t)
1513{
1514 isdn_net_local *lp = from_timer(lp, t, cisco_timer);
1515 struct sk_buff *skb;
1516 unsigned char *p;
1517 unsigned long last_cisco_myseq = lp->cisco_myseq;
1518 int myseq_diff = 0;
1519
1520 if (!(lp->flags & ISDN_NET_CONNECTED) || lp->dialstate) {
1521 printk("isdn BUG at %s:%d!\n", __FILE__, __LINE__);
1522 return;
1523 }
1524 lp->cisco_myseq++;
1525
1526 myseq_diff = (lp->cisco_myseq - lp->cisco_mineseen);
1527 if ((lp->cisco_line_state) && ((myseq_diff >= 3) || (myseq_diff <= -3))) {
1528 /* line up -> down */
1529 lp->cisco_line_state = 0;
1530 printk(KERN_WARNING
1531 "UPDOWN: Line protocol on Interface %s,"
1532 " changed state to down\n", lp->netdev->dev->name);
1533 /* should stop routing higher-level data across */
1534 } else if ((!lp->cisco_line_state) &&
1535 (myseq_diff >= 0) && (myseq_diff <= 2)) {
1536 /* line down -> up */
1537 lp->cisco_line_state = 1;
1538 printk(KERN_WARNING
1539 "UPDOWN: Line protocol on Interface %s,"
1540 " changed state to up\n", lp->netdev->dev->name);
1541 /* restart routing higher-level data across */
1542 }
1543
1544 if (lp->cisco_debserint)
1545 printk(KERN_DEBUG "%s: HDLC "
1546 "myseq %lu, mineseen %lu%c, yourseen %lu, %s\n",
1547 lp->netdev->dev->name, last_cisco_myseq, lp->cisco_mineseen,
1548 ((last_cisco_myseq == lp->cisco_mineseen) ? '*' : 040),
1549 lp->cisco_yourseq,
1550 ((lp->cisco_line_state) ? "line up" : "line down"));
1551
1552 skb = isdn_net_ciscohdlck_alloc_skb(lp, 4 + 14);
1553 if (!skb)
1554 return;
1555
1556 p = skb_put(skb, 4 + 14);
1557
1558 /* cisco header */
1559 *(u8 *)(p + 0) = CISCO_ADDR_UNICAST;
1560 *(u8 *)(p + 1) = CISCO_CTRL;
1561 *(__be16 *)(p + 2) = cpu_to_be16(CISCO_TYPE_SLARP);
1562
1563 /* slarp keepalive */
1564 *(__be32 *)(p + 4) = cpu_to_be32(CISCO_SLARP_KEEPALIVE);
1565 *(__be32 *)(p + 8) = cpu_to_be32(lp->cisco_myseq);
1566 *(__be32 *)(p + 12) = cpu_to_be32(lp->cisco_yourseq);
1567 *(__be16 *)(p + 16) = cpu_to_be16(0xffff); // reliability, always 0xffff
1568 p += 18;
1569
1570 isdn_net_write_super(lp, skb);
1571
1572 lp->cisco_timer.expires = jiffies + lp->cisco_keepalive_period * HZ;
1573
1574 add_timer(&lp->cisco_timer);
1575}
1576
1577static void
1578isdn_net_ciscohdlck_slarp_send_request(isdn_net_local *lp)
1579{
1580 struct sk_buff *skb;
1581 unsigned char *p;
1582
1583 skb = isdn_net_ciscohdlck_alloc_skb(lp, 4 + 14);
1584 if (!skb)
1585 return;
1586
1587 p = skb_put(skb, 4 + 14);
1588
1589 /* cisco header */
1590 *(u8 *)(p + 0) = CISCO_ADDR_UNICAST;
1591 *(u8 *)(p + 1) = CISCO_CTRL;
1592 *(__be16 *)(p + 2) = cpu_to_be16(CISCO_TYPE_SLARP);
1593
1594 /* slarp request */
1595 *(__be32 *)(p + 4) = cpu_to_be32(CISCO_SLARP_REQUEST);
1596 *(__be32 *)(p + 8) = cpu_to_be32(0); // address
1597 *(__be32 *)(p + 12) = cpu_to_be32(0); // netmask
1598 *(__be16 *)(p + 16) = cpu_to_be16(0); // unused
1599 p += 18;
1600
1601 isdn_net_write_super(lp, skb);
1602}
1603
1604static void
1605isdn_net_ciscohdlck_connected(isdn_net_local *lp)
1606{
1607 lp->cisco_myseq = 0;
1608 lp->cisco_mineseen = 0;
1609 lp->cisco_yourseq = 0;
1610 lp->cisco_keepalive_period = ISDN_TIMER_KEEPINT;
1611 lp->cisco_last_slarp_in = 0;
1612 lp->cisco_line_state = 0;
1613 lp->cisco_debserint = 0;
1614
1615 /* send slarp request because interface/seq.no.s reset */
1616 isdn_net_ciscohdlck_slarp_send_request(lp);
1617
1618 timer_setup(&lp->cisco_timer,
1619 isdn_net_ciscohdlck_slarp_send_keepalive, 0);
1620 lp->cisco_timer.expires = jiffies + lp->cisco_keepalive_period * HZ;
1621 add_timer(&lp->cisco_timer);
1622}
1623
1624static void
1625isdn_net_ciscohdlck_disconnected(isdn_net_local *lp)
1626{
1627 del_timer(&lp->cisco_timer);
1628}
1629
1630static void
1631isdn_net_ciscohdlck_slarp_send_reply(isdn_net_local *lp)
1632{
1633 struct sk_buff *skb;
1634 unsigned char *p;
1635 struct in_device *in_dev = NULL;
1636 __be32 addr = 0; /* local ipv4 address */
1637 __be32 mask = 0; /* local netmask */
1638
1639 if ((in_dev = lp->netdev->dev->ip_ptr) != NULL) {
1640 /* take primary(first) address of interface */
1641 struct in_ifaddr *ifa = in_dev->ifa_list;
1642 if (ifa != NULL) {
1643 addr = ifa->ifa_local;
1644 mask = ifa->ifa_mask;
1645 }
1646 }
1647
1648 skb = isdn_net_ciscohdlck_alloc_skb(lp, 4 + 14);
1649 if (!skb)
1650 return;
1651
1652 p = skb_put(skb, 4 + 14);
1653
1654 /* cisco header */
1655 *(u8 *)(p + 0) = CISCO_ADDR_UNICAST;
1656 *(u8 *)(p + 1) = CISCO_CTRL;
1657 *(__be16 *)(p + 2) = cpu_to_be16(CISCO_TYPE_SLARP);
1658
1659 /* slarp reply, send own ip/netmask; if values are nonsense remote
1660 * should think we are unable to provide it with an address via SLARP */
1661 *(__be32 *)(p + 4) = cpu_to_be32(CISCO_SLARP_REPLY);
1662 *(__be32 *)(p + 8) = addr; // address
1663 *(__be32 *)(p + 12) = mask; // netmask
1664 *(__be16 *)(p + 16) = cpu_to_be16(0); // unused
1665 p += 18;
1666
1667 isdn_net_write_super(lp, skb);
1668}
1669
1670static void
1671isdn_net_ciscohdlck_slarp_in(isdn_net_local *lp, struct sk_buff *skb)
1672{
1673 unsigned char *p;
1674 int period;
1675 u32 code;
1676 u32 my_seq;
1677 u32 your_seq;
1678 __be32 local;
1679 __be32 *addr, *mask;
1680
1681 if (skb->len < 14)
1682 return;
1683
1684 p = skb->data;
1685 code = be32_to_cpup((__be32 *)p);
1686 p += 4;
1687
1688 switch (code) {
1689 case CISCO_SLARP_REQUEST:
1690 lp->cisco_yourseq = 0;
1691 isdn_net_ciscohdlck_slarp_send_reply(lp);
1692 break;
1693 case CISCO_SLARP_REPLY:
1694 addr = (__be32 *)p;
1695 mask = (__be32 *)(p + 4);
1696 if (*mask != cpu_to_be32(0xfffffffc))
1697 goto slarp_reply_out;
1698 if ((*addr & cpu_to_be32(3)) == cpu_to_be32(0) ||
1699 (*addr & cpu_to_be32(3)) == cpu_to_be32(3))
1700 goto slarp_reply_out;
1701 local = *addr ^ cpu_to_be32(3);
1702 printk(KERN_INFO "%s: got slarp reply: remote ip: %pI4, local ip: %pI4 mask: %pI4\n",
1703 lp->netdev->dev->name, addr, &local, mask);
1704 break;
1705 slarp_reply_out:
1706 printk(KERN_INFO "%s: got invalid slarp reply (%pI4/%pI4) - ignored\n",
1707 lp->netdev->dev->name, addr, mask);
1708 break;
1709 case CISCO_SLARP_KEEPALIVE:
1710 period = (int)((jiffies - lp->cisco_last_slarp_in
1711 + HZ / 2 - 1) / HZ);
1712 if (lp->cisco_debserint &&
1713 (period != lp->cisco_keepalive_period) &&
1714 lp->cisco_last_slarp_in) {
1715 printk(KERN_DEBUG "%s: Keepalive period mismatch - "
1716 "is %d but should be %d.\n",
1717 lp->netdev->dev->name, period,
1718 lp->cisco_keepalive_period);
1719 }
1720 lp->cisco_last_slarp_in = jiffies;
1721 my_seq = be32_to_cpup((__be32 *)(p + 0));
1722 your_seq = be32_to_cpup((__be32 *)(p + 4));
1723 p += 10;
1724 lp->cisco_yourseq = my_seq;
1725 lp->cisco_mineseen = your_seq;
1726 break;
1727 }
1728}
1729
1730static void
1731isdn_net_ciscohdlck_receive(isdn_net_local *lp, struct sk_buff *skb)
1732{
1733 unsigned char *p;
1734 u8 addr;
1735 u8 ctrl;
1736 u16 type;
1737
1738 if (skb->len < 4)
1739 goto out_free;
1740
1741 p = skb->data;
1742 addr = *(u8 *)(p + 0);
1743 ctrl = *(u8 *)(p + 1);
1744 type = be16_to_cpup((__be16 *)(p + 2));
1745 p += 4;
1746 skb_pull(skb, 4);
1747
1748 if (addr != CISCO_ADDR_UNICAST && addr != CISCO_ADDR_BROADCAST) {
1749 printk(KERN_WARNING "%s: Unknown Cisco addr 0x%02x\n",
1750 lp->netdev->dev->name, addr);
1751 goto out_free;
1752 }
1753 if (ctrl != CISCO_CTRL) {
1754 printk(KERN_WARNING "%s: Unknown Cisco ctrl 0x%02x\n",
1755 lp->netdev->dev->name, ctrl);
1756 goto out_free;
1757 }
1758
1759 switch (type) {
1760 case CISCO_TYPE_SLARP:
1761 isdn_net_ciscohdlck_slarp_in(lp, skb);
1762 goto out_free;
1763 case CISCO_TYPE_CDP:
1764 if (lp->cisco_debserint)
1765 printk(KERN_DEBUG "%s: Received CDP packet. use "
1766 "\"no cdp enable\" on cisco.\n",
1767 lp->netdev->dev->name);
1768 goto out_free;
1769 default:
1770 /* no special cisco protocol */
1771 skb->protocol = htons(type);
1772 netif_rx(skb);
1773 return;
1774 }
1775
1776out_free:
1777 kfree_skb(skb);
1778}
1779
1780/*
1781 * Got a packet from ISDN-Channel.
1782 */
1783static void
1784isdn_net_receive(struct net_device *ndev, struct sk_buff *skb)
1785{
1786 isdn_net_local *lp = netdev_priv(ndev);
1787 isdn_net_local *olp = lp; /* original 'lp' */
1788#ifdef CONFIG_ISDN_X25
1789 struct concap_proto *cprot = lp->netdev->cprot;
1790#endif
1791 lp->transcount += skb->len;
1792
1793 lp->stats.rx_packets++;
1794 lp->stats.rx_bytes += skb->len;
1795 if (lp->master) {
1796 /* Bundling: If device is a slave-device, deliver to master, also
1797 * handle master's statistics and hangup-timeout
1798 */
1799 ndev = lp->master;
1800 lp = netdev_priv(ndev);
1801 lp->stats.rx_packets++;
1802 lp->stats.rx_bytes += skb->len;
1803 }
1804 skb->dev = ndev;
1805 skb->pkt_type = PACKET_HOST;
1806 skb_reset_mac_header(skb);
1807#ifdef ISDN_DEBUG_NET_DUMP
1808 isdn_dumppkt("R:", skb->data, skb->len, 40);
1809#endif
1810 switch (lp->p_encap) {
1811 case ISDN_NET_ENCAP_ETHER:
1812 /* Ethernet over ISDN */
1813 olp->huptimer = 0;
1814 lp->huptimer = 0;
1815 skb->protocol = isdn_net_type_trans(skb, ndev);
1816 break;
1817 case ISDN_NET_ENCAP_UIHDLC:
1818 /* HDLC with UI-frame (for ispa with -h1 option) */
1819 olp->huptimer = 0;
1820 lp->huptimer = 0;
1821 skb_pull(skb, 2);
1822 /* Fall through */
1823 case ISDN_NET_ENCAP_RAWIP:
1824 /* RAW-IP without MAC-Header */
1825 olp->huptimer = 0;
1826 lp->huptimer = 0;
1827 skb->protocol = htons(ETH_P_IP);
1828 break;
1829 case ISDN_NET_ENCAP_CISCOHDLCK:
1830 isdn_net_ciscohdlck_receive(lp, skb);
1831 return;
1832 case ISDN_NET_ENCAP_CISCOHDLC:
1833 /* CISCO-HDLC IP with type field and fake I-frame-header */
1834 skb_pull(skb, 2);
1835 /* Fall through */
1836 case ISDN_NET_ENCAP_IPTYP:
1837 /* IP with type field */
1838 olp->huptimer = 0;
1839 lp->huptimer = 0;
1840 skb->protocol = *(__be16 *)&(skb->data[0]);
1841 skb_pull(skb, 2);
1842 if (*(unsigned short *) skb->data == 0xFFFF)
1843 skb->protocol = htons(ETH_P_802_3);
1844 break;
1845#ifdef CONFIG_ISDN_PPP
1846 case ISDN_NET_ENCAP_SYNCPPP:
1847 /* huptimer is done in isdn_ppp_push_higher */
1848 isdn_ppp_receive(lp->netdev, olp, skb);
1849 return;
1850#endif
1851
1852 default:
1853#ifdef CONFIG_ISDN_X25
1854 /* try if there are generic sync_device receiver routines */
1855 if (cprot) if (cprot->pops)
1856 if (cprot->pops->data_ind) {
1857 cprot->pops->data_ind(cprot, skb);
1858 return;
1859 };
1860#endif /* CONFIG_ISDN_X25 */
1861 printk(KERN_WARNING "%s: unknown encapsulation, dropping\n",
1862 lp->netdev->dev->name);
1863 kfree_skb(skb);
1864 return;
1865 }
1866
1867 netif_rx(skb);
1868 return;
1869}
1870
1871/*
1872 * A packet arrived via ISDN. Search interface-chain for a corresponding
1873 * interface. If found, deliver packet to receiver-function and return 1,
1874 * else return 0.
1875 */
1876int
1877isdn_net_rcv_skb(int idx, struct sk_buff *skb)
1878{
1879 isdn_net_dev *p = dev->rx_netdev[idx];
1880
1881 if (p) {
1882 isdn_net_local *lp = p->local;
1883 if ((lp->flags & ISDN_NET_CONNECTED) &&
1884 (!lp->dialstate)) {
1885 isdn_net_receive(p->dev, skb);
1886 return 1;
1887 }
1888 }
1889 return 0;
1890}
1891
1892/*
1893 * build an header
1894 * depends on encaps that is being used.
1895 */
1896
1897static int isdn_net_header(struct sk_buff *skb, struct net_device *dev,
1898 unsigned short type,
1899 const void *daddr, const void *saddr, unsigned plen)
1900{
1901 isdn_net_local *lp = netdev_priv(dev);
1902 unsigned char *p;
1903 int len = 0;
1904
1905 switch (lp->p_encap) {
1906 case ISDN_NET_ENCAP_ETHER:
1907 len = eth_header(skb, dev, type, daddr, saddr, plen);
1908 break;
1909#ifdef CONFIG_ISDN_PPP
1910 case ISDN_NET_ENCAP_SYNCPPP:
1911 /* stick on a fake header to keep fragmentation code happy. */
1912 len = IPPP_MAX_HEADER;
1913 skb_push(skb, len);
1914 break;
1915#endif
1916 case ISDN_NET_ENCAP_RAWIP:
1917 printk(KERN_WARNING "isdn_net_header called with RAW_IP!\n");
1918 len = 0;
1919 break;
1920 case ISDN_NET_ENCAP_IPTYP:
1921 /* ethernet type field */
1922 *((__be16 *)skb_push(skb, 2)) = htons(type);
1923 len = 2;
1924 break;
1925 case ISDN_NET_ENCAP_UIHDLC:
1926 /* HDLC with UI-Frames (for ispa with -h1 option) */
1927 *((__be16 *)skb_push(skb, 2)) = htons(0x0103);
1928 len = 2;
1929 break;
1930 case ISDN_NET_ENCAP_CISCOHDLC:
1931 case ISDN_NET_ENCAP_CISCOHDLCK:
1932 p = skb_push(skb, 4);
1933 *(u8 *)(p + 0) = CISCO_ADDR_UNICAST;
1934 *(u8 *)(p + 1) = CISCO_CTRL;
1935 *(__be16 *)(p + 2) = cpu_to_be16(type);
1936 p += 4;
1937 len = 4;
1938 break;
1939#ifdef CONFIG_ISDN_X25
1940 default:
1941 /* try if there are generic concap protocol routines */
1942 if (lp->netdev->cprot) {
1943 printk(KERN_WARNING "isdn_net_header called with concap_proto!\n");
1944 len = 0;
1945 break;
1946 }
1947 break;
1948#endif /* CONFIG_ISDN_X25 */
1949 }
1950 return len;
1951}
1952
1953static int isdn_header_cache(const struct neighbour *neigh, struct hh_cache *hh,
1954 __be16 type)
1955{
1956 const struct net_device *dev = neigh->dev;
1957 isdn_net_local *lp = netdev_priv(dev);
1958
1959 if (lp->p_encap == ISDN_NET_ENCAP_ETHER)
1960 return eth_header_cache(neigh, hh, type);
1961 return -1;
1962}
1963
1964static void isdn_header_cache_update(struct hh_cache *hh,
1965 const struct net_device *dev,
1966 const unsigned char *haddr)
1967{
1968 isdn_net_local *lp = netdev_priv(dev);
1969 if (lp->p_encap == ISDN_NET_ENCAP_ETHER)
1970 eth_header_cache_update(hh, dev, haddr);
1971}
1972
1973static const struct header_ops isdn_header_ops = {
1974 .create = isdn_net_header,
1975 .cache = isdn_header_cache,
1976 .cache_update = isdn_header_cache_update,
1977};
1978
1979/*
1980 * Interface-setup. (just after registering a new interface)
1981 */
1982static int
1983isdn_net_init(struct net_device *ndev)
1984{
1985 ushort max_hlhdr_len = 0;
1986 int drvidx;
1987
1988 /*
1989 * up till binding we ask the protocol layer to reserve as much
1990 * as we might need for HL layer
1991 */
1992
1993 for (drvidx = 0; drvidx < ISDN_MAX_DRIVERS; drvidx++)
1994 if (dev->drv[drvidx])
1995 if (max_hlhdr_len < dev->drv[drvidx]->interface->hl_hdrlen)
1996 max_hlhdr_len = dev->drv[drvidx]->interface->hl_hdrlen;
1997
1998 ndev->hard_header_len = ETH_HLEN + max_hlhdr_len;
1999 return 0;
2000}
2001
2002static void
2003isdn_net_swapbind(int drvidx)
2004{
2005 isdn_net_dev *p;
2006
2007#ifdef ISDN_DEBUG_NET_ICALL
2008 printk(KERN_DEBUG "n_fi: swapping ch of %d\n", drvidx);
2009#endif
2010 p = dev->netdev;
2011 while (p) {
2012 if (p->local->pre_device == drvidx)
2013 switch (p->local->pre_channel) {
2014 case 0:
2015 p->local->pre_channel = 1;
2016 break;
2017 case 1:
2018 p->local->pre_channel = 0;
2019 break;
2020 }
2021 p = (isdn_net_dev *) p->next;
2022 }
2023}
2024
2025static void
2026isdn_net_swap_usage(int i1, int i2)
2027{
2028 int u1 = dev->usage[i1] & ISDN_USAGE_EXCLUSIVE;
2029 int u2 = dev->usage[i2] & ISDN_USAGE_EXCLUSIVE;
2030
2031#ifdef ISDN_DEBUG_NET_ICALL
2032 printk(KERN_DEBUG "n_fi: usage of %d and %d\n", i1, i2);
2033#endif
2034 dev->usage[i1] &= ~ISDN_USAGE_EXCLUSIVE;
2035 dev->usage[i1] |= u2;
2036 dev->usage[i2] &= ~ISDN_USAGE_EXCLUSIVE;
2037 dev->usage[i2] |= u1;
2038 isdn_info_update();
2039}
2040
2041/*
2042 * An incoming call-request has arrived.
2043 * Search the interface-chain for an appropriate interface.
2044 * If found, connect the interface to the ISDN-channel and initiate
2045 * D- and B-Channel-setup. If secure-flag is set, accept only
2046 * configured phone-numbers. If callback-flag is set, initiate
2047 * callback-dialing.
2048 *
2049 * Return-Value: 0 = No appropriate interface for this call.
2050 * 1 = Call accepted
2051 * 2 = Reject call, wait cbdelay, then call back
2052 * 3 = Reject call
2053 * 4 = Wait cbdelay, then call back
2054 * 5 = No appropriate interface for this call,
2055 * would eventually match if CID was longer.
2056 */
2057
2058int
2059isdn_net_find_icall(int di, int ch, int idx, setup_parm *setup)
2060{
2061 char *eaz;
2062 int si1;
2063 int si2;
2064 int ematch;
2065 int wret;
2066 int swapped;
2067 int sidx = 0;
2068 u_long flags;
2069 isdn_net_dev *p;
2070 isdn_net_phone *n;
2071 char nr[ISDN_MSNLEN];
2072 char *my_eaz;
2073
2074 /* Search name in netdev-chain */
2075 if (!setup->phone[0]) {
2076 nr[0] = '0';
2077 nr[1] = '\0';
2078 printk(KERN_INFO "isdn_net: Incoming call without OAD, assuming '0'\n");
2079 } else
2080 strlcpy(nr, setup->phone, ISDN_MSNLEN);
2081 si1 = (int) setup->si1;
2082 si2 = (int) setup->si2;
2083 if (!setup->eazmsn[0]) {
2084 printk(KERN_WARNING "isdn_net: Incoming call without CPN, assuming '0'\n");
2085 eaz = "0";
2086 } else
2087 eaz = setup->eazmsn;
2088 if (dev->net_verbose > 1)
2089 printk(KERN_INFO "isdn_net: call from %s,%d,%d -> %s\n", nr, si1, si2, eaz);
2090 /* Accept DATA and VOICE calls at this stage
2091 * local eaz is checked later for allowed call types
2092 */
2093 if ((si1 != 7) && (si1 != 1)) {
2094 if (dev->net_verbose > 1)
2095 printk(KERN_INFO "isdn_net: Service-Indicator not 1 or 7, ignored\n");
2096 return 0;
2097 }
2098 n = (isdn_net_phone *) 0;
2099 p = dev->netdev;
2100 ematch = wret = swapped = 0;
2101#ifdef ISDN_DEBUG_NET_ICALL
2102 printk(KERN_DEBUG "n_fi: di=%d ch=%d idx=%d usg=%d\n", di, ch, idx,
2103 dev->usage[idx]);
2104#endif
2105 while (p) {
2106 int matchret;
2107 isdn_net_local *lp = p->local;
2108
2109 /* If last check has triggered as binding-swap, revert it */
2110 switch (swapped) {
2111 case 2:
2112 isdn_net_swap_usage(idx, sidx);
2113 /* fall through */
2114 case 1:
2115 isdn_net_swapbind(di);
2116 break;
2117 }
2118 swapped = 0;
2119 /* check acceptable call types for DOV */
2120 my_eaz = isdn_map_eaz2msn(lp->msn, di);
2121 if (si1 == 1) { /* it's a DOV call, check if we allow it */
2122 if (*my_eaz == 'v' || *my_eaz == 'V' ||
2123 *my_eaz == 'b' || *my_eaz == 'B')
2124 my_eaz++; /* skip to allow a match */
2125 else
2126 my_eaz = NULL; /* force non match */
2127 } else { /* it's a DATA call, check if we allow it */
2128 if (*my_eaz == 'b' || *my_eaz == 'B')
2129 my_eaz++; /* skip to allow a match */
2130 }
2131 if (my_eaz)
2132 matchret = isdn_msncmp(eaz, my_eaz);
2133 else
2134 matchret = 1;
2135 if (!matchret)
2136 ematch = 1;
2137
2138 /* Remember if more numbers eventually can match */
2139 if (matchret > wret)
2140 wret = matchret;
2141#ifdef ISDN_DEBUG_NET_ICALL
2142 printk(KERN_DEBUG "n_fi: if='%s', l.msn=%s, l.flags=%d, l.dstate=%d\n",
2143 p->dev->name, lp->msn, lp->flags, lp->dialstate);
2144#endif
2145 if ((!matchret) && /* EAZ is matching */
2146 (((!(lp->flags & ISDN_NET_CONNECTED)) && /* but not connected */
2147 (USG_NONE(dev->usage[idx]))) || /* and ch. unused or */
2148 ((((lp->dialstate == 4) || (lp->dialstate == 12)) && /* if dialing */
2149 (!(lp->flags & ISDN_NET_CALLBACK))) /* but no callback */
2150 )))
2151 {
2152#ifdef ISDN_DEBUG_NET_ICALL
2153 printk(KERN_DEBUG "n_fi: match1, pdev=%d pch=%d\n",
2154 lp->pre_device, lp->pre_channel);
2155#endif
2156 if (dev->usage[idx] & ISDN_USAGE_EXCLUSIVE) {
2157 if ((lp->pre_channel != ch) ||
2158 (lp->pre_device != di)) {
2159 /* Here we got a problem:
2160 * If using an ICN-Card, an incoming call is always signaled on
2161 * on the first channel of the card, if both channels are
2162 * down. However this channel may be bound exclusive. If the
2163 * second channel is free, this call should be accepted.
2164 * The solution is horribly but it runs, so what:
2165 * We exchange the exclusive bindings of the two channels, the
2166 * corresponding variables in the interface-structs.
2167 */
2168 if (ch == 0) {
2169 sidx = isdn_dc2minor(di, 1);
2170#ifdef ISDN_DEBUG_NET_ICALL
2171 printk(KERN_DEBUG "n_fi: ch is 0\n");
2172#endif
2173 if (USG_NONE(dev->usage[sidx])) {
2174 /* Second Channel is free, now see if it is bound
2175 * exclusive too. */
2176 if (dev->usage[sidx] & ISDN_USAGE_EXCLUSIVE) {
2177#ifdef ISDN_DEBUG_NET_ICALL
2178 printk(KERN_DEBUG "n_fi: 2nd channel is down and bound\n");
2179#endif
2180 /* Yes, swap bindings only, if the original
2181 * binding is bound to channel 1 of this driver */
2182 if ((lp->pre_device == di) &&
2183 (lp->pre_channel == 1)) {
2184 isdn_net_swapbind(di);
2185 swapped = 1;
2186 } else {
2187 /* ... else iterate next device */
2188 p = (isdn_net_dev *) p->next;
2189 continue;
2190 }
2191 } else {
2192#ifdef ISDN_DEBUG_NET_ICALL
2193 printk(KERN_DEBUG "n_fi: 2nd channel is down and unbound\n");
2194#endif
2195 /* No, swap always and swap excl-usage also */
2196 isdn_net_swap_usage(idx, sidx);
2197 isdn_net_swapbind(di);
2198 swapped = 2;
2199 }
2200 /* Now check for exclusive binding again */
2201#ifdef ISDN_DEBUG_NET_ICALL
2202 printk(KERN_DEBUG "n_fi: final check\n");
2203#endif
2204 if ((dev->usage[idx] & ISDN_USAGE_EXCLUSIVE) &&
2205 ((lp->pre_channel != ch) ||
2206 (lp->pre_device != di))) {
2207#ifdef ISDN_DEBUG_NET_ICALL
2208 printk(KERN_DEBUG "n_fi: final check failed\n");
2209#endif
2210 p = (isdn_net_dev *) p->next;
2211 continue;
2212 }
2213 }
2214 } else {
2215 /* We are already on the second channel, so nothing to do */
2216#ifdef ISDN_DEBUG_NET_ICALL
2217 printk(KERN_DEBUG "n_fi: already on 2nd channel\n");
2218#endif
2219 }
2220 }
2221 }
2222#ifdef ISDN_DEBUG_NET_ICALL
2223 printk(KERN_DEBUG "n_fi: match2\n");
2224#endif
2225 n = lp->phone[0];
2226 if (lp->flags & ISDN_NET_SECURE) {
2227 while (n) {
2228 if (!isdn_msncmp(nr, n->num))
2229 break;
2230 n = (isdn_net_phone *) n->next;
2231 }
2232 }
2233 if (n || (!(lp->flags & ISDN_NET_SECURE))) {
2234#ifdef ISDN_DEBUG_NET_ICALL
2235 printk(KERN_DEBUG "n_fi: match3\n");
2236#endif
2237 /* matching interface found */
2238
2239 /*
2240 * Is the state STOPPED?
2241 * If so, no dialin is allowed,
2242 * so reject actively.
2243 * */
2244 if (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF) {
2245 printk(KERN_INFO "incoming call, interface %s `stopped' -> rejected\n",
2246 p->dev->name);
2247 return 3;
2248 }
2249 /*
2250 * Is the interface up?
2251 * If not, reject the call actively.
2252 */
2253 if (!isdn_net_device_started(p)) {
2254 printk(KERN_INFO "%s: incoming call, interface down -> rejected\n",
2255 p->dev->name);
2256 return 3;
2257 }
2258 /* Interface is up, now see if it's a slave. If so, see if
2259 * it's master and parent slave is online. If not, reject the call.
2260 */
2261 if (lp->master) {
2262 isdn_net_local *mlp = ISDN_MASTER_PRIV(lp);
2263 printk(KERN_DEBUG "ICALLslv: %s\n", p->dev->name);
2264 printk(KERN_DEBUG "master=%s\n", lp->master->name);
2265 if (mlp->flags & ISDN_NET_CONNECTED) {
2266 printk(KERN_DEBUG "master online\n");
2267 /* Master is online, find parent-slave (master if first slave) */
2268 while (mlp->slave) {
2269 if (ISDN_SLAVE_PRIV(mlp) == lp)
2270 break;
2271 mlp = ISDN_SLAVE_PRIV(mlp);
2272 }
2273 } else
2274 printk(KERN_DEBUG "master offline\n");
2275 /* Found parent, if it's offline iterate next device */
2276 printk(KERN_DEBUG "mlpf: %d\n", mlp->flags & ISDN_NET_CONNECTED);
2277 if (!(mlp->flags & ISDN_NET_CONNECTED)) {
2278 p = (isdn_net_dev *) p->next;
2279 continue;
2280 }
2281 }
2282 if (lp->flags & ISDN_NET_CALLBACK) {
2283 int chi;
2284 /*
2285 * Is the state MANUAL?
2286 * If so, no callback can be made,
2287 * so reject actively.
2288 * */
2289 if (ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_OFF) {
2290 printk(KERN_INFO "incoming call for callback, interface %s `off' -> rejected\n",
2291 p->dev->name);
2292 return 3;
2293 }
2294 printk(KERN_DEBUG "%s: call from %s -> %s, start callback\n",
2295 p->dev->name, nr, eaz);
2296 if (lp->phone[1]) {
2297 /* Grab a free ISDN-Channel */
2298 spin_lock_irqsave(&dev->lock, flags);
2299 if ((chi =
2300 isdn_get_free_channel(
2301 ISDN_USAGE_NET,
2302 lp->l2_proto,
2303 lp->l3_proto,
2304 lp->pre_device,
2305 lp->pre_channel,
2306 lp->msn)
2307 ) < 0) {
2308
2309 printk(KERN_WARNING "isdn_net_find_icall: No channel for %s\n",
2310 p->dev->name);
2311 spin_unlock_irqrestore(&dev->lock, flags);
2312 return 0;
2313 }
2314 /* Setup dialstate. */
2315 lp->dtimer = 0;
2316 lp->dialstate = 11;
2317 /* Connect interface with channel */
2318 isdn_net_bind_channel(lp, chi);
2319#ifdef CONFIG_ISDN_PPP
2320 if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
2321 if (isdn_ppp_bind(lp) < 0) {
2322 spin_unlock_irqrestore(&dev->lock, flags);
2323 isdn_net_unbind_channel(lp);
2324 return 0;
2325 }
2326#endif
2327 spin_unlock_irqrestore(&dev->lock, flags);
2328 /* Initiate dialing by returning 2 or 4 */
2329 return (lp->flags & ISDN_NET_CBHUP) ? 2 : 4;
2330 } else
2331 printk(KERN_WARNING "isdn_net: %s: No phone number\n",
2332 p->dev->name);
2333 return 0;
2334 } else {
2335 printk(KERN_DEBUG "%s: call from %s -> %s accepted\n",
2336 p->dev->name, nr, eaz);
2337 /* if this interface is dialing, it does it probably on a different
2338 device, so free this device */
2339 if ((lp->dialstate == 4) || (lp->dialstate == 12)) {
2340#ifdef CONFIG_ISDN_PPP
2341 if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
2342 isdn_ppp_free(lp);
2343#endif
2344 isdn_net_lp_disconnected(lp);
2345 isdn_free_channel(lp->isdn_device, lp->isdn_channel,
2346 ISDN_USAGE_NET);
2347 }
2348 spin_lock_irqsave(&dev->lock, flags);
2349 dev->usage[idx] &= ISDN_USAGE_EXCLUSIVE;
2350 dev->usage[idx] |= ISDN_USAGE_NET;
2351 strcpy(dev->num[idx], nr);
2352 isdn_info_update();
2353 dev->st_netdev[idx] = lp->netdev;
2354 lp->isdn_device = di;
2355 lp->isdn_channel = ch;
2356 lp->ppp_slot = -1;
2357 lp->flags |= ISDN_NET_CONNECTED;
2358 lp->dialstate = 7;
2359 lp->dtimer = 0;
2360 lp->outgoing = 0;
2361 lp->huptimer = 0;
2362 lp->hupflags |= ISDN_WAITCHARGE;
2363 lp->hupflags &= ~ISDN_HAVECHARGE;
2364#ifdef CONFIG_ISDN_PPP
2365 if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP) {
2366 if (isdn_ppp_bind(lp) < 0) {
2367 isdn_net_unbind_channel(lp);
2368 spin_unlock_irqrestore(&dev->lock, flags);
2369 return 0;
2370 }
2371 }
2372#endif
2373 spin_unlock_irqrestore(&dev->lock, flags);
2374 return 1;
2375 }
2376 }
2377 }
2378 p = (isdn_net_dev *) p->next;
2379 }
2380 /* If none of configured EAZ/MSN matched and not verbose, be silent */
2381 if (!ematch || dev->net_verbose)
2382 printk(KERN_INFO "isdn_net: call from %s -> %d %s ignored\n", nr, di, eaz);
2383 return (wret == 2) ? 5 : 0;
2384}
2385
2386/*
2387 * Search list of net-interfaces for an interface with given name.
2388 */
2389isdn_net_dev *
2390isdn_net_findif(char *name)
2391{
2392 isdn_net_dev *p = dev->netdev;
2393
2394 while (p) {
2395 if (!strcmp(p->dev->name, name))
2396 return p;
2397 p = (isdn_net_dev *) p->next;
2398 }
2399 return (isdn_net_dev *) NULL;
2400}
2401
2402/*
2403 * Force a net-interface to dial out.
2404 * This is called from the userlevel-routine below or
2405 * from isdn_net_start_xmit().
2406 */
2407static int
2408isdn_net_force_dial_lp(isdn_net_local *lp)
2409{
2410 if ((!(lp->flags & ISDN_NET_CONNECTED)) && !lp->dialstate) {
2411 int chi;
2412 if (lp->phone[1]) {
2413 ulong flags;
2414
2415 /* Grab a free ISDN-Channel */
2416 spin_lock_irqsave(&dev->lock, flags);
2417 if ((chi = isdn_get_free_channel(
2418 ISDN_USAGE_NET,
2419 lp->l2_proto,
2420 lp->l3_proto,
2421 lp->pre_device,
2422 lp->pre_channel,
2423 lp->msn)) < 0) {
2424 printk(KERN_WARNING "isdn_net_force_dial: No channel for %s\n",
2425 lp->netdev->dev->name);
2426 spin_unlock_irqrestore(&dev->lock, flags);
2427 return -EAGAIN;
2428 }
2429 lp->dialstate = 1;
2430 /* Connect interface with channel */
2431 isdn_net_bind_channel(lp, chi);
2432#ifdef CONFIG_ISDN_PPP
2433 if (lp->p_encap == ISDN_NET_ENCAP_SYNCPPP)
2434 if (isdn_ppp_bind(lp) < 0) {
2435 isdn_net_unbind_channel(lp);
2436 spin_unlock_irqrestore(&dev->lock, flags);
2437 return -EAGAIN;
2438 }
2439#endif
2440 /* Initiate dialing */
2441 spin_unlock_irqrestore(&dev->lock, flags);
2442 isdn_net_dial();
2443 return 0;
2444 } else
2445 return -EINVAL;
2446 } else
2447 return -EBUSY;
2448}
2449
2450/*
2451 * This is called from certain upper protocol layers (multilink ppp
2452 * and x25iface encapsulation module) that want to initiate dialing
2453 * themselves.
2454 */
2455int
2456isdn_net_dial_req(isdn_net_local *lp)
2457{
2458 /* is there a better error code? */
2459 if (!(ISDN_NET_DIALMODE(*lp) == ISDN_NET_DM_AUTO)) return -EBUSY;
2460
2461 return isdn_net_force_dial_lp(lp);
2462}
2463
2464/*
2465 * Force a net-interface to dial out.
2466 * This is always called from within userspace (ISDN_IOCTL_NET_DIAL).
2467 */
2468int
2469isdn_net_force_dial(char *name)
2470{
2471 isdn_net_dev *p = isdn_net_findif(name);
2472
2473 if (!p)
2474 return -ENODEV;
2475 return (isdn_net_force_dial_lp(p->local));
2476}
2477
2478/* The ISDN-specific entries in the device structure. */
2479static const struct net_device_ops isdn_netdev_ops = {
2480 .ndo_init = isdn_net_init,
2481 .ndo_open = isdn_net_open,
2482 .ndo_stop = isdn_net_close,
2483 .ndo_do_ioctl = isdn_net_ioctl,
2484
2485 .ndo_start_xmit = isdn_net_start_xmit,
2486 .ndo_get_stats = isdn_net_get_stats,
2487 .ndo_tx_timeout = isdn_net_tx_timeout,
2488};
2489
2490/*
2491 * Helper for alloc_netdev()
2492 */
2493static void _isdn_setup(struct net_device *dev)
2494{
2495 isdn_net_local *lp = netdev_priv(dev);
2496
2497 ether_setup(dev);
2498
2499 /* Setup the generic properties */
2500 dev->flags = IFF_NOARP | IFF_POINTOPOINT;
2501
2502 /* isdn prepends a header in the tx path, can't share skbs */
2503 dev->priv_flags &= ~IFF_TX_SKB_SHARING;
2504 dev->header_ops = NULL;
2505 dev->netdev_ops = &isdn_netdev_ops;
2506
2507 /* for clients with MPPP maybe higher values better */
2508 dev->tx_queue_len = 30;
2509
2510 lp->p_encap = ISDN_NET_ENCAP_RAWIP;
2511 lp->magic = ISDN_NET_MAGIC;
2512 lp->last = lp;
2513 lp->next = lp;
2514 lp->isdn_device = -1;
2515 lp->isdn_channel = -1;
2516 lp->pre_device = -1;
2517 lp->pre_channel = -1;
2518 lp->exclusive = -1;
2519 lp->ppp_slot = -1;
2520 lp->pppbind = -1;
2521 skb_queue_head_init(&lp->super_tx_queue);
2522 lp->l2_proto = ISDN_PROTO_L2_X75I;
2523 lp->l3_proto = ISDN_PROTO_L3_TRANS;
2524 lp->triggercps = 6000;
2525 lp->slavedelay = 10 * HZ;
2526 lp->hupflags = ISDN_INHUP; /* Do hangup even on incoming calls */
2527 lp->onhtime = 10; /* Default hangup-time for saving costs */
2528 lp->dialmax = 1;
2529 /* Hangup before Callback, manual dial */
2530 lp->flags = ISDN_NET_CBHUP | ISDN_NET_DM_MANUAL;
2531 lp->cbdelay = 25; /* Wait 5 secs before Callback */
2532 lp->dialtimeout = -1; /* Infinite Dial-Timeout */
2533 lp->dialwait = 5 * HZ; /* Wait 5 sec. after failed dial */
2534 lp->dialstarted = 0; /* Jiffies of last dial-start */
2535 lp->dialwait_timer = 0; /* Jiffies of earliest next dial-start */
2536}
2537
2538/*
2539 * Allocate a new network-interface and initialize its data structures.
2540 */
2541char *
2542isdn_net_new(char *name, struct net_device *master)
2543{
2544 isdn_net_dev *netdev;
2545
2546 /* Avoid creating an existing interface */
2547 if (isdn_net_findif(name)) {
2548 printk(KERN_WARNING "isdn_net: interface %s already exists\n", name);
2549 return NULL;
2550 }
2551 if (name == NULL)
2552 return NULL;
2553 if (!(netdev = kzalloc(sizeof(isdn_net_dev), GFP_KERNEL))) {
2554 printk(KERN_WARNING "isdn_net: Could not allocate net-device\n");
2555 return NULL;
2556 }
2557 netdev->dev = alloc_netdev(sizeof(isdn_net_local), name,
2558 NET_NAME_UNKNOWN, _isdn_setup);
2559 if (!netdev->dev) {
2560 printk(KERN_WARNING "isdn_net: Could not allocate network device\n");
2561 kfree(netdev);
2562 return NULL;
2563 }
2564 netdev->local = netdev_priv(netdev->dev);
2565
2566 if (master) {
2567 /* Device shall be a slave */
2568 struct net_device *p = MASTER_TO_SLAVE(master);
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 = MASTER_TO_SLAVE(p);
2576 }
2577 MASTER_TO_SLAVE(q) = netdev->dev;
2578 } else {
2579 /* Device shall be a master */
2580 /*
2581 * Watchdog timer (currently) for master only.
2582 */
2583 netdev->dev->watchdog_timeo = ISDN_NET_TX_TIMEOUT;
2584 if (register_netdev(netdev->dev) != 0) {
2585 printk(KERN_WARNING "isdn_net: Could not register net-device\n");
2586 free_netdev(netdev->dev);
2587 kfree(netdev);
2588 return NULL;
2589 }
2590 }
2591 netdev->queue = netdev->local;
2592 spin_lock_init(&netdev->queue_lock);
2593
2594 netdev->local->netdev = netdev;
2595
2596 INIT_WORK(&netdev->local->tqueue, isdn_net_softint);
2597 spin_lock_init(&netdev->local->xmit_lock);
2598
2599 /* Put into to netdev-chain */
2600 netdev->next = (void *) dev->netdev;
2601 dev->netdev = netdev;
2602 return netdev->dev->name;
2603}
2604
2605char *
2606isdn_net_newslave(char *parm)
2607{
2608 char *p = strchr(parm, ',');
2609 isdn_net_dev *n;
2610 char newname[10];
2611
2612 if (p) {
2613 /* Slave-Name MUST not be empty or overflow 'newname' */
2614 if (strscpy(newname, p + 1, sizeof(newname)) <= 0)
2615 return NULL;
2616 *p = 0;
2617 /* Master must already exist */
2618 if (!(n = isdn_net_findif(parm)))
2619 return NULL;
2620 /* Master must be a real interface, not a slave */
2621 if (n->local->master)
2622 return NULL;
2623 /* Master must not be started yet */
2624 if (isdn_net_device_started(n))
2625 return NULL;
2626 return (isdn_net_new(newname, n->dev));
2627 }
2628 return NULL;
2629}
2630
2631/*
2632 * Set interface-parameters.
2633 * Always set all parameters, so the user-level application is responsible
2634 * for not overwriting existing setups. It has to get the current
2635 * setup first, if only selected parameters are to be changed.
2636 */
2637int
2638isdn_net_setcfg(isdn_net_ioctl_cfg *cfg)
2639{
2640 isdn_net_dev *p = isdn_net_findif(cfg->name);
2641 ulong features;
2642 int i;
2643 int drvidx;
2644 int chidx;
2645 char drvid[25];
2646
2647 if (p) {
2648 isdn_net_local *lp = p->local;
2649
2650 /* See if any registered driver supports the features we want */
2651 features = ((1 << cfg->l2_proto) << ISDN_FEATURE_L2_SHIFT) |
2652 ((1 << cfg->l3_proto) << ISDN_FEATURE_L3_SHIFT);
2653 for (i = 0; i < ISDN_MAX_DRIVERS; i++)
2654 if (dev->drv[i])
2655 if ((dev->drv[i]->interface->features & features) == features)
2656 break;
2657 if (i == ISDN_MAX_DRIVERS) {
2658 printk(KERN_WARNING "isdn_net: No driver with selected features\n");
2659 return -ENODEV;
2660 }
2661 if (lp->p_encap != cfg->p_encap) {
2662#ifdef CONFIG_ISDN_X25
2663 struct concap_proto *cprot = p->cprot;
2664#endif
2665 if (isdn_net_device_started(p)) {
2666 printk(KERN_WARNING "%s: cannot change encap when if is up\n",
2667 p->dev->name);
2668 return -EBUSY;
2669 }
2670#ifdef CONFIG_ISDN_X25
2671 if (cprot && cprot->pops)
2672 cprot->pops->proto_del(cprot);
2673 p->cprot = NULL;
2674 lp->dops = NULL;
2675 /* ... , prepare for configuration of new one ... */
2676 switch (cfg->p_encap) {
2677 case ISDN_NET_ENCAP_X25IFACE:
2678 lp->dops = &isdn_concap_reliable_dl_dops;
2679 }
2680 /* ... and allocate new one ... */
2681 p->cprot = isdn_concap_new(cfg->p_encap);
2682 /* p -> cprot == NULL now if p_encap is not supported
2683 by means of the concap_proto mechanism */
2684 /* the protocol is not configured yet; this will
2685 happen later when isdn_net_reset() is called */
2686#endif
2687 }
2688 switch (cfg->p_encap) {
2689 case ISDN_NET_ENCAP_SYNCPPP:
2690#ifndef CONFIG_ISDN_PPP
2691 printk(KERN_WARNING "%s: SyncPPP support not configured\n",
2692 p->dev->name);
2693 return -EINVAL;
2694#else
2695 p->dev->type = ARPHRD_PPP; /* change ARP type */
2696 p->dev->addr_len = 0;
2697#endif
2698 break;
2699 case ISDN_NET_ENCAP_X25IFACE:
2700#ifndef CONFIG_ISDN_X25
2701 printk(KERN_WARNING "%s: isdn-x25 support not configured\n",
2702 p->dev->name);
2703 return -EINVAL;
2704#else
2705 p->dev->type = ARPHRD_X25; /* change ARP type */
2706 p->dev->addr_len = 0;
2707#endif
2708 break;
2709 case ISDN_NET_ENCAP_CISCOHDLCK:
2710 break;
2711 default:
2712 if (cfg->p_encap >= 0 &&
2713 cfg->p_encap <= ISDN_NET_ENCAP_MAX_ENCAP)
2714 break;
2715 printk(KERN_WARNING
2716 "%s: encapsulation protocol %d not supported\n",
2717 p->dev->name, cfg->p_encap);
2718 return -EINVAL;
2719 }
2720 if (strlen(cfg->drvid)) {
2721 /* A bind has been requested ... */
2722 char *c,
2723 *e;
2724
2725 if (strnlen(cfg->drvid, sizeof(cfg->drvid)) ==
2726 sizeof(cfg->drvid))
2727 return -EINVAL;
2728 drvidx = -1;
2729 chidx = -1;
2730 strcpy(drvid, cfg->drvid);
2731 if ((c = strchr(drvid, ','))) {
2732 /* The channel-number is appended to the driver-Id with a comma */
2733 chidx = (int) simple_strtoul(c + 1, &e, 10);
2734 if (e == c)
2735 chidx = -1;
2736 *c = '\0';
2737 }
2738 for (i = 0; i < ISDN_MAX_DRIVERS; i++)
2739 /* Lookup driver-Id in array */
2740 if (!(strcmp(dev->drvid[i], drvid))) {
2741 drvidx = i;
2742 break;
2743 }
2744 if ((drvidx == -1) || (chidx == -1))
2745 /* Either driver-Id or channel-number invalid */
2746 return -ENODEV;
2747 } else {
2748 /* Parameters are valid, so get them */
2749 drvidx = lp->pre_device;
2750 chidx = lp->pre_channel;
2751 }
2752 if (cfg->exclusive > 0) {
2753 unsigned long flags;
2754
2755 /* If binding is exclusive, try to grab the channel */
2756 spin_lock_irqsave(&dev->lock, flags);
2757 if ((i = isdn_get_free_channel(ISDN_USAGE_NET,
2758 lp->l2_proto, lp->l3_proto, drvidx,
2759 chidx, lp->msn)) < 0) {
2760 /* Grab failed, because desired channel is in use */
2761 lp->exclusive = -1;
2762 spin_unlock_irqrestore(&dev->lock, flags);
2763 return -EBUSY;
2764 }
2765 /* All went ok, so update isdninfo */
2766 dev->usage[i] = ISDN_USAGE_EXCLUSIVE;
2767 isdn_info_update();
2768 spin_unlock_irqrestore(&dev->lock, flags);
2769 lp->exclusive = i;
2770 } else {
2771 /* Non-exclusive binding or unbind. */
2772 lp->exclusive = -1;
2773 if ((lp->pre_device != -1) && (cfg->exclusive == -1)) {
2774 isdn_unexclusive_channel(lp->pre_device, lp->pre_channel);
2775 isdn_free_channel(lp->pre_device, lp->pre_channel, ISDN_USAGE_NET);
2776 drvidx = -1;
2777 chidx = -1;
2778 }
2779 }
2780 strlcpy(lp->msn, cfg->eaz, sizeof(lp->msn));
2781 lp->pre_device = drvidx;
2782 lp->pre_channel = chidx;
2783 lp->onhtime = cfg->onhtime;
2784 lp->charge = cfg->charge;
2785 lp->l2_proto = cfg->l2_proto;
2786 lp->l3_proto = cfg->l3_proto;
2787 lp->cbdelay = cfg->cbdelay;
2788 lp->dialmax = cfg->dialmax;
2789 lp->triggercps = cfg->triggercps;
2790 lp->slavedelay = cfg->slavedelay * HZ;
2791 lp->pppbind = cfg->pppbind;
2792 lp->dialtimeout = cfg->dialtimeout >= 0 ? cfg->dialtimeout * HZ : -1;
2793 lp->dialwait = cfg->dialwait * HZ;
2794 if (cfg->secure)
2795 lp->flags |= ISDN_NET_SECURE;
2796 else
2797 lp->flags &= ~ISDN_NET_SECURE;
2798 if (cfg->cbhup)
2799 lp->flags |= ISDN_NET_CBHUP;
2800 else
2801 lp->flags &= ~ISDN_NET_CBHUP;
2802 switch (cfg->callback) {
2803 case 0:
2804 lp->flags &= ~(ISDN_NET_CALLBACK | ISDN_NET_CBOUT);
2805 break;
2806 case 1:
2807 lp->flags |= ISDN_NET_CALLBACK;
2808 lp->flags &= ~ISDN_NET_CBOUT;
2809 break;
2810 case 2:
2811 lp->flags |= ISDN_NET_CBOUT;
2812 lp->flags &= ~ISDN_NET_CALLBACK;
2813 break;
2814 }
2815 lp->flags &= ~ISDN_NET_DIALMODE_MASK; /* first all bits off */
2816 if (cfg->dialmode && !(cfg->dialmode & ISDN_NET_DIALMODE_MASK)) {
2817 /* old isdnctrl version, where only 0 or 1 is given */
2818 printk(KERN_WARNING
2819 "Old isdnctrl version detected! Please update.\n");
2820 lp->flags |= ISDN_NET_DM_OFF; /* turn on `off' bit */
2821 }
2822 else {
2823 lp->flags |= cfg->dialmode; /* turn on selected bits */
2824 }
2825 if (cfg->chargehup)
2826 lp->hupflags |= ISDN_CHARGEHUP;
2827 else
2828 lp->hupflags &= ~ISDN_CHARGEHUP;
2829 if (cfg->ihup)
2830 lp->hupflags |= ISDN_INHUP;
2831 else
2832 lp->hupflags &= ~ISDN_INHUP;
2833 if (cfg->chargeint > 10) {
2834 lp->hupflags |= ISDN_CHARGEHUP | ISDN_HAVECHARGE | ISDN_MANCHARGE;
2835 lp->chargeint = cfg->chargeint * HZ;
2836 }
2837 if (cfg->p_encap != lp->p_encap) {
2838 if (cfg->p_encap == ISDN_NET_ENCAP_RAWIP) {
2839 p->dev->header_ops = NULL;
2840 p->dev->flags = IFF_NOARP | IFF_POINTOPOINT;
2841 } else {
2842 p->dev->header_ops = &isdn_header_ops;
2843 if (cfg->p_encap == ISDN_NET_ENCAP_ETHER)
2844 p->dev->flags = IFF_BROADCAST | IFF_MULTICAST;
2845 else
2846 p->dev->flags = IFF_NOARP | IFF_POINTOPOINT;
2847 }
2848 }
2849 lp->p_encap = cfg->p_encap;
2850 return 0;
2851 }
2852 return -ENODEV;
2853}
2854
2855/*
2856 * Perform get-interface-parameters.ioctl
2857 */
2858int
2859isdn_net_getcfg(isdn_net_ioctl_cfg *cfg)
2860{
2861 isdn_net_dev *p = isdn_net_findif(cfg->name);
2862
2863 if (p) {
2864 isdn_net_local *lp = p->local;
2865
2866 strcpy(cfg->eaz, lp->msn);
2867 cfg->exclusive = lp->exclusive;
2868 if (lp->pre_device >= 0) {
2869 sprintf(cfg->drvid, "%s,%d", dev->drvid[lp->pre_device],
2870 lp->pre_channel);
2871 } else
2872 cfg->drvid[0] = '\0';
2873 cfg->onhtime = lp->onhtime;
2874 cfg->charge = lp->charge;
2875 cfg->l2_proto = lp->l2_proto;
2876 cfg->l3_proto = lp->l3_proto;
2877 cfg->p_encap = lp->p_encap;
2878 cfg->secure = (lp->flags & ISDN_NET_SECURE) ? 1 : 0;
2879 cfg->callback = 0;
2880 if (lp->flags & ISDN_NET_CALLBACK)
2881 cfg->callback = 1;
2882 if (lp->flags & ISDN_NET_CBOUT)
2883 cfg->callback = 2;
2884 cfg->cbhup = (lp->flags & ISDN_NET_CBHUP) ? 1 : 0;
2885 cfg->dialmode = lp->flags & ISDN_NET_DIALMODE_MASK;
2886 cfg->chargehup = (lp->hupflags & ISDN_CHARGEHUP) ? 1 : 0;
2887 cfg->ihup = (lp->hupflags & ISDN_INHUP) ? 1 : 0;
2888 cfg->cbdelay = lp->cbdelay;
2889 cfg->dialmax = lp->dialmax;
2890 cfg->triggercps = lp->triggercps;
2891 cfg->slavedelay = lp->slavedelay / HZ;
2892 cfg->chargeint = (lp->hupflags & ISDN_CHARGEHUP) ?
2893 (lp->chargeint / HZ) : 0;
2894 cfg->pppbind = lp->pppbind;
2895 cfg->dialtimeout = lp->dialtimeout >= 0 ? lp->dialtimeout / HZ : -1;
2896 cfg->dialwait = lp->dialwait / HZ;
2897 if (lp->slave) {
2898 if (strlen(lp->slave->name) >= 10)
2899 strcpy(cfg->slave, "too-long");
2900 else
2901 strcpy(cfg->slave, lp->slave->name);
2902 } else
2903 cfg->slave[0] = '\0';
2904 if (lp->master) {
2905 if (strlen(lp->master->name) >= 10)
2906 strcpy(cfg->master, "too-long");
2907 else
2908 strcpy(cfg->master, lp->master->name);
2909 } else
2910 cfg->master[0] = '\0';
2911 return 0;
2912 }
2913 return -ENODEV;
2914}
2915
2916/*
2917 * Add a phone-number to an interface.
2918 */
2919int
2920isdn_net_addphone(isdn_net_ioctl_phone *phone)
2921{
2922 isdn_net_dev *p = isdn_net_findif(phone->name);
2923 isdn_net_phone *n;
2924
2925 if (p) {
2926 if (!(n = kmalloc(sizeof(isdn_net_phone), GFP_KERNEL)))
2927 return -ENOMEM;
2928 strlcpy(n->num, phone->phone, sizeof(n->num));
2929 n->next = p->local->phone[phone->outgoing & 1];
2930 p->local->phone[phone->outgoing & 1] = n;
2931 return 0;
2932 }
2933 return -ENODEV;
2934}
2935
2936/*
2937 * Copy a string of all phone-numbers of an interface to user space.
2938 * This might sleep and must be called with the isdn semaphore down.
2939 */
2940int
2941isdn_net_getphones(isdn_net_ioctl_phone *phone, char __user *phones)
2942{
2943 isdn_net_dev *p = isdn_net_findif(phone->name);
2944 int inout = phone->outgoing & 1;
2945 int more = 0;
2946 int count = 0;
2947 isdn_net_phone *n;
2948
2949 if (!p)
2950 return -ENODEV;
2951 inout &= 1;
2952 for (n = p->local->phone[inout]; n; n = n->next) {
2953 if (more) {
2954 put_user(' ', phones++);
2955 count++;
2956 }
2957 if (copy_to_user(phones, n->num, strlen(n->num) + 1)) {
2958 return -EFAULT;
2959 }
2960 phones += strlen(n->num);
2961 count += strlen(n->num);
2962 more = 1;
2963 }
2964 put_user(0, phones);
2965 count++;
2966 return count;
2967}
2968
2969/*
2970 * Copy a string containing the peer's phone number of a connected interface
2971 * to user space.
2972 */
2973int
2974isdn_net_getpeer(isdn_net_ioctl_phone *phone, isdn_net_ioctl_phone __user *peer)
2975{
2976 isdn_net_dev *p = isdn_net_findif(phone->name);
2977 int ch, dv, idx;
2978
2979 if (!p)
2980 return -ENODEV;
2981 /*
2982 * Theoretical race: while this executes, the remote number might
2983 * become invalid (hang up) or change (new connection), resulting
2984 * in (partially) wrong number copied to user. This race
2985 * currently ignored.
2986 */
2987 ch = p->local->isdn_channel;
2988 dv = p->local->isdn_device;
2989 if (ch < 0 && dv < 0)
2990 return -ENOTCONN;
2991 idx = isdn_dc2minor(dv, ch);
2992 if (idx < 0)
2993 return -ENODEV;
2994 /* for pre-bound channels, we need this extra check */
2995 if (strncmp(dev->num[idx], "???", 3) == 0)
2996 return -ENOTCONN;
2997 strncpy(phone->phone, dev->num[idx], ISDN_MSNLEN);
2998 phone->outgoing = USG_OUTGOING(dev->usage[idx]);
2999 if (copy_to_user(peer, phone, sizeof(*peer)))
3000 return -EFAULT;
3001 return 0;
3002}
3003/*
3004 * Delete a phone-number from an interface.
3005 */
3006int
3007isdn_net_delphone(isdn_net_ioctl_phone *phone)
3008{
3009 isdn_net_dev *p = isdn_net_findif(phone->name);
3010 int inout = phone->outgoing & 1;
3011 isdn_net_phone *n;
3012 isdn_net_phone *m;
3013
3014 if (p) {
3015 n = p->local->phone[inout];
3016 m = NULL;
3017 while (n) {
3018 if (!strcmp(n->num, phone->phone)) {
3019 if (p->local->dial == n)
3020 p->local->dial = n->next;
3021 if (m)
3022 m->next = n->next;
3023 else
3024 p->local->phone[inout] = n->next;
3025 kfree(n);
3026 return 0;
3027 }
3028 m = n;
3029 n = (isdn_net_phone *) n->next;
3030 }
3031 return -EINVAL;
3032 }
3033 return -ENODEV;
3034}
3035
3036/*
3037 * Delete all phone-numbers of an interface.
3038 */
3039static int
3040isdn_net_rmallphone(isdn_net_dev *p)
3041{
3042 isdn_net_phone *n;
3043 isdn_net_phone *m;
3044 int i;
3045
3046 for (i = 0; i < 2; i++) {
3047 n = p->local->phone[i];
3048 while (n) {
3049 m = n->next;
3050 kfree(n);
3051 n = m;
3052 }
3053 p->local->phone[i] = NULL;
3054 }
3055 p->local->dial = NULL;
3056 return 0;
3057}
3058
3059/*
3060 * Force a hangup of a network-interface.
3061 */
3062int
3063isdn_net_force_hangup(char *name)
3064{
3065 isdn_net_dev *p = isdn_net_findif(name);
3066 struct net_device *q;
3067
3068 if (p) {
3069 if (p->local->isdn_device < 0)
3070 return 1;
3071 q = p->local->slave;
3072 /* If this interface has slaves, do a hangup for them also. */
3073 while (q) {
3074 isdn_net_hangup(q);
3075 q = MASTER_TO_SLAVE(q);
3076 }
3077 isdn_net_hangup(p->dev);
3078 return 0;
3079 }
3080 return -ENODEV;
3081}
3082
3083/*
3084 * Helper-function for isdn_net_rm: Do the real work.
3085 */
3086static int
3087isdn_net_realrm(isdn_net_dev *p, isdn_net_dev *q)
3088{
3089 u_long flags;
3090
3091 if (isdn_net_device_started(p)) {
3092 return -EBUSY;
3093 }
3094#ifdef CONFIG_ISDN_X25
3095 if (p->cprot && p->cprot->pops)
3096 p->cprot->pops->proto_del(p->cprot);
3097#endif
3098 /* Free all phone-entries */
3099 isdn_net_rmallphone(p);
3100 /* If interface is bound exclusive, free channel-usage */
3101 if (p->local->exclusive != -1)
3102 isdn_unexclusive_channel(p->local->pre_device, p->local->pre_channel);
3103 if (p->local->master) {
3104 /* It's a slave-device, so update master's slave-pointer if necessary */
3105 if (((isdn_net_local *) ISDN_MASTER_PRIV(p->local))->slave ==
3106 p->dev)
3107 ((isdn_net_local *)ISDN_MASTER_PRIV(p->local))->slave =
3108 p->local->slave;
3109 } else {
3110 /* Unregister only if it's a master-device */
3111 unregister_netdev(p->dev);
3112 }
3113 /* Unlink device from chain */
3114 spin_lock_irqsave(&dev->lock, flags);
3115 if (q)
3116 q->next = p->next;
3117 else
3118 dev->netdev = p->next;
3119 if (p->local->slave) {
3120 /* If this interface has a slave, remove it also */
3121 char *slavename = p->local->slave->name;
3122 isdn_net_dev *n = dev->netdev;
3123 q = NULL;
3124 while (n) {
3125 if (!strcmp(n->dev->name, slavename)) {
3126 spin_unlock_irqrestore(&dev->lock, flags);
3127 isdn_net_realrm(n, q);
3128 spin_lock_irqsave(&dev->lock, flags);
3129 break;
3130 }
3131 q = n;
3132 n = (isdn_net_dev *)n->next;
3133 }
3134 }
3135 spin_unlock_irqrestore(&dev->lock, flags);
3136 /* If no more net-devices remain, disable auto-hangup timer */
3137 if (dev->netdev == NULL)
3138 isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, 0);
3139 free_netdev(p->dev);
3140 kfree(p);
3141
3142 return 0;
3143}
3144
3145/*
3146 * Remove a single network-interface.
3147 */
3148int
3149isdn_net_rm(char *name)
3150{
3151 u_long flags;
3152 isdn_net_dev *p;
3153 isdn_net_dev *q;
3154
3155 /* Search name in netdev-chain */
3156 spin_lock_irqsave(&dev->lock, flags);
3157 p = dev->netdev;
3158 q = NULL;
3159 while (p) {
3160 if (!strcmp(p->dev->name, name)) {
3161 spin_unlock_irqrestore(&dev->lock, flags);
3162 return (isdn_net_realrm(p, q));
3163 }
3164 q = p;
3165 p = (isdn_net_dev *) p->next;
3166 }
3167 spin_unlock_irqrestore(&dev->lock, flags);
3168 /* If no more net-devices remain, disable auto-hangup timer */
3169 if (dev->netdev == NULL)
3170 isdn_timer_ctrl(ISDN_TIMER_NETHANGUP, 0);
3171 return -ENODEV;
3172}
3173
3174/*
3175 * Remove all network-interfaces
3176 */
3177int
3178isdn_net_rmall(void)
3179{
3180 u_long flags;
3181 int ret;
3182
3183 /* Walk through netdev-chain */
3184 spin_lock_irqsave(&dev->lock, flags);
3185 while (dev->netdev) {
3186 if (!dev->netdev->local->master) {
3187 /* Remove master-devices only, slaves get removed with their master */
3188 spin_unlock_irqrestore(&dev->lock, flags);
3189 if ((ret = isdn_net_realrm(dev->netdev, NULL))) {
3190 return ret;
3191 }
3192 spin_lock_irqsave(&dev->lock, flags);
3193 }
3194 }
3195 dev->netdev = NULL;
3196 spin_unlock_irqrestore(&dev->lock, flags);
3197 return 0;
3198}
diff --git a/drivers/isdn/i4l/isdn_net.h b/drivers/isdn/i4l/isdn_net.h
deleted file mode 100644
index cca6d68da171..000000000000
--- a/drivers/isdn/i4l/isdn_net.h
+++ /dev/null
@@ -1,151 +0,0 @@
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#define ISDN_MASTER_PRIV(lp) ((isdn_net_local *) netdev_priv(lp->master))
60#define ISDN_SLAVE_PRIV(lp) ((isdn_net_local *) netdev_priv(lp->slave))
61#define MASTER_TO_SLAVE(master) \
62 (((isdn_net_local *) netdev_priv(master))->slave)
63
64/*
65 * is this particular channel busy?
66 */
67static __inline__ int isdn_net_lp_busy(isdn_net_local *lp)
68{
69 if (atomic_read(&lp->frame_cnt) < ISDN_NET_MAX_QUEUE_LENGTH)
70 return 0;
71 else
72 return 1;
73}
74
75/*
76 * For the given net device, this will get a non-busy channel out of the
77 * corresponding bundle. The returned channel is locked.
78 */
79static __inline__ isdn_net_local *isdn_net_get_locked_lp(isdn_net_dev *nd)
80{
81 unsigned long flags;
82 isdn_net_local *lp;
83
84 spin_lock_irqsave(&nd->queue_lock, flags);
85 lp = nd->queue; /* get lp on top of queue */
86 while (isdn_net_lp_busy(nd->queue)) {
87 nd->queue = nd->queue->next;
88 if (nd->queue == lp) { /* not found -- should never happen */
89 lp = NULL;
90 goto errout;
91 }
92 }
93 lp = nd->queue;
94 nd->queue = nd->queue->next;
95 spin_unlock_irqrestore(&nd->queue_lock, flags);
96 spin_lock(&lp->xmit_lock);
97 local_bh_disable();
98 return lp;
99errout:
100 spin_unlock_irqrestore(&nd->queue_lock, flags);
101 return lp;
102}
103
104/*
105 * add a channel to a bundle
106 */
107static __inline__ void isdn_net_add_to_bundle(isdn_net_dev *nd, isdn_net_local *nlp)
108{
109 isdn_net_local *lp;
110 unsigned long flags;
111
112 spin_lock_irqsave(&nd->queue_lock, flags);
113
114 lp = nd->queue;
115// printk(KERN_DEBUG "%s: lp:%s(%p) nlp:%s(%p) last(%p)\n",
116// __func__, lp->name, lp, nlp->name, nlp, lp->last);
117 nlp->last = lp->last;
118 lp->last->next = nlp;
119 lp->last = nlp;
120 nlp->next = lp;
121 nd->queue = nlp;
122
123 spin_unlock_irqrestore(&nd->queue_lock, flags);
124}
125/*
126 * remove a channel from the bundle it belongs to
127 */
128static __inline__ void isdn_net_rm_from_bundle(isdn_net_local *lp)
129{
130 isdn_net_local *master_lp = lp;
131 unsigned long flags;
132
133 if (lp->master)
134 master_lp = ISDN_MASTER_PRIV(lp);
135
136// printk(KERN_DEBUG "%s: lp:%s(%p) mlp:%s(%p) last(%p) next(%p) mndq(%p)\n",
137// __func__, lp->name, lp, master_lp->name, master_lp, lp->last, lp->next, master_lp->netdev->queue);
138 spin_lock_irqsave(&master_lp->netdev->queue_lock, flags);
139 lp->last->next = lp->next;
140 lp->next->last = lp->last;
141 if (master_lp->netdev->queue == lp) {
142 master_lp->netdev->queue = lp->next;
143 if (lp->next == lp) { /* last in queue */
144 master_lp->netdev->queue = master_lp->netdev->local;
145 }
146 }
147 lp->next = lp->last = lp; /* (re)set own pointers */
148// printk(KERN_DEBUG "%s: mndq(%p)\n",
149// __func__, master_lp->netdev->queue);
150 spin_unlock_irqrestore(&master_lp->netdev->queue_lock, flags);
151}
diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c
deleted file mode 100644
index 7e0f419c14f8..000000000000
--- a/drivers/isdn/i4l/isdn_ppp.c
+++ /dev/null
@@ -1,3046 +0,0 @@
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/isdn.h>
13#include <linux/poll.h>
14#include <linux/ppp-comp.h>
15#include <linux/slab.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(struct timer_list *t);
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 __func__, 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 __func__, 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 /* get unit number from interface name .. ugly! */
195 unit = isdn_ppp_if_get_unit(lp->netdev->dev->name);
196 if (unit < 0) {
197 printk(KERN_ERR "isdn_ppp_bind: illegal interface name %s.\n",
198 lp->netdev->dev->name);
199 retval = -1;
200 goto out;
201 }
202
203 lp->ppp_slot = i;
204 is = ippp_table[i];
205 is->lp = lp;
206 is->unit = unit;
207 is->state = IPPP_OPEN | IPPP_ASSIGNED; /* assigned to a netdevice but not connected */
208#ifdef CONFIG_ISDN_MPP
209 retval = isdn_ppp_mp_init(lp, NULL);
210 if (retval < 0)
211 goto out;
212#endif /* CONFIG_ISDN_MPP */
213
214 retval = lp->ppp_slot;
215
216out:
217 return retval;
218}
219
220/*
221 * kick the ipppd on the device
222 * (wakes up daemon after B-channel connect)
223 */
224
225void
226isdn_ppp_wakeup_daemon(isdn_net_local *lp)
227{
228 if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) {
229 printk(KERN_ERR "%s: ppp_slot(%d) out of range\n",
230 __func__, lp->ppp_slot);
231 return;
232 }
233 ippp_table[lp->ppp_slot]->state = IPPP_OPEN | IPPP_CONNECT | IPPP_NOBLOCK;
234 wake_up_interruptible(&ippp_table[lp->ppp_slot]->wq);
235}
236
237/*
238 * there was a hangup on the netdevice
239 * force wakeup of the ippp device
240 * go into 'device waits for release' state
241 */
242static int
243isdn_ppp_closewait(int slot)
244{
245 struct ippp_struct *is;
246
247 if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
248 printk(KERN_ERR "%s: slot(%d) out of range\n",
249 __func__, slot);
250 return 0;
251 }
252 is = ippp_table[slot];
253 if (is->state)
254 wake_up_interruptible(&is->wq);
255 is->state = IPPP_CLOSEWAIT;
256 return 1;
257}
258
259/*
260 * isdn_ppp_find_slot / isdn_ppp_free_slot
261 */
262
263static int
264isdn_ppp_get_slot(void)
265{
266 int i;
267 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
268 if (!ippp_table[i]->state)
269 return i;
270 }
271 return -1;
272}
273
274/*
275 * isdn_ppp_open
276 */
277
278int
279isdn_ppp_open(int min, struct file *file)
280{
281 int slot;
282 struct ippp_struct *is;
283
284 if (min < 0 || min >= ISDN_MAX_CHANNELS)
285 return -ENODEV;
286
287 slot = isdn_ppp_get_slot();
288 if (slot < 0) {
289 return -EBUSY;
290 }
291 is = file->private_data = ippp_table[slot];
292
293 printk(KERN_DEBUG "ippp, open, slot: %d, minor: %d, state: %04x\n",
294 slot, min, is->state);
295
296 /* compression stuff */
297 is->link_compressor = is->compressor = NULL;
298 is->link_decompressor = is->decompressor = NULL;
299 is->link_comp_stat = is->comp_stat = NULL;
300 is->link_decomp_stat = is->decomp_stat = NULL;
301 is->compflags = 0;
302
303 is->reset = isdn_ppp_ccp_reset_alloc(is);
304 if (!is->reset)
305 return -ENOMEM;
306
307 is->lp = NULL;
308 is->mp_seqno = 0; /* MP sequence number */
309 is->pppcfg = 0; /* ppp configuration */
310 is->mpppcfg = 0; /* mppp configuration */
311 is->last_link_seqno = -1; /* MP: maybe set to Bundle-MIN, when joining a bundle ?? */
312 is->unit = -1; /* set, when we have our interface */
313 is->mru = 1524; /* MRU, default 1524 */
314 is->maxcid = 16; /* VJ: maxcid */
315 is->tk = current;
316 init_waitqueue_head(&is->wq);
317 is->first = is->rq + NUM_RCV_BUFFS - 1; /* receive queue */
318 is->last = is->rq;
319 is->minor = min;
320#ifdef CONFIG_ISDN_PPP_VJ
321 /*
322 * VJ header compression init
323 */
324 is->slcomp = slhc_init(16, 16); /* not necessary for 2. link in bundle */
325 if (IS_ERR(is->slcomp)) {
326 isdn_ppp_ccp_reset_free(is);
327 return PTR_ERR(is->slcomp);
328 }
329#endif
330#ifdef CONFIG_IPPP_FILTER
331 is->pass_filter = NULL;
332 is->active_filter = NULL;
333#endif
334 is->state = IPPP_OPEN;
335
336 return 0;
337}
338
339/*
340 * release ippp device
341 */
342void
343isdn_ppp_release(int min, struct file *file)
344{
345 int i;
346 struct ippp_struct *is;
347
348 if (min < 0 || min >= ISDN_MAX_CHANNELS)
349 return;
350 is = file->private_data;
351
352 if (!is) {
353 printk(KERN_ERR "%s: no file->private_data\n", __func__);
354 return;
355 }
356 if (is->debug & 0x1)
357 printk(KERN_DEBUG "ippp: release, minor: %d %lx\n", min, (long) is->lp);
358
359 if (is->lp) { /* a lp address says: this link is still up */
360 isdn_net_dev *p = is->lp->netdev;
361
362 if (!p) {
363 printk(KERN_ERR "%s: no lp->netdev\n", __func__);
364 return;
365 }
366 is->state &= ~IPPP_CONNECT; /* -> effect: no call of wakeup */
367 /*
368 * isdn_net_hangup() calls isdn_ppp_free()
369 * isdn_ppp_free() sets is->lp to NULL and lp->ppp_slot to -1
370 * removing the IPPP_CONNECT flag omits calling of isdn_ppp_wakeup_daemon()
371 */
372 isdn_net_hangup(p->dev);
373 }
374 for (i = 0; i < NUM_RCV_BUFFS; i++) {
375 kfree(is->rq[i].buf);
376 is->rq[i].buf = NULL;
377 }
378 is->first = is->rq + NUM_RCV_BUFFS - 1; /* receive queue */
379 is->last = is->rq;
380
381#ifdef CONFIG_ISDN_PPP_VJ
382/* TODO: if this was the previous master: link the slcomp to the new master */
383 slhc_free(is->slcomp);
384 is->slcomp = NULL;
385#endif
386#ifdef CONFIG_IPPP_FILTER
387 if (is->pass_filter) {
388 bpf_prog_destroy(is->pass_filter);
389 is->pass_filter = NULL;
390 }
391
392 if (is->active_filter) {
393 bpf_prog_destroy(is->active_filter);
394 is->active_filter = NULL;
395 }
396#endif
397
398/* TODO: if this was the previous master: link the stuff to the new master */
399 if (is->comp_stat)
400 is->compressor->free(is->comp_stat);
401 if (is->link_comp_stat)
402 is->link_compressor->free(is->link_comp_stat);
403 if (is->link_decomp_stat)
404 is->link_decompressor->free(is->link_decomp_stat);
405 if (is->decomp_stat)
406 is->decompressor->free(is->decomp_stat);
407 is->compressor = is->link_compressor = NULL;
408 is->decompressor = is->link_decompressor = NULL;
409 is->comp_stat = is->link_comp_stat = NULL;
410 is->decomp_stat = is->link_decomp_stat = NULL;
411
412 /* Clean up if necessary */
413 if (is->reset)
414 isdn_ppp_ccp_reset_free(is);
415
416 /* this slot is ready for new connections */
417 is->state = 0;
418}
419
420/*
421 * get_arg .. ioctl helper
422 */
423static int
424get_arg(void __user *b, void *val, int len)
425{
426 if (len <= 0)
427 len = sizeof(void *);
428 if (copy_from_user(val, b, len))
429 return -EFAULT;
430 return 0;
431}
432
433/*
434 * set arg .. ioctl helper
435 */
436static int
437set_arg(void __user *b, void *val, int len)
438{
439 if (len <= 0)
440 len = sizeof(void *);
441 if (copy_to_user(b, val, len))
442 return -EFAULT;
443 return 0;
444}
445
446#ifdef CONFIG_IPPP_FILTER
447static int get_filter(void __user *arg, struct sock_filter **p)
448{
449 struct sock_fprog uprog;
450 struct sock_filter *code = NULL;
451 int len;
452
453 if (copy_from_user(&uprog, arg, sizeof(uprog)))
454 return -EFAULT;
455
456 if (!uprog.len) {
457 *p = NULL;
458 return 0;
459 }
460
461 /* uprog.len is unsigned short, so no overflow here */
462 len = uprog.len * sizeof(struct sock_filter);
463 code = memdup_user(uprog.filter, len);
464 if (IS_ERR(code))
465 return PTR_ERR(code);
466
467 *p = code;
468 return uprog.len;
469}
470#endif /* CONFIG_IPPP_FILTER */
471
472/*
473 * ippp device ioctl
474 */
475int
476isdn_ppp_ioctl(int min, struct file *file, unsigned int cmd, unsigned long arg)
477{
478 unsigned long val;
479 int r, i, j;
480 struct ippp_struct *is;
481 isdn_net_local *lp;
482 struct isdn_ppp_comp_data data;
483 void __user *argp = (void __user *)arg;
484
485 is = file->private_data;
486 lp = is->lp;
487
488 if (is->debug & 0x1)
489 printk(KERN_DEBUG "isdn_ppp_ioctl: minor: %d cmd: %x state: %x\n", min, cmd, is->state);
490
491 if (!(is->state & IPPP_OPEN))
492 return -EINVAL;
493
494 switch (cmd) {
495 case PPPIOCBUNDLE:
496#ifdef CONFIG_ISDN_MPP
497 if (!(is->state & IPPP_CONNECT))
498 return -EINVAL;
499 if ((r = get_arg(argp, &val, sizeof(val))))
500 return r;
501 printk(KERN_DEBUG "iPPP-bundle: minor: %d, slave unit: %d, master unit: %d\n",
502 (int) min, (int) is->unit, (int) val);
503 return isdn_ppp_bundle(is, val);
504#else
505 return -1;
506#endif
507 break;
508 case PPPIOCGUNIT: /* get ppp/isdn unit number */
509 if ((r = set_arg(argp, &is->unit, sizeof(is->unit))))
510 return r;
511 break;
512 case PPPIOCGIFNAME:
513 if (!lp)
514 return -EINVAL;
515 if ((r = set_arg(argp, lp->netdev->dev->name,
516 strlen(lp->netdev->dev->name))))
517 return r;
518 break;
519 case PPPIOCGMPFLAGS: /* get configuration flags */
520 if ((r = set_arg(argp, &is->mpppcfg, sizeof(is->mpppcfg))))
521 return r;
522 break;
523 case PPPIOCSMPFLAGS: /* set configuration flags */
524 if ((r = get_arg(argp, &val, sizeof(val))))
525 return r;
526 is->mpppcfg = val;
527 break;
528 case PPPIOCGFLAGS: /* get configuration flags */
529 if ((r = set_arg(argp, &is->pppcfg, sizeof(is->pppcfg))))
530 return r;
531 break;
532 case PPPIOCSFLAGS: /* set configuration flags */
533 if ((r = get_arg(argp, &val, sizeof(val)))) {
534 return r;
535 }
536 if (val & SC_ENABLE_IP && !(is->pppcfg & SC_ENABLE_IP) && (is->state & IPPP_CONNECT)) {
537 if (lp) {
538 /* OK .. we are ready to send buffers */
539 is->pppcfg = val; /* isdn_ppp_xmit test for SC_ENABLE_IP !!! */
540 netif_wake_queue(lp->netdev->dev);
541 break;
542 }
543 }
544 is->pppcfg = val;
545 break;
546 case PPPIOCGIDLE: /* get idle time information */
547 if (lp) {
548 struct ppp_idle pidle;
549 pidle.xmit_idle = pidle.recv_idle = lp->huptimer;
550 if ((r = set_arg(argp, &pidle, sizeof(struct ppp_idle))))
551 return r;
552 }
553 break;
554 case PPPIOCSMRU: /* set receive unit size for PPP */
555 if ((r = get_arg(argp, &val, sizeof(val))))
556 return r;
557 is->mru = val;
558 break;
559 case PPPIOCSMPMRU:
560 break;
561 case PPPIOCSMPMTU:
562 break;
563 case PPPIOCSMAXCID: /* set the maximum compression slot id */
564 if ((r = get_arg(argp, &val, sizeof(val))))
565 return r;
566 val++;
567 if (is->maxcid != val) {
568#ifdef CONFIG_ISDN_PPP_VJ
569 struct slcompress *sltmp;
570#endif
571 if (is->debug & 0x1)
572 printk(KERN_DEBUG "ippp, ioctl: changed MAXCID to %ld\n", val);
573 is->maxcid = val;
574#ifdef CONFIG_ISDN_PPP_VJ
575 sltmp = slhc_init(16, val);
576 if (IS_ERR(sltmp))
577 return PTR_ERR(sltmp);
578 if (is->slcomp)
579 slhc_free(is->slcomp);
580 is->slcomp = sltmp;
581#endif
582 }
583 break;
584 case PPPIOCGDEBUG:
585 if ((r = set_arg(argp, &is->debug, sizeof(is->debug))))
586 return r;
587 break;
588 case PPPIOCSDEBUG:
589 if ((r = get_arg(argp, &val, sizeof(val))))
590 return r;
591 is->debug = val;
592 break;
593 case PPPIOCGCOMPRESSORS:
594 {
595 unsigned long protos[8] = {0,};
596 struct isdn_ppp_compressor *ipc = ipc_head;
597 while (ipc) {
598 j = ipc->num / (sizeof(long) * 8);
599 i = ipc->num % (sizeof(long) * 8);
600 if (j < 8)
601 protos[j] |= (1UL << i);
602 ipc = ipc->next;
603 }
604 if ((r = set_arg(argp, protos, 8 * sizeof(long))))
605 return r;
606 }
607 break;
608 case PPPIOCSCOMPRESSOR:
609 if ((r = get_arg(argp, &data, sizeof(struct isdn_ppp_comp_data))))
610 return r;
611 return isdn_ppp_set_compressor(is, &data);
612 case PPPIOCGCALLINFO:
613 {
614 struct pppcallinfo pci;
615 memset((char *)&pci, 0, sizeof(struct pppcallinfo));
616 if (lp)
617 {
618 strncpy(pci.local_num, lp->msn, 63);
619 if (lp->dial) {
620 strncpy(pci.remote_num, lp->dial->num, 63);
621 }
622 pci.charge_units = lp->charge;
623 if (lp->outgoing)
624 pci.calltype = CALLTYPE_OUTGOING;
625 else
626 pci.calltype = CALLTYPE_INCOMING;
627 if (lp->flags & ISDN_NET_CALLBACK)
628 pci.calltype |= CALLTYPE_CALLBACK;
629 }
630 return set_arg(argp, &pci, sizeof(struct pppcallinfo));
631 }
632#ifdef CONFIG_IPPP_FILTER
633 case PPPIOCSPASS:
634 {
635 struct sock_fprog_kern fprog;
636 struct sock_filter *code;
637 int err, len = get_filter(argp, &code);
638
639 if (len < 0)
640 return len;
641
642 fprog.len = len;
643 fprog.filter = code;
644
645 if (is->pass_filter) {
646 bpf_prog_destroy(is->pass_filter);
647 is->pass_filter = NULL;
648 }
649 if (fprog.filter != NULL)
650 err = bpf_prog_create(&is->pass_filter, &fprog);
651 else
652 err = 0;
653 kfree(code);
654
655 return err;
656 }
657 case PPPIOCSACTIVE:
658 {
659 struct sock_fprog_kern fprog;
660 struct sock_filter *code;
661 int err, len = get_filter(argp, &code);
662
663 if (len < 0)
664 return len;
665
666 fprog.len = len;
667 fprog.filter = code;
668
669 if (is->active_filter) {
670 bpf_prog_destroy(is->active_filter);
671 is->active_filter = NULL;
672 }
673 if (fprog.filter != NULL)
674 err = bpf_prog_create(&is->active_filter, &fprog);
675 else
676 err = 0;
677 kfree(code);
678
679 return err;
680 }
681#endif /* CONFIG_IPPP_FILTER */
682 default:
683 break;
684 }
685 return 0;
686}
687
688__poll_t
689isdn_ppp_poll(struct file *file, poll_table *wait)
690{
691 __poll_t mask;
692 struct ippp_buf_queue *bf, *bl;
693 u_long flags;
694 struct ippp_struct *is;
695
696 is = file->private_data;
697
698 if (is->debug & 0x2)
699 printk(KERN_DEBUG "isdn_ppp_poll: minor: %d\n",
700 iminor(file_inode(file)));
701
702 /* just registers wait_queue hook. This doesn't really wait. */
703 poll_wait(file, &is->wq, wait);
704
705 if (!(is->state & IPPP_OPEN)) {
706 if (is->state == IPPP_CLOSEWAIT)
707 return EPOLLHUP;
708 printk(KERN_DEBUG "isdn_ppp: device not open\n");
709 return EPOLLERR;
710 }
711 /* we're always ready to send .. */
712 mask = EPOLLOUT | EPOLLWRNORM;
713
714 spin_lock_irqsave(&is->buflock, flags);
715 bl = is->last;
716 bf = is->first;
717 /*
718 * if IPPP_NOBLOCK is set we return even if we have nothing to read
719 */
720 if (bf->next != bl || (is->state & IPPP_NOBLOCK)) {
721 is->state &= ~IPPP_NOBLOCK;
722 mask |= EPOLLIN | EPOLLRDNORM;
723 }
724 spin_unlock_irqrestore(&is->buflock, flags);
725 return mask;
726}
727
728/*
729 * fill up isdn_ppp_read() queue ..
730 */
731
732static int
733isdn_ppp_fill_rq(unsigned char *buf, int len, int proto, int slot)
734{
735 struct ippp_buf_queue *bf, *bl;
736 u_long flags;
737 u_char *nbuf;
738 struct ippp_struct *is;
739
740 if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
741 printk(KERN_WARNING "ippp: illegal slot(%d).\n", slot);
742 return 0;
743 }
744 is = ippp_table[slot];
745
746 if (!(is->state & IPPP_CONNECT)) {
747 printk(KERN_DEBUG "ippp: device not activated.\n");
748 return 0;
749 }
750 nbuf = kmalloc(len + 4, GFP_ATOMIC);
751 if (!nbuf) {
752 printk(KERN_WARNING "ippp: Can't alloc buf\n");
753 return 0;
754 }
755 nbuf[0] = PPP_ALLSTATIONS;
756 nbuf[1] = PPP_UI;
757 nbuf[2] = proto >> 8;
758 nbuf[3] = proto & 0xff;
759 memcpy(nbuf + 4, buf, len);
760
761 spin_lock_irqsave(&is->buflock, flags);
762 bf = is->first;
763 bl = is->last;
764
765 if (bf == bl) {
766 printk(KERN_WARNING "ippp: Queue is full; discarding first buffer\n");
767 bf = bf->next;
768 kfree(bf->buf);
769 is->first = bf;
770 }
771 bl->buf = (char *) nbuf;
772 bl->len = len + 4;
773
774 is->last = bl->next;
775 spin_unlock_irqrestore(&is->buflock, flags);
776 wake_up_interruptible(&is->wq);
777 return len;
778}
779
780/*
781 * read() .. non-blocking: ipppd calls it only after select()
782 * reports, that there is data
783 */
784
785int
786isdn_ppp_read(int min, struct file *file, char __user *buf, int count)
787{
788 struct ippp_struct *is;
789 struct ippp_buf_queue *b;
790 u_long flags;
791 u_char *save_buf;
792
793 is = file->private_data;
794
795 if (!(is->state & IPPP_OPEN))
796 return 0;
797
798 spin_lock_irqsave(&is->buflock, flags);
799 b = is->first->next;
800 save_buf = b->buf;
801 if (!save_buf) {
802 spin_unlock_irqrestore(&is->buflock, flags);
803 return -EAGAIN;
804 }
805 if (b->len < count)
806 count = b->len;
807 b->buf = NULL;
808 is->first = b;
809
810 spin_unlock_irqrestore(&is->buflock, flags);
811 if (copy_to_user(buf, save_buf, count))
812 count = -EFAULT;
813 kfree(save_buf);
814
815 return count;
816}
817
818/*
819 * ipppd wanna write a packet to the card .. non-blocking
820 */
821
822int
823isdn_ppp_write(int min, struct file *file, const char __user *buf, int count)
824{
825 isdn_net_local *lp;
826 struct ippp_struct *is;
827 int proto;
828
829 is = file->private_data;
830
831 if (!(is->state & IPPP_CONNECT))
832 return 0;
833
834 lp = is->lp;
835
836 /* -> push it directly to the lowlevel interface */
837
838 if (!lp)
839 printk(KERN_DEBUG "isdn_ppp_write: lp == NULL\n");
840 else {
841 if (lp->isdn_device < 0 || lp->isdn_channel < 0) {
842 unsigned char protobuf[4];
843 /*
844 * Don't reset huptimer for
845 * LCP packets. (Echo requests).
846 */
847 if (copy_from_user(protobuf, buf, 4))
848 return -EFAULT;
849
850 proto = PPP_PROTOCOL(protobuf);
851 if (proto != PPP_LCP)
852 lp->huptimer = 0;
853
854 return 0;
855 }
856
857 if ((dev->drv[lp->isdn_device]->flags & DRV_FLAG_RUNNING) &&
858 lp->dialstate == 0 &&
859 (lp->flags & ISDN_NET_CONNECTED)) {
860 unsigned short hl;
861 struct sk_buff *skb;
862 unsigned char *cpy_buf;
863 /*
864 * we need to reserve enough space in front of
865 * sk_buff. old call to dev_alloc_skb only reserved
866 * 16 bytes, now we are looking what the driver want
867 */
868 hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen;
869 skb = alloc_skb(hl + count, GFP_ATOMIC);
870 if (!skb) {
871 printk(KERN_WARNING "isdn_ppp_write: out of memory!\n");
872 return count;
873 }
874 skb_reserve(skb, hl);
875 cpy_buf = skb_put(skb, count);
876 if (copy_from_user(cpy_buf, buf, count))
877 {
878 kfree_skb(skb);
879 return -EFAULT;
880 }
881
882 /*
883 * Don't reset huptimer for
884 * LCP packets. (Echo requests).
885 */
886 proto = PPP_PROTOCOL(cpy_buf);
887 if (proto != PPP_LCP)
888 lp->huptimer = 0;
889
890 if (is->debug & 0x40) {
891 printk(KERN_DEBUG "ppp xmit: len %d\n", (int) skb->len);
892 isdn_ppp_frame_log("xmit", skb->data, skb->len, 32, is->unit, lp->ppp_slot);
893 }
894
895 isdn_ppp_send_ccp(lp->netdev, lp, skb); /* keeps CCP/compression states in sync */
896
897 isdn_net_write_super(lp, skb);
898 }
899 }
900 return count;
901}
902
903/*
904 * init memory, structures etc.
905 */
906
907int
908isdn_ppp_init(void)
909{
910 int i,
911 j;
912
913#ifdef CONFIG_ISDN_MPP
914 if (isdn_ppp_mp_bundle_array_init() < 0)
915 return -ENOMEM;
916#endif /* CONFIG_ISDN_MPP */
917
918 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
919 if (!(ippp_table[i] = kzalloc(sizeof(struct ippp_struct), GFP_KERNEL))) {
920 printk(KERN_WARNING "isdn_ppp_init: Could not alloc ippp_table\n");
921 for (j = 0; j < i; j++)
922 kfree(ippp_table[j]);
923 return -1;
924 }
925 spin_lock_init(&ippp_table[i]->buflock);
926 ippp_table[i]->state = 0;
927 ippp_table[i]->first = ippp_table[i]->rq + NUM_RCV_BUFFS - 1;
928 ippp_table[i]->last = ippp_table[i]->rq;
929
930 for (j = 0; j < NUM_RCV_BUFFS; j++) {
931 ippp_table[i]->rq[j].buf = NULL;
932 ippp_table[i]->rq[j].last = ippp_table[i]->rq +
933 (NUM_RCV_BUFFS + j - 1) % NUM_RCV_BUFFS;
934 ippp_table[i]->rq[j].next = ippp_table[i]->rq + (j + 1) % NUM_RCV_BUFFS;
935 }
936 }
937 return 0;
938}
939
940void
941isdn_ppp_cleanup(void)
942{
943 int i;
944
945 for (i = 0; i < ISDN_MAX_CHANNELS; i++)
946 kfree(ippp_table[i]);
947
948#ifdef CONFIG_ISDN_MPP
949 kfree(isdn_ppp_bundle_arr);
950#endif /* CONFIG_ISDN_MPP */
951
952}
953
954/*
955 * check for address/control field and skip if allowed
956 * retval != 0 -> discard packet silently
957 */
958static int isdn_ppp_skip_ac(struct ippp_struct *is, struct sk_buff *skb)
959{
960 if (skb->len < 1)
961 return -1;
962
963 if (skb->data[0] == 0xff) {
964 if (skb->len < 2)
965 return -1;
966
967 if (skb->data[1] != 0x03)
968 return -1;
969
970 // skip address/control (AC) field
971 skb_pull(skb, 2);
972 } else {
973 if (is->pppcfg & SC_REJ_COMP_AC)
974 // if AC compression was not negotiated, but used, discard packet
975 return -1;
976 }
977 return 0;
978}
979
980/*
981 * get the PPP protocol header and pull skb
982 * retval < 0 -> discard packet silently
983 */
984static int isdn_ppp_strip_proto(struct sk_buff *skb)
985{
986 int proto;
987
988 if (skb->len < 1)
989 return -1;
990
991 if (skb->data[0] & 0x1) {
992 // protocol field is compressed
993 proto = skb->data[0];
994 skb_pull(skb, 1);
995 } else {
996 if (skb->len < 2)
997 return -1;
998 proto = ((int) skb->data[0] << 8) + skb->data[1];
999 skb_pull(skb, 2);
1000 }
1001 return proto;
1002}
1003
1004
1005/*
1006 * handler for incoming packets on a syncPPP interface
1007 */
1008void isdn_ppp_receive(isdn_net_dev *net_dev, isdn_net_local *lp, struct sk_buff *skb)
1009{
1010 struct ippp_struct *is;
1011 int slot;
1012 int proto;
1013
1014 BUG_ON(net_dev->local->master); // we're called with the master device always
1015
1016 slot = lp->ppp_slot;
1017 if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
1018 printk(KERN_ERR "isdn_ppp_receive: lp->ppp_slot(%d)\n",
1019 lp->ppp_slot);
1020 kfree_skb(skb);
1021 return;
1022 }
1023 is = ippp_table[slot];
1024
1025 if (is->debug & 0x4) {
1026 printk(KERN_DEBUG "ippp_receive: is:%08lx lp:%08lx slot:%d unit:%d len:%d\n",
1027 (long)is, (long)lp, lp->ppp_slot, is->unit, (int)skb->len);
1028 isdn_ppp_frame_log("receive", skb->data, skb->len, 32, is->unit, lp->ppp_slot);
1029 }
1030
1031 if (isdn_ppp_skip_ac(is, skb) < 0) {
1032 kfree_skb(skb);
1033 return;
1034 }
1035 proto = isdn_ppp_strip_proto(skb);
1036 if (proto < 0) {
1037 kfree_skb(skb);
1038 return;
1039 }
1040
1041#ifdef CONFIG_ISDN_MPP
1042 if (is->compflags & SC_LINK_DECOMP_ON) {
1043 skb = isdn_ppp_decompress(skb, is, NULL, &proto);
1044 if (!skb) // decompression error
1045 return;
1046 }
1047
1048 if (!(is->mpppcfg & SC_REJ_MP_PROT)) { // we agreed to receive MPPP
1049 if (proto == PPP_MP) {
1050 isdn_ppp_mp_receive(net_dev, lp, skb);
1051 return;
1052 }
1053 }
1054#endif
1055 isdn_ppp_push_higher(net_dev, lp, skb, proto);
1056}
1057
1058/*
1059 * we receive a reassembled frame, MPPP has been taken care of before.
1060 * address/control and protocol have been stripped from the skb
1061 * note: net_dev has to be master net_dev
1062 */
1063static void
1064isdn_ppp_push_higher(isdn_net_dev *net_dev, isdn_net_local *lp, struct sk_buff *skb, int proto)
1065{
1066 struct net_device *dev = net_dev->dev;
1067 struct ippp_struct *is, *mis;
1068 isdn_net_local *mlp = NULL;
1069 int slot;
1070
1071 slot = lp->ppp_slot;
1072 if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
1073 printk(KERN_ERR "isdn_ppp_push_higher: lp->ppp_slot(%d)\n",
1074 lp->ppp_slot);
1075 goto drop_packet;
1076 }
1077 is = ippp_table[slot];
1078
1079 if (lp->master) { // FIXME?
1080 mlp = ISDN_MASTER_PRIV(lp);
1081 slot = mlp->ppp_slot;
1082 if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
1083 printk(KERN_ERR "isdn_ppp_push_higher: master->ppp_slot(%d)\n",
1084 lp->ppp_slot);
1085 goto drop_packet;
1086 }
1087 }
1088 mis = ippp_table[slot];
1089
1090 if (is->debug & 0x10) {
1091 printk(KERN_DEBUG "push, skb %d %04x\n", (int) skb->len, proto);
1092 isdn_ppp_frame_log("rpush", skb->data, skb->len, 32, is->unit, lp->ppp_slot);
1093 }
1094 if (mis->compflags & SC_DECOMP_ON) {
1095 skb = isdn_ppp_decompress(skb, is, mis, &proto);
1096 if (!skb) // decompression error
1097 return;
1098 }
1099 switch (proto) {
1100 case PPP_IPX: /* untested */
1101 if (is->debug & 0x20)
1102 printk(KERN_DEBUG "isdn_ppp: IPX\n");
1103 skb->protocol = htons(ETH_P_IPX);
1104 break;
1105 case PPP_IP:
1106 if (is->debug & 0x20)
1107 printk(KERN_DEBUG "isdn_ppp: IP\n");
1108 skb->protocol = htons(ETH_P_IP);
1109 break;
1110 case PPP_COMP:
1111 case PPP_COMPFRAG:
1112 printk(KERN_INFO "isdn_ppp: unexpected compressed frame dropped\n");
1113 goto drop_packet;
1114#ifdef CONFIG_ISDN_PPP_VJ
1115 case PPP_VJC_UNCOMP:
1116 if (is->debug & 0x20)
1117 printk(KERN_DEBUG "isdn_ppp: VJC_UNCOMP\n");
1118 if (net_dev->local->ppp_slot < 0) {
1119 printk(KERN_ERR "%s: net_dev->local->ppp_slot(%d) out of range\n",
1120 __func__, net_dev->local->ppp_slot);
1121 goto drop_packet;
1122 }
1123 if (slhc_remember(ippp_table[net_dev->local->ppp_slot]->slcomp, skb->data, skb->len) <= 0) {
1124 printk(KERN_WARNING "isdn_ppp: received illegal VJC_UNCOMP frame!\n");
1125 goto drop_packet;
1126 }
1127 skb->protocol = htons(ETH_P_IP);
1128 break;
1129 case PPP_VJC_COMP:
1130 if (is->debug & 0x20)
1131 printk(KERN_DEBUG "isdn_ppp: VJC_COMP\n");
1132 {
1133 struct sk_buff *skb_old = skb;
1134 int pkt_len;
1135 skb = dev_alloc_skb(skb_old->len + 128);
1136
1137 if (!skb) {
1138 printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n", dev->name);
1139 skb = skb_old;
1140 goto drop_packet;
1141 }
1142 skb_put(skb, skb_old->len + 128);
1143 skb_copy_from_linear_data(skb_old, skb->data,
1144 skb_old->len);
1145 if (net_dev->local->ppp_slot < 0) {
1146 printk(KERN_ERR "%s: net_dev->local->ppp_slot(%d) out of range\n",
1147 __func__, net_dev->local->ppp_slot);
1148 goto drop_packet;
1149 }
1150 pkt_len = slhc_uncompress(ippp_table[net_dev->local->ppp_slot]->slcomp,
1151 skb->data, skb_old->len);
1152 kfree_skb(skb_old);
1153 if (pkt_len < 0)
1154 goto drop_packet;
1155
1156 skb_trim(skb, pkt_len);
1157 skb->protocol = htons(ETH_P_IP);
1158 }
1159 break;
1160#endif
1161 case PPP_CCP:
1162 case PPP_CCPFRAG:
1163 isdn_ppp_receive_ccp(net_dev, lp, skb, proto);
1164 /* Dont pop up ResetReq/Ack stuff to the daemon any
1165 longer - the job is done already */
1166 if (skb->data[0] == CCP_RESETREQ ||
1167 skb->data[0] == CCP_RESETACK)
1168 break;
1169 /* fall through */
1170 default:
1171 isdn_ppp_fill_rq(skb->data, skb->len, proto, lp->ppp_slot); /* push data to pppd device */
1172 kfree_skb(skb);
1173 return;
1174 }
1175
1176#ifdef CONFIG_IPPP_FILTER
1177 /* check if the packet passes the pass and active filters
1178 * the filter instructions are constructed assuming
1179 * a four-byte PPP header on each packet (which is still present) */
1180 skb_push(skb, 4);
1181
1182 {
1183 u_int16_t *p = (u_int16_t *) skb->data;
1184
1185 *p = 0; /* indicate inbound */
1186 }
1187
1188 if (is->pass_filter
1189 && BPF_PROG_RUN(is->pass_filter, skb) == 0) {
1190 if (is->debug & 0x2)
1191 printk(KERN_DEBUG "IPPP: inbound frame filtered.\n");
1192 kfree_skb(skb);
1193 return;
1194 }
1195 if (!(is->active_filter
1196 && BPF_PROG_RUN(is->active_filter, skb) == 0)) {
1197 if (is->debug & 0x2)
1198 printk(KERN_DEBUG "IPPP: link-active filter: resetting huptimer.\n");
1199 lp->huptimer = 0;
1200 if (mlp)
1201 mlp->huptimer = 0;
1202 }
1203 skb_pull(skb, 4);
1204#else /* CONFIG_IPPP_FILTER */
1205 lp->huptimer = 0;
1206 if (mlp)
1207 mlp->huptimer = 0;
1208#endif /* CONFIG_IPPP_FILTER */
1209 skb->dev = dev;
1210 skb_reset_mac_header(skb);
1211 netif_rx(skb);
1212 /* net_dev->local->stats.rx_packets++; done in isdn_net.c */
1213 return;
1214
1215drop_packet:
1216 net_dev->local->stats.rx_dropped++;
1217 kfree_skb(skb);
1218}
1219
1220/*
1221 * isdn_ppp_skb_push ..
1222 * checks whether we have enough space at the beginning of the skb
1223 * and allocs a new SKB if necessary
1224 */
1225static unsigned char *isdn_ppp_skb_push(struct sk_buff **skb_p, int len)
1226{
1227 struct sk_buff *skb = *skb_p;
1228
1229 if (skb_headroom(skb) < len) {
1230 struct sk_buff *nskb = skb_realloc_headroom(skb, len);
1231
1232 if (!nskb) {
1233 printk(KERN_ERR "isdn_ppp_skb_push: can't realloc headroom!\n");
1234 dev_kfree_skb(skb);
1235 return NULL;
1236 }
1237 printk(KERN_DEBUG "isdn_ppp_skb_push:under %d %d\n", skb_headroom(skb), len);
1238 dev_kfree_skb(skb);
1239 *skb_p = nskb;
1240 return skb_push(nskb, len);
1241 }
1242 return skb_push(skb, len);
1243}
1244
1245/*
1246 * send ppp frame .. we expect a PIDCOMPressable proto --
1247 * (here: currently always PPP_IP,PPP_VJC_COMP,PPP_VJC_UNCOMP)
1248 *
1249 * VJ compression may change skb pointer!!! .. requeue with old
1250 * skb isn't allowed!!
1251 */
1252
1253int
1254isdn_ppp_xmit(struct sk_buff *skb, struct net_device *netdev)
1255{
1256 isdn_net_local *lp, *mlp;
1257 isdn_net_dev *nd;
1258 unsigned int proto = PPP_IP; /* 0x21 */
1259 struct ippp_struct *ipt, *ipts;
1260 int slot, retval = NETDEV_TX_OK;
1261
1262 mlp = netdev_priv(netdev);
1263 nd = mlp->netdev; /* get master lp */
1264
1265 slot = mlp->ppp_slot;
1266 if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
1267 printk(KERN_ERR "isdn_ppp_xmit: lp->ppp_slot(%d)\n",
1268 mlp->ppp_slot);
1269 kfree_skb(skb);
1270 goto out;
1271 }
1272 ipts = ippp_table[slot];
1273
1274 if (!(ipts->pppcfg & SC_ENABLE_IP)) { /* PPP connected ? */
1275 if (ipts->debug & 0x1)
1276 printk(KERN_INFO "%s: IP frame delayed.\n", netdev->name);
1277 retval = NETDEV_TX_BUSY;
1278 goto out;
1279 }
1280
1281 switch (ntohs(skb->protocol)) {
1282 case ETH_P_IP:
1283 proto = PPP_IP;
1284 break;
1285 case ETH_P_IPX:
1286 proto = PPP_IPX; /* untested */
1287 break;
1288 default:
1289 printk(KERN_ERR "isdn_ppp: skipped unsupported protocol: %#x.\n",
1290 skb->protocol);
1291 dev_kfree_skb(skb);
1292 goto out;
1293 }
1294
1295 lp = isdn_net_get_locked_lp(nd);
1296 if (!lp) {
1297 printk(KERN_WARNING "%s: all channels busy - requeuing!\n", netdev->name);
1298 retval = NETDEV_TX_BUSY;
1299 goto out;
1300 }
1301 /* we have our lp locked from now on */
1302
1303 slot = lp->ppp_slot;
1304 if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
1305 printk(KERN_ERR "isdn_ppp_xmit: lp->ppp_slot(%d)\n",
1306 lp->ppp_slot);
1307 kfree_skb(skb);
1308 goto unlock;
1309 }
1310 ipt = ippp_table[slot];
1311
1312 /*
1313 * after this line .. requeueing in the device queue is no longer allowed!!!
1314 */
1315
1316 /* Pull off the fake header we stuck on earlier to keep
1317 * the fragmentation code happy.
1318 */
1319 skb_pull(skb, IPPP_MAX_HEADER);
1320
1321#ifdef CONFIG_IPPP_FILTER
1322 /* check if we should pass this packet
1323 * the filter instructions are constructed assuming
1324 * a four-byte PPP header on each packet */
1325 *(u8 *)skb_push(skb, 4) = 1; /* indicate outbound */
1326
1327 {
1328 __be16 *p = (__be16 *)skb->data;
1329
1330 p++;
1331 *p = htons(proto);
1332 }
1333
1334 if (ipt->pass_filter
1335 && BPF_PROG_RUN(ipt->pass_filter, skb) == 0) {
1336 if (ipt->debug & 0x4)
1337 printk(KERN_DEBUG "IPPP: outbound frame filtered.\n");
1338 kfree_skb(skb);
1339 goto unlock;
1340 }
1341 if (!(ipt->active_filter
1342 && BPF_PROG_RUN(ipt->active_filter, skb) == 0)) {
1343 if (ipt->debug & 0x4)
1344 printk(KERN_DEBUG "IPPP: link-active filter: resetting huptimer.\n");
1345 lp->huptimer = 0;
1346 }
1347 skb_pull(skb, 4);
1348#else /* CONFIG_IPPP_FILTER */
1349 lp->huptimer = 0;
1350#endif /* CONFIG_IPPP_FILTER */
1351
1352 if (ipt->debug & 0x4)
1353 printk(KERN_DEBUG "xmit skb, len %d\n", (int) skb->len);
1354 if (ipts->debug & 0x40)
1355 isdn_ppp_frame_log("xmit0", skb->data, skb->len, 32, ipts->unit, lp->ppp_slot);
1356
1357#ifdef CONFIG_ISDN_PPP_VJ
1358 if (proto == PPP_IP && ipts->pppcfg & SC_COMP_TCP) { /* ipts here? probably yes, but check this again */
1359 struct sk_buff *new_skb;
1360 unsigned short hl;
1361 /*
1362 * we need to reserve enough space in front of
1363 * sk_buff. old call to dev_alloc_skb only reserved
1364 * 16 bytes, now we are looking what the driver want.
1365 */
1366 hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen + IPPP_MAX_HEADER;
1367 /*
1368 * Note: hl might still be insufficient because the method
1369 * above does not account for a possibible MPPP slave channel
1370 * which had larger HL header space requirements than the
1371 * master.
1372 */
1373 new_skb = alloc_skb(hl + skb->len, GFP_ATOMIC);
1374 if (new_skb) {
1375 u_char *buf;
1376 int pktlen;
1377
1378 skb_reserve(new_skb, hl);
1379 new_skb->dev = skb->dev;
1380 skb_put(new_skb, skb->len);
1381 buf = skb->data;
1382
1383 pktlen = slhc_compress(ipts->slcomp, skb->data, skb->len, new_skb->data,
1384 &buf, !(ipts->pppcfg & SC_NO_TCP_CCID));
1385
1386 if (buf != skb->data) {
1387 if (new_skb->data != buf)
1388 printk(KERN_ERR "isdn_ppp: FATAL error after slhc_compress!!\n");
1389 dev_kfree_skb(skb);
1390 skb = new_skb;
1391 } else {
1392 dev_kfree_skb(new_skb);
1393 }
1394
1395 skb_trim(skb, pktlen);
1396 if (skb->data[0] & SL_TYPE_COMPRESSED_TCP) { /* cslip? style -> PPP */
1397 proto = PPP_VJC_COMP;
1398 skb->data[0] ^= SL_TYPE_COMPRESSED_TCP;
1399 } else {
1400 if (skb->data[0] >= SL_TYPE_UNCOMPRESSED_TCP)
1401 proto = PPP_VJC_UNCOMP;
1402 skb->data[0] = (skb->data[0] & 0x0f) | 0x40;
1403 }
1404 }
1405 }
1406#endif
1407
1408 /*
1409 * normal (single link) or bundle compression
1410 */
1411 if (ipts->compflags & SC_COMP_ON) {
1412 /* We send compressed only if both down- und upstream
1413 compression is negotiated, that means, CCP is up */
1414 if (ipts->compflags & SC_DECOMP_ON) {
1415 skb = isdn_ppp_compress(skb, &proto, ipt, ipts, 0);
1416 } else {
1417 printk(KERN_DEBUG "isdn_ppp: CCP not yet up - sending as-is\n");
1418 }
1419 }
1420
1421 if (ipt->debug & 0x24)
1422 printk(KERN_DEBUG "xmit2 skb, len %d, proto %04x\n", (int) skb->len, proto);
1423
1424#ifdef CONFIG_ISDN_MPP
1425 if (ipt->mpppcfg & SC_MP_PROT) {
1426 /* we get mp_seqno from static isdn_net_local */
1427 long mp_seqno = ipts->mp_seqno;
1428 ipts->mp_seqno++;
1429 if (ipt->mpppcfg & SC_OUT_SHORT_SEQ) {
1430 unsigned char *data = isdn_ppp_skb_push(&skb, 3);
1431 if (!data)
1432 goto unlock;
1433 mp_seqno &= 0xfff;
1434 data[0] = MP_BEGIN_FRAG | MP_END_FRAG | ((mp_seqno >> 8) & 0xf); /* (B)egin & (E)ndbit .. */
1435 data[1] = mp_seqno & 0xff;
1436 data[2] = proto; /* PID compression */
1437 } else {
1438 unsigned char *data = isdn_ppp_skb_push(&skb, 5);
1439 if (!data)
1440 goto unlock;
1441 data[0] = MP_BEGIN_FRAG | MP_END_FRAG; /* (B)egin & (E)ndbit .. */
1442 data[1] = (mp_seqno >> 16) & 0xff; /* sequence number: 24bit */
1443 data[2] = (mp_seqno >> 8) & 0xff;
1444 data[3] = (mp_seqno >> 0) & 0xff;
1445 data[4] = proto; /* PID compression */
1446 }
1447 proto = PPP_MP; /* MP Protocol, 0x003d */
1448 }
1449#endif
1450
1451 /*
1452 * 'link in bundle' compression ...
1453 */
1454 if (ipt->compflags & SC_LINK_COMP_ON)
1455 skb = isdn_ppp_compress(skb, &proto, ipt, ipts, 1);
1456
1457 if ((ipt->pppcfg & SC_COMP_PROT) && (proto <= 0xff)) {
1458 unsigned char *data = isdn_ppp_skb_push(&skb, 1);
1459 if (!data)
1460 goto unlock;
1461 data[0] = proto & 0xff;
1462 }
1463 else {
1464 unsigned char *data = isdn_ppp_skb_push(&skb, 2);
1465 if (!data)
1466 goto unlock;
1467 data[0] = (proto >> 8) & 0xff;
1468 data[1] = proto & 0xff;
1469 }
1470 if (!(ipt->pppcfg & SC_COMP_AC)) {
1471 unsigned char *data = isdn_ppp_skb_push(&skb, 2);
1472 if (!data)
1473 goto unlock;
1474 data[0] = 0xff; /* All Stations */
1475 data[1] = 0x03; /* Unnumbered information */
1476 }
1477
1478 /* tx-stats are now updated via BSENT-callback */
1479
1480 if (ipts->debug & 0x40) {
1481 printk(KERN_DEBUG "skb xmit: len: %d\n", (int) skb->len);
1482 isdn_ppp_frame_log("xmit", skb->data, skb->len, 32, ipt->unit, lp->ppp_slot);
1483 }
1484
1485 isdn_net_writebuf_skb(lp, skb);
1486
1487unlock:
1488 spin_unlock_bh(&lp->xmit_lock);
1489out:
1490 return retval;
1491}
1492
1493#ifdef CONFIG_IPPP_FILTER
1494/*
1495 * check if this packet may trigger auto-dial.
1496 */
1497
1498int isdn_ppp_autodial_filter(struct sk_buff *skb, isdn_net_local *lp)
1499{
1500 struct ippp_struct *is = ippp_table[lp->ppp_slot];
1501 u_int16_t proto;
1502 int drop = 0;
1503
1504 switch (ntohs(skb->protocol)) {
1505 case ETH_P_IP:
1506 proto = PPP_IP;
1507 break;
1508 case ETH_P_IPX:
1509 proto = PPP_IPX;
1510 break;
1511 default:
1512 printk(KERN_ERR "isdn_ppp_autodial_filter: unsupported protocol 0x%x.\n",
1513 skb->protocol);
1514 return 1;
1515 }
1516
1517 /* the filter instructions are constructed assuming
1518 * a four-byte PPP header on each packet. we have to
1519 * temporarily remove part of the fake header stuck on
1520 * earlier.
1521 */
1522 *(u8 *)skb_pull(skb, IPPP_MAX_HEADER - 4) = 1; /* indicate outbound */
1523
1524 {
1525 __be16 *p = (__be16 *)skb->data;
1526
1527 p++;
1528 *p = htons(proto);
1529 }
1530
1531 drop |= is->pass_filter
1532 && BPF_PROG_RUN(is->pass_filter, skb) == 0;
1533 drop |= is->active_filter
1534 && BPF_PROG_RUN(is->active_filter, skb) == 0;
1535
1536 skb_push(skb, IPPP_MAX_HEADER - 4);
1537 return drop;
1538}
1539#endif
1540#ifdef CONFIG_ISDN_MPP
1541
1542/* this is _not_ rfc1990 header, but something we convert both short and long
1543 * headers to for convinience's sake:
1544 * byte 0 is flags as in rfc1990
1545 * bytes 1...4 is 24-bit seqence number converted to host byte order
1546 */
1547#define MP_HEADER_LEN 5
1548
1549#define MP_LONGSEQ_MASK 0x00ffffff
1550#define MP_SHORTSEQ_MASK 0x00000fff
1551#define MP_LONGSEQ_MAX MP_LONGSEQ_MASK
1552#define MP_SHORTSEQ_MAX MP_SHORTSEQ_MASK
1553#define MP_LONGSEQ_MAXBIT ((MP_LONGSEQ_MASK + 1) >> 1)
1554#define MP_SHORTSEQ_MAXBIT ((MP_SHORTSEQ_MASK + 1) >> 1)
1555
1556/* sequence-wrap safe comparisons (for long sequence)*/
1557#define MP_LT(a, b) ((a - b) & MP_LONGSEQ_MAXBIT)
1558#define MP_LE(a, b) !((b - a) & MP_LONGSEQ_MAXBIT)
1559#define MP_GT(a, b) ((b - a) & MP_LONGSEQ_MAXBIT)
1560#define MP_GE(a, b) !((a - b) & MP_LONGSEQ_MAXBIT)
1561
1562#define MP_SEQ(f) ((*(u32 *)(f->data + 1)))
1563#define MP_FLAGS(f) (f->data[0])
1564
1565static int isdn_ppp_mp_bundle_array_init(void)
1566{
1567 int i;
1568 int sz = ISDN_MAX_CHANNELS * sizeof(ippp_bundle);
1569 if ((isdn_ppp_bundle_arr = kzalloc(sz, GFP_KERNEL)) == NULL)
1570 return -ENOMEM;
1571 for (i = 0; i < ISDN_MAX_CHANNELS; i++)
1572 spin_lock_init(&isdn_ppp_bundle_arr[i].lock);
1573 return 0;
1574}
1575
1576static ippp_bundle *isdn_ppp_mp_bundle_alloc(void)
1577{
1578 int i;
1579 for (i = 0; i < ISDN_MAX_CHANNELS; i++)
1580 if (isdn_ppp_bundle_arr[i].ref_ct <= 0)
1581 return (isdn_ppp_bundle_arr + i);
1582 return NULL;
1583}
1584
1585static int isdn_ppp_mp_init(isdn_net_local *lp, ippp_bundle *add_to)
1586{
1587 struct ippp_struct *is;
1588
1589 if (lp->ppp_slot < 0) {
1590 printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
1591 __func__, lp->ppp_slot);
1592 return (-EINVAL);
1593 }
1594
1595 is = ippp_table[lp->ppp_slot];
1596 if (add_to) {
1597 if (lp->netdev->pb)
1598 lp->netdev->pb->ref_ct--;
1599 lp->netdev->pb = add_to;
1600 } else { /* first link in a bundle */
1601 is->mp_seqno = 0;
1602 if ((lp->netdev->pb = isdn_ppp_mp_bundle_alloc()) == NULL)
1603 return -ENOMEM;
1604 lp->next = lp->last = lp; /* nobody else in a queue */
1605 lp->netdev->pb->frags = NULL;
1606 lp->netdev->pb->frames = 0;
1607 lp->netdev->pb->seq = UINT_MAX;
1608 }
1609 lp->netdev->pb->ref_ct++;
1610
1611 is->last_link_seqno = 0;
1612 return 0;
1613}
1614
1615static u32 isdn_ppp_mp_get_seq(int short_seq,
1616 struct sk_buff *skb, u32 last_seq);
1617static struct sk_buff *isdn_ppp_mp_discard(ippp_bundle *mp,
1618 struct sk_buff *from, struct sk_buff *to);
1619static void isdn_ppp_mp_reassembly(isdn_net_dev *net_dev, isdn_net_local *lp,
1620 struct sk_buff *from, struct sk_buff *to);
1621static void isdn_ppp_mp_free_skb(ippp_bundle *mp, struct sk_buff *skb);
1622static void isdn_ppp_mp_print_recv_pkt(int slot, struct sk_buff *skb);
1623
1624static void isdn_ppp_mp_receive(isdn_net_dev *net_dev, isdn_net_local *lp,
1625 struct sk_buff *skb)
1626{
1627 struct ippp_struct *is;
1628 isdn_net_local *lpq;
1629 ippp_bundle *mp;
1630 isdn_mppp_stats *stats;
1631 struct sk_buff *newfrag, *frag, *start, *nextf;
1632 u32 newseq, minseq, thisseq;
1633 unsigned long flags;
1634 int slot;
1635
1636 spin_lock_irqsave(&net_dev->pb->lock, flags);
1637 mp = net_dev->pb;
1638 stats = &mp->stats;
1639 slot = lp->ppp_slot;
1640 if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
1641 printk(KERN_ERR "%s: lp->ppp_slot(%d)\n",
1642 __func__, lp->ppp_slot);
1643 stats->frame_drops++;
1644 dev_kfree_skb(skb);
1645 spin_unlock_irqrestore(&mp->lock, flags);
1646 return;
1647 }
1648 is = ippp_table[slot];
1649 if (++mp->frames > stats->max_queue_len)
1650 stats->max_queue_len = mp->frames;
1651
1652 if (is->debug & 0x8)
1653 isdn_ppp_mp_print_recv_pkt(lp->ppp_slot, skb);
1654
1655 newseq = isdn_ppp_mp_get_seq(is->mpppcfg & SC_IN_SHORT_SEQ,
1656 skb, is->last_link_seqno);
1657
1658
1659 /* if this packet seq # is less than last already processed one,
1660 * toss it right away, but check for sequence start case first
1661 */
1662 if (mp->seq > MP_LONGSEQ_MAX && (newseq & MP_LONGSEQ_MAXBIT)) {
1663 mp->seq = newseq; /* the first packet: required for
1664 * rfc1990 non-compliant clients --
1665 * prevents constant packet toss */
1666 } else if (MP_LT(newseq, mp->seq)) {
1667 stats->frame_drops++;
1668 isdn_ppp_mp_free_skb(mp, skb);
1669 spin_unlock_irqrestore(&mp->lock, flags);
1670 return;
1671 }
1672
1673 /* find the minimum received sequence number over all links */
1674 is->last_link_seqno = minseq = newseq;
1675 for (lpq = net_dev->queue;;) {
1676 slot = lpq->ppp_slot;
1677 if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
1678 printk(KERN_ERR "%s: lpq->ppp_slot(%d)\n",
1679 __func__, lpq->ppp_slot);
1680 } else {
1681 u32 lls = ippp_table[slot]->last_link_seqno;
1682 if (MP_LT(lls, minseq))
1683 minseq = lls;
1684 }
1685 if ((lpq = lpq->next) == net_dev->queue)
1686 break;
1687 }
1688 if (MP_LT(minseq, mp->seq))
1689 minseq = mp->seq; /* can't go beyond already processed
1690 * packets */
1691 newfrag = skb;
1692
1693 /* if this new fragment is before the first one, then enqueue it now. */
1694 if ((frag = mp->frags) == NULL || MP_LT(newseq, MP_SEQ(frag))) {
1695 newfrag->next = frag;
1696 mp->frags = frag = newfrag;
1697 newfrag = NULL;
1698 }
1699
1700 start = MP_FLAGS(frag) & MP_BEGIN_FRAG &&
1701 MP_SEQ(frag) == mp->seq ? frag : NULL;
1702
1703 /*
1704 * main fragment traversing loop
1705 *
1706 * try to accomplish several tasks:
1707 * - insert new fragment into the proper sequence slot (once that's done
1708 * newfrag will be set to NULL)
1709 * - reassemble any complete fragment sequence (non-null 'start'
1710 * indicates there is a contiguous sequence present)
1711 * - discard any incomplete sequences that are below minseq -- due
1712 * to the fact that sender always increment sequence number, if there
1713 * is an incomplete sequence below minseq, no new fragments would
1714 * come to complete such sequence and it should be discarded
1715 *
1716 * loop completes when we accomplished the following tasks:
1717 * - new fragment is inserted in the proper sequence ('newfrag' is
1718 * set to NULL)
1719 * - we hit a gap in the sequence, so no reassembly/processing is
1720 * possible ('start' would be set to NULL)
1721 *
1722 * algorithm for this code is derived from code in the book
1723 * 'PPP Design And Debugging' by James Carlson (Addison-Wesley)
1724 */
1725 while (start != NULL || newfrag != NULL) {
1726
1727 thisseq = MP_SEQ(frag);
1728 nextf = frag->next;
1729
1730 /* drop any duplicate fragments */
1731 if (newfrag != NULL && thisseq == newseq) {
1732 isdn_ppp_mp_free_skb(mp, newfrag);
1733 newfrag = NULL;
1734 }
1735
1736 /* insert new fragment before next element if possible. */
1737 if (newfrag != NULL && (nextf == NULL ||
1738 MP_LT(newseq, MP_SEQ(nextf)))) {
1739 newfrag->next = nextf;
1740 frag->next = nextf = newfrag;
1741 newfrag = NULL;
1742 }
1743
1744 if (start != NULL) {
1745 /* check for misplaced start */
1746 if (start != frag && (MP_FLAGS(frag) & MP_BEGIN_FRAG)) {
1747 printk(KERN_WARNING"isdn_mppp(seq %d): new "
1748 "BEGIN flag with no prior END", thisseq);
1749 stats->seqerrs++;
1750 stats->frame_drops++;
1751 start = isdn_ppp_mp_discard(mp, start, frag);
1752 nextf = frag->next;
1753 }
1754 } else if (MP_LE(thisseq, minseq)) {
1755 if (MP_FLAGS(frag) & MP_BEGIN_FRAG)
1756 start = frag;
1757 else {
1758 if (MP_FLAGS(frag) & MP_END_FRAG)
1759 stats->frame_drops++;
1760 if (mp->frags == frag)
1761 mp->frags = nextf;
1762 isdn_ppp_mp_free_skb(mp, frag);
1763 frag = nextf;
1764 continue;
1765 }
1766 }
1767
1768 /* if start is non-null and we have end fragment, then
1769 * we have full reassembly sequence -- reassemble
1770 * and process packet now
1771 */
1772 if (start != NULL && (MP_FLAGS(frag) & MP_END_FRAG)) {
1773 minseq = mp->seq = (thisseq + 1) & MP_LONGSEQ_MASK;
1774 /* Reassemble the packet then dispatch it */
1775 isdn_ppp_mp_reassembly(net_dev, lp, start, nextf);
1776
1777 start = NULL;
1778 frag = NULL;
1779
1780 mp->frags = nextf;
1781 }
1782
1783 /* check if need to update start pointer: if we just
1784 * reassembled the packet and sequence is contiguous
1785 * then next fragment should be the start of new reassembly
1786 * if sequence is contiguous, but we haven't reassembled yet,
1787 * keep going.
1788 * if sequence is not contiguous, either clear everything
1789 * below low watermark and set start to the next frag or
1790 * clear start ptr.
1791 */
1792 if (nextf != NULL &&
1793 ((thisseq + 1) & MP_LONGSEQ_MASK) == MP_SEQ(nextf)) {
1794 /* if we just reassembled and the next one is here,
1795 * then start another reassembly. */
1796
1797 if (frag == NULL) {
1798 if (MP_FLAGS(nextf) & MP_BEGIN_FRAG)
1799 start = nextf;
1800 else
1801 {
1802 printk(KERN_WARNING"isdn_mppp(seq %d):"
1803 " END flag with no following "
1804 "BEGIN", thisseq);
1805 stats->seqerrs++;
1806 }
1807 }
1808
1809 } else {
1810 if (nextf != NULL && frag != NULL &&
1811 MP_LT(thisseq, minseq)) {
1812 /* we've got a break in the sequence
1813 * and we not at the end yet
1814 * and we did not just reassembled
1815 *(if we did, there wouldn't be anything before)
1816 * and we below the low watermark
1817 * discard all the frames below low watermark
1818 * and start over */
1819 stats->frame_drops++;
1820 mp->frags = isdn_ppp_mp_discard(mp, start, nextf);
1821 }
1822 /* break in the sequence, no reassembly */
1823 start = NULL;
1824 }
1825
1826 frag = nextf;
1827 } /* while -- main loop */
1828
1829 if (mp->frags == NULL)
1830 mp->frags = frag;
1831
1832 /* rather straighforward way to deal with (not very) possible
1833 * queue overflow */
1834 if (mp->frames > MP_MAX_QUEUE_LEN) {
1835 stats->overflows++;
1836 while (mp->frames > MP_MAX_QUEUE_LEN) {
1837 frag = mp->frags->next;
1838 isdn_ppp_mp_free_skb(mp, mp->frags);
1839 mp->frags = frag;
1840 }
1841 }
1842 spin_unlock_irqrestore(&mp->lock, flags);
1843}
1844
1845static void isdn_ppp_mp_cleanup(isdn_net_local *lp)
1846{
1847 struct sk_buff *frag = lp->netdev->pb->frags;
1848 struct sk_buff *nextfrag;
1849 while (frag) {
1850 nextfrag = frag->next;
1851 isdn_ppp_mp_free_skb(lp->netdev->pb, frag);
1852 frag = nextfrag;
1853 }
1854 lp->netdev->pb->frags = NULL;
1855}
1856
1857static u32 isdn_ppp_mp_get_seq(int short_seq,
1858 struct sk_buff *skb, u32 last_seq)
1859{
1860 u32 seq;
1861 int flags = skb->data[0] & (MP_BEGIN_FRAG | MP_END_FRAG);
1862
1863 if (!short_seq)
1864 {
1865 seq = ntohl(*(__be32 *)skb->data) & MP_LONGSEQ_MASK;
1866 skb_push(skb, 1);
1867 }
1868 else
1869 {
1870 /* convert 12-bit short seq number to 24-bit long one
1871 */
1872 seq = ntohs(*(__be16 *)skb->data) & MP_SHORTSEQ_MASK;
1873
1874 /* check for seqence wrap */
1875 if (!(seq & MP_SHORTSEQ_MAXBIT) &&
1876 (last_seq & MP_SHORTSEQ_MAXBIT) &&
1877 (unsigned long)last_seq <= MP_LONGSEQ_MAX)
1878 seq |= (last_seq + MP_SHORTSEQ_MAX + 1) &
1879 (~MP_SHORTSEQ_MASK & MP_LONGSEQ_MASK);
1880 else
1881 seq |= last_seq & (~MP_SHORTSEQ_MASK & MP_LONGSEQ_MASK);
1882
1883 skb_push(skb, 3); /* put converted seqence back in skb */
1884 }
1885 *(u32 *)(skb->data + 1) = seq; /* put seqence back in _host_ byte
1886 * order */
1887 skb->data[0] = flags; /* restore flags */
1888 return seq;
1889}
1890
1891static struct sk_buff *isdn_ppp_mp_discard(ippp_bundle *mp,
1892 struct sk_buff *from,
1893 struct sk_buff *to)
1894{
1895 if (from)
1896 while (from != to) {
1897 struct sk_buff *next = from->next;
1898 isdn_ppp_mp_free_skb(mp, from);
1899 from = next;
1900 }
1901 return from;
1902}
1903
1904static void isdn_ppp_mp_reassembly(isdn_net_dev *net_dev, isdn_net_local *lp,
1905 struct sk_buff *from, struct sk_buff *to)
1906{
1907 ippp_bundle *mp = net_dev->pb;
1908 int proto;
1909 struct sk_buff *skb;
1910 unsigned int tot_len;
1911
1912 if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) {
1913 printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
1914 __func__, lp->ppp_slot);
1915 return;
1916 }
1917 if (MP_FLAGS(from) == (MP_BEGIN_FRAG | MP_END_FRAG)) {
1918 if (ippp_table[lp->ppp_slot]->debug & 0x40)
1919 printk(KERN_DEBUG "isdn_mppp: reassembly: frame %d, "
1920 "len %d\n", MP_SEQ(from), from->len);
1921 skb = from;
1922 skb_pull(skb, MP_HEADER_LEN);
1923 mp->frames--;
1924 } else {
1925 struct sk_buff *frag;
1926 int n;
1927
1928 for (tot_len = n = 0, frag = from; frag != to; frag = frag->next, n++)
1929 tot_len += frag->len - MP_HEADER_LEN;
1930
1931 if (ippp_table[lp->ppp_slot]->debug & 0x40)
1932 printk(KERN_DEBUG"isdn_mppp: reassembling frames %d "
1933 "to %d, len %d\n", MP_SEQ(from),
1934 (MP_SEQ(from) + n - 1) & MP_LONGSEQ_MASK, tot_len);
1935 if ((skb = dev_alloc_skb(tot_len)) == NULL) {
1936 printk(KERN_ERR "isdn_mppp: cannot allocate sk buff "
1937 "of size %d\n", tot_len);
1938 isdn_ppp_mp_discard(mp, from, to);
1939 return;
1940 }
1941
1942 while (from != to) {
1943 unsigned int len = from->len - MP_HEADER_LEN;
1944
1945 skb_copy_from_linear_data_offset(from, MP_HEADER_LEN,
1946 skb_put(skb, len),
1947 len);
1948 frag = from->next;
1949 isdn_ppp_mp_free_skb(mp, from);
1950 from = frag;
1951 }
1952 }
1953 proto = isdn_ppp_strip_proto(skb);
1954 isdn_ppp_push_higher(net_dev, lp, skb, proto);
1955}
1956
1957static void isdn_ppp_mp_free_skb(ippp_bundle *mp, struct sk_buff *skb)
1958{
1959 dev_kfree_skb(skb);
1960 mp->frames--;
1961}
1962
1963static void isdn_ppp_mp_print_recv_pkt(int slot, struct sk_buff *skb)
1964{
1965 printk(KERN_DEBUG "mp_recv: %d/%d -> %02x %02x %02x %02x %02x %02x\n",
1966 slot, (int) skb->len,
1967 (int) skb->data[0], (int) skb->data[1], (int) skb->data[2],
1968 (int) skb->data[3], (int) skb->data[4], (int) skb->data[5]);
1969}
1970
1971static int
1972isdn_ppp_bundle(struct ippp_struct *is, int unit)
1973{
1974 char ifn[IFNAMSIZ + 1];
1975 isdn_net_dev *p;
1976 isdn_net_local *lp, *nlp;
1977 int rc;
1978 unsigned long flags;
1979
1980 sprintf(ifn, "ippp%d", unit);
1981 p = isdn_net_findif(ifn);
1982 if (!p) {
1983 printk(KERN_ERR "ippp_bundle: cannot find %s\n", ifn);
1984 return -EINVAL;
1985 }
1986
1987 spin_lock_irqsave(&p->pb->lock, flags);
1988
1989 nlp = is->lp;
1990 lp = p->queue;
1991 if (nlp->ppp_slot < 0 || nlp->ppp_slot >= ISDN_MAX_CHANNELS ||
1992 lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) {
1993 printk(KERN_ERR "ippp_bundle: binding to invalid slot %d\n",
1994 nlp->ppp_slot < 0 || nlp->ppp_slot >= ISDN_MAX_CHANNELS ?
1995 nlp->ppp_slot : lp->ppp_slot);
1996 rc = -EINVAL;
1997 goto out;
1998 }
1999
2000 isdn_net_add_to_bundle(p, nlp);
2001
2002 ippp_table[nlp->ppp_slot]->unit = ippp_table[lp->ppp_slot]->unit;
2003
2004 /* maybe also SC_CCP stuff */
2005 ippp_table[nlp->ppp_slot]->pppcfg |= ippp_table[lp->ppp_slot]->pppcfg &
2006 (SC_ENABLE_IP | SC_NO_TCP_CCID | SC_REJ_COMP_TCP);
2007 ippp_table[nlp->ppp_slot]->mpppcfg |= ippp_table[lp->ppp_slot]->mpppcfg &
2008 (SC_MP_PROT | SC_REJ_MP_PROT | SC_OUT_SHORT_SEQ | SC_IN_SHORT_SEQ);
2009 rc = isdn_ppp_mp_init(nlp, p->pb);
2010out:
2011 spin_unlock_irqrestore(&p->pb->lock, flags);
2012 return rc;
2013}
2014
2015#endif /* CONFIG_ISDN_MPP */
2016
2017/*
2018 * network device ioctl handlers
2019 */
2020
2021static int
2022isdn_ppp_dev_ioctl_stats(int slot, struct ifreq *ifr, struct net_device *dev)
2023{
2024 struct ppp_stats __user *res = ifr->ifr_data;
2025 struct ppp_stats t;
2026 isdn_net_local *lp = netdev_priv(dev);
2027
2028 /* build a temporary stat struct and copy it to user space */
2029
2030 memset(&t, 0, sizeof(struct ppp_stats));
2031 if (dev->flags & IFF_UP) {
2032 t.p.ppp_ipackets = lp->stats.rx_packets;
2033 t.p.ppp_ibytes = lp->stats.rx_bytes;
2034 t.p.ppp_ierrors = lp->stats.rx_errors;
2035 t.p.ppp_opackets = lp->stats.tx_packets;
2036 t.p.ppp_obytes = lp->stats.tx_bytes;
2037 t.p.ppp_oerrors = lp->stats.tx_errors;
2038#ifdef CONFIG_ISDN_PPP_VJ
2039 if (slot >= 0 && ippp_table[slot]->slcomp) {
2040 struct slcompress *slcomp = ippp_table[slot]->slcomp;
2041 t.vj.vjs_packets = slcomp->sls_o_compressed + slcomp->sls_o_uncompressed;
2042 t.vj.vjs_compressed = slcomp->sls_o_compressed;
2043 t.vj.vjs_searches = slcomp->sls_o_searches;
2044 t.vj.vjs_misses = slcomp->sls_o_misses;
2045 t.vj.vjs_errorin = slcomp->sls_i_error;
2046 t.vj.vjs_tossed = slcomp->sls_i_tossed;
2047 t.vj.vjs_uncompressedin = slcomp->sls_i_uncompressed;
2048 t.vj.vjs_compressedin = slcomp->sls_i_compressed;
2049 }
2050#endif
2051 }
2052 if (copy_to_user(res, &t, sizeof(struct ppp_stats)))
2053 return -EFAULT;
2054 return 0;
2055}
2056
2057int
2058isdn_ppp_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
2059{
2060 int error = 0;
2061 int len;
2062 isdn_net_local *lp = netdev_priv(dev);
2063
2064
2065 if (lp->p_encap != ISDN_NET_ENCAP_SYNCPPP)
2066 return -EINVAL;
2067
2068 switch (cmd) {
2069#define PPP_VERSION "2.3.7"
2070 case SIOCGPPPVER:
2071 len = strlen(PPP_VERSION) + 1;
2072 if (copy_to_user(ifr->ifr_data, PPP_VERSION, len))
2073 error = -EFAULT;
2074 break;
2075
2076 case SIOCGPPPSTATS:
2077 error = isdn_ppp_dev_ioctl_stats(lp->ppp_slot, ifr, dev);
2078 break;
2079 default:
2080 error = -EINVAL;
2081 break;
2082 }
2083 return error;
2084}
2085
2086static int
2087isdn_ppp_if_get_unit(char *name)
2088{
2089 int len,
2090 i,
2091 unit = 0,
2092 deci;
2093
2094 len = strlen(name);
2095
2096 if (strncmp("ippp", name, 4) || len > 8)
2097 return -1;
2098
2099 for (i = 0, deci = 1; i < len; i++, deci *= 10) {
2100 char a = name[len - i - 1];
2101 if (a >= '0' && a <= '9')
2102 unit += (a - '0') * deci;
2103 else
2104 break;
2105 }
2106 if (!i || len - i != 4)
2107 unit = -1;
2108
2109 return unit;
2110}
2111
2112
2113int
2114isdn_ppp_dial_slave(char *name)
2115{
2116#ifdef CONFIG_ISDN_MPP
2117 isdn_net_dev *ndev;
2118 isdn_net_local *lp;
2119 struct net_device *sdev;
2120
2121 if (!(ndev = isdn_net_findif(name)))
2122 return 1;
2123 lp = ndev->local;
2124 if (!(lp->flags & ISDN_NET_CONNECTED))
2125 return 5;
2126
2127 sdev = lp->slave;
2128 while (sdev) {
2129 isdn_net_local *mlp = netdev_priv(sdev);
2130 if (!(mlp->flags & ISDN_NET_CONNECTED))
2131 break;
2132 sdev = mlp->slave;
2133 }
2134 if (!sdev)
2135 return 2;
2136
2137 isdn_net_dial_req(netdev_priv(sdev));
2138 return 0;
2139#else
2140 return -1;
2141#endif
2142}
2143
2144int
2145isdn_ppp_hangup_slave(char *name)
2146{
2147#ifdef CONFIG_ISDN_MPP
2148 isdn_net_dev *ndev;
2149 isdn_net_local *lp;
2150 struct net_device *sdev;
2151
2152 if (!(ndev = isdn_net_findif(name)))
2153 return 1;
2154 lp = ndev->local;
2155 if (!(lp->flags & ISDN_NET_CONNECTED))
2156 return 5;
2157
2158 sdev = lp->slave;
2159 while (sdev) {
2160 isdn_net_local *mlp = netdev_priv(sdev);
2161
2162 if (mlp->slave) { /* find last connected link in chain */
2163 isdn_net_local *nlp = ISDN_SLAVE_PRIV(mlp);
2164
2165 if (!(nlp->flags & ISDN_NET_CONNECTED))
2166 break;
2167 } else if (mlp->flags & ISDN_NET_CONNECTED)
2168 break;
2169
2170 sdev = mlp->slave;
2171 }
2172 if (!sdev)
2173 return 2;
2174
2175 isdn_net_hangup(sdev);
2176 return 0;
2177#else
2178 return -1;
2179#endif
2180}
2181
2182/*
2183 * PPP compression stuff
2184 */
2185
2186
2187/* Push an empty CCP Data Frame up to the daemon to wake it up and let it
2188 generate a CCP Reset-Request or tear down CCP altogether */
2189
2190static void isdn_ppp_ccp_kickup(struct ippp_struct *is)
2191{
2192 isdn_ppp_fill_rq(NULL, 0, PPP_COMP, is->lp->ppp_slot);
2193}
2194
2195/* In-kernel handling of CCP Reset-Request and Reset-Ack is necessary,
2196 but absolutely nontrivial. The most abstruse problem we are facing is
2197 that the generation, reception and all the handling of timeouts and
2198 resends including proper request id management should be entirely left
2199 to the (de)compressor, but indeed is not covered by the current API to
2200 the (de)compressor. The API is a prototype version from PPP where only
2201 some (de)compressors have yet been implemented and all of them are
2202 rather simple in their reset handling. Especially, their is only one
2203 outstanding ResetAck at a time with all of them and ResetReq/-Acks do
2204 not have parameters. For this very special case it was sufficient to
2205 just return an error code from the decompressor and have a single
2206 reset() entry to communicate all the necessary information between
2207 the framework and the (de)compressor. Bad enough, LZS is different
2208 (and any other compressor may be different, too). It has multiple
2209 histories (eventually) and needs to Reset each of them independently
2210 and thus uses multiple outstanding Acks and history numbers as an
2211 additional parameter to Reqs/Acks.
2212 All that makes it harder to port the reset state engine into the
2213 kernel because it is not just the same simple one as in (i)pppd but
2214 it must be able to pass additional parameters and have multiple out-
2215 standing Acks. We are trying to achieve the impossible by handling
2216 reset transactions independent by their id. The id MUST change when
2217 the data portion changes, thus any (de)compressor who uses more than
2218 one resettable state must provide and recognize individual ids for
2219 each individual reset transaction. The framework itself does _only_
2220 differentiate them by id, because it has no other semantics like the
2221 (de)compressor might.
2222 This looks like a major redesign of the interface would be nice,
2223 but I don't have an idea how to do it better. */
2224
2225/* Send a CCP Reset-Request or Reset-Ack directly from the kernel. This is
2226 getting that lengthy because there is no simple "send-this-frame-out"
2227 function above but every wrapper does a bit different. Hope I guess
2228 correct in this hack... */
2229
2230static void isdn_ppp_ccp_xmit_reset(struct ippp_struct *is, int proto,
2231 unsigned char code, unsigned char id,
2232 unsigned char *data, int len)
2233{
2234 struct sk_buff *skb;
2235 unsigned char *p;
2236 int hl;
2237 int cnt = 0;
2238 isdn_net_local *lp = is->lp;
2239
2240 /* Alloc large enough skb */
2241 hl = dev->drv[lp->isdn_device]->interface->hl_hdrlen;
2242 skb = alloc_skb(len + hl + 16, GFP_ATOMIC);
2243 if (!skb) {
2244 printk(KERN_WARNING
2245 "ippp: CCP cannot send reset - out of memory\n");
2246 return;
2247 }
2248 skb_reserve(skb, hl);
2249
2250 /* We may need to stuff an address and control field first */
2251 if (!(is->pppcfg & SC_COMP_AC)) {
2252 p = skb_put(skb, 2);
2253 *p++ = 0xff;
2254 *p++ = 0x03;
2255 }
2256
2257 /* Stuff proto, code, id and length */
2258 p = skb_put(skb, 6);
2259 *p++ = (proto >> 8);
2260 *p++ = (proto & 0xff);
2261 *p++ = code;
2262 *p++ = id;
2263 cnt = 4 + len;
2264 *p++ = (cnt >> 8);
2265 *p++ = (cnt & 0xff);
2266
2267 /* Now stuff remaining bytes */
2268 if (len) {
2269 skb_put_data(skb, data, len);
2270 }
2271
2272 /* skb is now ready for xmit */
2273 printk(KERN_DEBUG "Sending CCP Frame:\n");
2274 isdn_ppp_frame_log("ccp-xmit", skb->data, skb->len, 32, is->unit, lp->ppp_slot);
2275
2276 isdn_net_write_super(lp, skb);
2277}
2278
2279/* Allocate the reset state vector */
2280static struct ippp_ccp_reset *isdn_ppp_ccp_reset_alloc(struct ippp_struct *is)
2281{
2282 struct ippp_ccp_reset *r;
2283 r = kzalloc(sizeof(struct ippp_ccp_reset), GFP_KERNEL);
2284 if (!r) {
2285 printk(KERN_ERR "ippp_ccp: failed to allocate reset data"
2286 " structure - no mem\n");
2287 return NULL;
2288 }
2289 printk(KERN_DEBUG "ippp_ccp: allocated reset data structure %p\n", r);
2290 is->reset = r;
2291 return r;
2292}
2293
2294/* Destroy the reset state vector. Kill all pending timers first. */
2295static void isdn_ppp_ccp_reset_free(struct ippp_struct *is)
2296{
2297 unsigned int id;
2298
2299 printk(KERN_DEBUG "ippp_ccp: freeing reset data structure %p\n",
2300 is->reset);
2301 for (id = 0; id < 256; id++) {
2302 if (is->reset->rs[id]) {
2303 isdn_ppp_ccp_reset_free_state(is, (unsigned char)id);
2304 }
2305 }
2306 kfree(is->reset);
2307 is->reset = NULL;
2308}
2309
2310/* Free a given state and clear everything up for later reallocation */
2311static void isdn_ppp_ccp_reset_free_state(struct ippp_struct *is,
2312 unsigned char id)
2313{
2314 struct ippp_ccp_reset_state *rs;
2315
2316 if (is->reset->rs[id]) {
2317 printk(KERN_DEBUG "ippp_ccp: freeing state for id %d\n", id);
2318 rs = is->reset->rs[id];
2319 /* Make sure the kernel will not call back later */
2320 if (rs->ta)
2321 del_timer(&rs->timer);
2322 is->reset->rs[id] = NULL;
2323 kfree(rs);
2324 } else {
2325 printk(KERN_WARNING "ippp_ccp: id %d is not allocated\n", id);
2326 }
2327}
2328
2329/* The timer callback function which is called when a ResetReq has timed out,
2330 aka has never been answered by a ResetAck */
2331static void isdn_ppp_ccp_timer_callback(struct timer_list *t)
2332{
2333 struct ippp_ccp_reset_state *rs =
2334 from_timer(rs, t, timer);
2335
2336 if (!rs) {
2337 printk(KERN_ERR "ippp_ccp: timer cb with zero closure.\n");
2338 return;
2339 }
2340 if (rs->ta && rs->state == CCPResetSentReq) {
2341 /* We are correct here */
2342 if (!rs->expra) {
2343 /* Hmm, there is no Ack really expected. We can clean
2344 up the state now, it will be reallocated if the
2345 decompressor insists on another reset */
2346 rs->ta = 0;
2347 isdn_ppp_ccp_reset_free_state(rs->is, rs->id);
2348 return;
2349 }
2350 printk(KERN_DEBUG "ippp_ccp: CCP Reset timed out for id %d\n",
2351 rs->id);
2352 /* Push it again */
2353 isdn_ppp_ccp_xmit_reset(rs->is, PPP_CCP, CCP_RESETREQ, rs->id,
2354 rs->data, rs->dlen);
2355 /* Restart timer */
2356 rs->timer.expires = jiffies + HZ * 5;
2357 add_timer(&rs->timer);
2358 } else {
2359 printk(KERN_WARNING "ippp_ccp: timer cb in wrong state %d\n",
2360 rs->state);
2361 }
2362}
2363
2364/* Allocate a new reset transaction state */
2365static struct ippp_ccp_reset_state *isdn_ppp_ccp_reset_alloc_state(struct ippp_struct *is,
2366 unsigned char id)
2367{
2368 struct ippp_ccp_reset_state *rs;
2369 if (is->reset->rs[id]) {
2370 printk(KERN_WARNING "ippp_ccp: old state exists for id %d\n",
2371 id);
2372 return NULL;
2373 } else {
2374 rs = kzalloc(sizeof(struct ippp_ccp_reset_state), GFP_ATOMIC);
2375 if (!rs)
2376 return NULL;
2377 rs->state = CCPResetIdle;
2378 rs->is = is;
2379 rs->id = id;
2380 timer_setup(&rs->timer, isdn_ppp_ccp_timer_callback, 0);
2381 is->reset->rs[id] = rs;
2382 }
2383 return rs;
2384}
2385
2386
2387/* A decompressor wants a reset with a set of parameters - do what is
2388 necessary to fulfill it */
2389static void isdn_ppp_ccp_reset_trans(struct ippp_struct *is,
2390 struct isdn_ppp_resetparams *rp)
2391{
2392 struct ippp_ccp_reset_state *rs;
2393
2394 if (rp->valid) {
2395 /* The decompressor defines parameters by itself */
2396 if (rp->rsend) {
2397 /* And he wants us to send a request */
2398 if (!(rp->idval)) {
2399 printk(KERN_ERR "ippp_ccp: decompressor must"
2400 " specify reset id\n");
2401 return;
2402 }
2403 if (is->reset->rs[rp->id]) {
2404 /* There is already a transaction in existence
2405 for this id. May be still waiting for a
2406 Ack or may be wrong. */
2407 rs = is->reset->rs[rp->id];
2408 if (rs->state == CCPResetSentReq && rs->ta) {
2409 printk(KERN_DEBUG "ippp_ccp: reset"
2410 " trans still in progress"
2411 " for id %d\n", rp->id);
2412 } else {
2413 printk(KERN_WARNING "ippp_ccp: reset"
2414 " trans in wrong state %d for"
2415 " id %d\n", rs->state, rp->id);
2416 }
2417 } else {
2418 /* Ok, this is a new transaction */
2419 printk(KERN_DEBUG "ippp_ccp: new trans for id"
2420 " %d to be started\n", rp->id);
2421 rs = isdn_ppp_ccp_reset_alloc_state(is, rp->id);
2422 if (!rs) {
2423 printk(KERN_ERR "ippp_ccp: out of mem"
2424 " allocing ccp trans\n");
2425 return;
2426 }
2427 rs->state = CCPResetSentReq;
2428 rs->expra = rp->expra;
2429 if (rp->dtval) {
2430 rs->dlen = rp->dlen;
2431 memcpy(rs->data, rp->data, rp->dlen);
2432 }
2433 /* HACK TODO - add link comp here */
2434 isdn_ppp_ccp_xmit_reset(is, PPP_CCP,
2435 CCP_RESETREQ, rs->id,
2436 rs->data, rs->dlen);
2437 /* Start the timer */
2438 rs->timer.expires = jiffies + 5 * HZ;
2439 add_timer(&rs->timer);
2440 rs->ta = 1;
2441 }
2442 } else {
2443 printk(KERN_DEBUG "ippp_ccp: no reset sent\n");
2444 }
2445 } else {
2446 /* The reset params are invalid. The decompressor does not
2447 care about them, so we just send the minimal requests
2448 and increase ids only when an Ack is received for a
2449 given id */
2450 if (is->reset->rs[is->reset->lastid]) {
2451 /* There is already a transaction in existence
2452 for this id. May be still waiting for a
2453 Ack or may be wrong. */
2454 rs = is->reset->rs[is->reset->lastid];
2455 if (rs->state == CCPResetSentReq && rs->ta) {
2456 printk(KERN_DEBUG "ippp_ccp: reset"
2457 " trans still in progress"
2458 " for id %d\n", rp->id);
2459 } else {
2460 printk(KERN_WARNING "ippp_ccp: reset"
2461 " trans in wrong state %d for"
2462 " id %d\n", rs->state, rp->id);
2463 }
2464 } else {
2465 printk(KERN_DEBUG "ippp_ccp: new trans for id"
2466 " %d to be started\n", is->reset->lastid);
2467 rs = isdn_ppp_ccp_reset_alloc_state(is,
2468 is->reset->lastid);
2469 if (!rs) {
2470 printk(KERN_ERR "ippp_ccp: out of mem"
2471 " allocing ccp trans\n");
2472 return;
2473 }
2474 rs->state = CCPResetSentReq;
2475 /* We always expect an Ack if the decompressor doesn't
2476 know better */
2477 rs->expra = 1;
2478 rs->dlen = 0;
2479 /* HACK TODO - add link comp here */
2480 isdn_ppp_ccp_xmit_reset(is, PPP_CCP, CCP_RESETREQ,
2481 rs->id, NULL, 0);
2482 /* Start the timer */
2483 rs->timer.expires = jiffies + 5 * HZ;
2484 add_timer(&rs->timer);
2485 rs->ta = 1;
2486 }
2487 }
2488}
2489
2490/* An Ack was received for this id. This means we stop the timer and clean
2491 up the state prior to calling the decompressors reset routine. */
2492static void isdn_ppp_ccp_reset_ack_rcvd(struct ippp_struct *is,
2493 unsigned char id)
2494{
2495 struct ippp_ccp_reset_state *rs = is->reset->rs[id];
2496
2497 if (rs) {
2498 if (rs->ta && rs->state == CCPResetSentReq) {
2499 /* Great, we are correct */
2500 if (!rs->expra)
2501 printk(KERN_DEBUG "ippp_ccp: ResetAck received"
2502 " for id %d but not expected\n", id);
2503 } else {
2504 printk(KERN_INFO "ippp_ccp: ResetAck received out of"
2505 "sync for id %d\n", id);
2506 }
2507 if (rs->ta) {
2508 rs->ta = 0;
2509 del_timer(&rs->timer);
2510 }
2511 isdn_ppp_ccp_reset_free_state(is, id);
2512 } else {
2513 printk(KERN_INFO "ippp_ccp: ResetAck received for unknown id"
2514 " %d\n", id);
2515 }
2516 /* Make sure the simple reset stuff uses a new id next time */
2517 is->reset->lastid++;
2518}
2519
2520/*
2521 * decompress packet
2522 *
2523 * if master = 0, we're trying to uncompress an per-link compressed packet,
2524 * as opposed to an compressed reconstructed-from-MPPP packet.
2525 * proto is updated to protocol field of uncompressed packet.
2526 *
2527 * retval: decompressed packet,
2528 * same packet if uncompressed,
2529 * NULL if decompression error
2530 */
2531
2532static struct sk_buff *isdn_ppp_decompress(struct sk_buff *skb, struct ippp_struct *is, struct ippp_struct *master,
2533 int *proto)
2534{
2535 void *stat = NULL;
2536 struct isdn_ppp_compressor *ipc = NULL;
2537 struct sk_buff *skb_out;
2538 int len;
2539 struct ippp_struct *ri;
2540 struct isdn_ppp_resetparams rsparm;
2541 unsigned char rsdata[IPPP_RESET_MAXDATABYTES];
2542
2543 if (!master) {
2544 // per-link decompression
2545 stat = is->link_decomp_stat;
2546 ipc = is->link_decompressor;
2547 ri = is;
2548 } else {
2549 stat = master->decomp_stat;
2550 ipc = master->decompressor;
2551 ri = master;
2552 }
2553
2554 if (!ipc) {
2555 // no decompressor -> we can't decompress.
2556 printk(KERN_DEBUG "ippp: no decompressor defined!\n");
2557 return skb;
2558 }
2559 BUG_ON(!stat); // if we have a compressor, stat has been set as well
2560
2561 if ((master && *proto == PPP_COMP) || (!master && *proto == PPP_COMPFRAG)) {
2562 // compressed packets are compressed by their protocol type
2563
2564 // Set up reset params for the decompressor
2565 memset(&rsparm, 0, sizeof(rsparm));
2566 rsparm.data = rsdata;
2567 rsparm.maxdlen = IPPP_RESET_MAXDATABYTES;
2568
2569 skb_out = dev_alloc_skb(is->mru + PPP_HDRLEN);
2570 if (!skb_out) {
2571 kfree_skb(skb);
2572 printk(KERN_ERR "ippp: decomp memory allocation failure\n");
2573 return NULL;
2574 }
2575 len = ipc->decompress(stat, skb, skb_out, &rsparm);
2576 kfree_skb(skb);
2577 if (len <= 0) {
2578 switch (len) {
2579 case DECOMP_ERROR:
2580 printk(KERN_INFO "ippp: decomp wants reset %s params\n",
2581 rsparm.valid ? "with" : "without");
2582
2583 isdn_ppp_ccp_reset_trans(ri, &rsparm);
2584 break;
2585 case DECOMP_FATALERROR:
2586 ri->pppcfg |= SC_DC_FERROR;
2587 /* Kick ipppd to recognize the error */
2588 isdn_ppp_ccp_kickup(ri);
2589 break;
2590 }
2591 kfree_skb(skb_out);
2592 return NULL;
2593 }
2594 *proto = isdn_ppp_strip_proto(skb_out);
2595 if (*proto < 0) {
2596 kfree_skb(skb_out);
2597 return NULL;
2598 }
2599 return skb_out;
2600 } else {
2601 // uncompressed packets are fed through the decompressor to
2602 // update the decompressor state
2603 ipc->incomp(stat, skb, *proto);
2604 return skb;
2605 }
2606}
2607
2608/*
2609 * compress a frame
2610 * type=0: normal/bundle compression
2611 * =1: link compression
2612 * returns original skb if we haven't compressed the frame
2613 * and a new skb pointer if we've done it
2614 */
2615static struct sk_buff *isdn_ppp_compress(struct sk_buff *skb_in, int *proto,
2616 struct ippp_struct *is, struct ippp_struct *master, int type)
2617{
2618 int ret;
2619 int new_proto;
2620 struct isdn_ppp_compressor *compressor;
2621 void *stat;
2622 struct sk_buff *skb_out;
2623
2624 /* we do not compress control protocols */
2625 if (*proto < 0 || *proto > 0x3fff) {
2626 return skb_in;
2627 }
2628
2629 if (type) { /* type=1 => Link compression */
2630 return skb_in;
2631 }
2632 else {
2633 if (!master) {
2634 compressor = is->compressor;
2635 stat = is->comp_stat;
2636 }
2637 else {
2638 compressor = master->compressor;
2639 stat = master->comp_stat;
2640 }
2641 new_proto = PPP_COMP;
2642 }
2643
2644 if (!compressor) {
2645 printk(KERN_ERR "isdn_ppp: No compressor set!\n");
2646 return skb_in;
2647 }
2648 if (!stat) {
2649 printk(KERN_ERR "isdn_ppp: Compressor not initialized?\n");
2650 return skb_in;
2651 }
2652
2653 /* Allow for at least 150 % expansion (for now) */
2654 skb_out = alloc_skb(skb_in->len + skb_in->len / 2 + 32 +
2655 skb_headroom(skb_in), GFP_ATOMIC);
2656 if (!skb_out)
2657 return skb_in;
2658 skb_reserve(skb_out, skb_headroom(skb_in));
2659
2660 ret = (compressor->compress)(stat, skb_in, skb_out, *proto);
2661 if (!ret) {
2662 dev_kfree_skb(skb_out);
2663 return skb_in;
2664 }
2665
2666 dev_kfree_skb(skb_in);
2667 *proto = new_proto;
2668 return skb_out;
2669}
2670
2671/*
2672 * we received a CCP frame ..
2673 * not a clean solution, but we MUST handle a few cases in the kernel
2674 */
2675static void isdn_ppp_receive_ccp(isdn_net_dev *net_dev, isdn_net_local *lp,
2676 struct sk_buff *skb, int proto)
2677{
2678 struct ippp_struct *is;
2679 struct ippp_struct *mis;
2680 int len;
2681 struct isdn_ppp_resetparams rsparm;
2682 unsigned char rsdata[IPPP_RESET_MAXDATABYTES];
2683
2684 printk(KERN_DEBUG "Received CCP frame from peer slot(%d)\n",
2685 lp->ppp_slot);
2686 if (lp->ppp_slot < 0 || lp->ppp_slot >= ISDN_MAX_CHANNELS) {
2687 printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
2688 __func__, lp->ppp_slot);
2689 return;
2690 }
2691 is = ippp_table[lp->ppp_slot];
2692 isdn_ppp_frame_log("ccp-rcv", skb->data, skb->len, 32, is->unit, lp->ppp_slot);
2693
2694 if (lp->master) {
2695 int slot = ISDN_MASTER_PRIV(lp)->ppp_slot;
2696 if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
2697 printk(KERN_ERR "%s: slot(%d) out of range\n",
2698 __func__, slot);
2699 return;
2700 }
2701 mis = ippp_table[slot];
2702 } else
2703 mis = is;
2704
2705 switch (skb->data[0]) {
2706 case CCP_CONFREQ:
2707 if (is->debug & 0x10)
2708 printk(KERN_DEBUG "Disable compression here!\n");
2709 if (proto == PPP_CCP)
2710 mis->compflags &= ~SC_COMP_ON;
2711 else
2712 is->compflags &= ~SC_LINK_COMP_ON;
2713 break;
2714 case CCP_TERMREQ:
2715 case CCP_TERMACK:
2716 if (is->debug & 0x10)
2717 printk(KERN_DEBUG "Disable (de)compression here!\n");
2718 if (proto == PPP_CCP)
2719 mis->compflags &= ~(SC_DECOMP_ON | SC_COMP_ON);
2720 else
2721 is->compflags &= ~(SC_LINK_DECOMP_ON | SC_LINK_COMP_ON);
2722 break;
2723 case CCP_CONFACK:
2724 /* if we RECEIVE an ackowledge we enable the decompressor */
2725 if (is->debug & 0x10)
2726 printk(KERN_DEBUG "Enable decompression here!\n");
2727 if (proto == PPP_CCP) {
2728 if (!mis->decompressor)
2729 break;
2730 mis->compflags |= SC_DECOMP_ON;
2731 } else {
2732 if (!is->decompressor)
2733 break;
2734 is->compflags |= SC_LINK_DECOMP_ON;
2735 }
2736 break;
2737
2738 case CCP_RESETACK:
2739 printk(KERN_DEBUG "Received ResetAck from peer\n");
2740 len = (skb->data[2] << 8) | skb->data[3];
2741 len -= 4;
2742
2743 if (proto == PPP_CCP) {
2744 /* If a reset Ack was outstanding for this id, then
2745 clean up the state engine */
2746 isdn_ppp_ccp_reset_ack_rcvd(mis, skb->data[1]);
2747 if (mis->decompressor && mis->decomp_stat)
2748 mis->decompressor->
2749 reset(mis->decomp_stat,
2750 skb->data[0],
2751 skb->data[1],
2752 len ? &skb->data[4] : NULL,
2753 len, NULL);
2754 /* TODO: This is not easy to decide here */
2755 mis->compflags &= ~SC_DECOMP_DISCARD;
2756 }
2757 else {
2758 isdn_ppp_ccp_reset_ack_rcvd(is, skb->data[1]);
2759 if (is->link_decompressor && is->link_decomp_stat)
2760 is->link_decompressor->
2761 reset(is->link_decomp_stat,
2762 skb->data[0],
2763 skb->data[1],
2764 len ? &skb->data[4] : NULL,
2765 len, NULL);
2766 /* TODO: neither here */
2767 is->compflags &= ~SC_LINK_DECOMP_DISCARD;
2768 }
2769 break;
2770
2771 case CCP_RESETREQ:
2772 printk(KERN_DEBUG "Received ResetReq from peer\n");
2773 /* Receiving a ResetReq means we must reset our compressor */
2774 /* Set up reset params for the reset entry */
2775 memset(&rsparm, 0, sizeof(rsparm));
2776 rsparm.data = rsdata;
2777 rsparm.maxdlen = IPPP_RESET_MAXDATABYTES;
2778 /* Isolate data length */
2779 len = (skb->data[2] << 8) | skb->data[3];
2780 len -= 4;
2781 if (proto == PPP_CCP) {
2782 if (mis->compressor && mis->comp_stat)
2783 mis->compressor->
2784 reset(mis->comp_stat,
2785 skb->data[0],
2786 skb->data[1],
2787 len ? &skb->data[4] : NULL,
2788 len, &rsparm);
2789 }
2790 else {
2791 if (is->link_compressor && is->link_comp_stat)
2792 is->link_compressor->
2793 reset(is->link_comp_stat,
2794 skb->data[0],
2795 skb->data[1],
2796 len ? &skb->data[4] : NULL,
2797 len, &rsparm);
2798 }
2799 /* Ack the Req as specified by rsparm */
2800 if (rsparm.valid) {
2801 /* Compressor reset handler decided how to answer */
2802 if (rsparm.rsend) {
2803 /* We should send a Frame */
2804 isdn_ppp_ccp_xmit_reset(is, proto, CCP_RESETACK,
2805 rsparm.idval ? rsparm.id
2806 : skb->data[1],
2807 rsparm.dtval ?
2808 rsparm.data : NULL,
2809 rsparm.dtval ?
2810 rsparm.dlen : 0);
2811 } else {
2812 printk(KERN_DEBUG "ResetAck suppressed\n");
2813 }
2814 } else {
2815 /* We answer with a straight reflected Ack */
2816 isdn_ppp_ccp_xmit_reset(is, proto, CCP_RESETACK,
2817 skb->data[1],
2818 len ? &skb->data[4] : NULL,
2819 len);
2820 }
2821 break;
2822 }
2823}
2824
2825
2826/*
2827 * Daemon sends a CCP frame ...
2828 */
2829
2830/* TODO: Clean this up with new Reset semantics */
2831
2832/* I believe the CCP handling as-is is done wrong. Compressed frames
2833 * should only be sent/received after CCP reaches UP state, which means
2834 * both sides have sent CONF_ACK. Currently, we handle both directions
2835 * independently, which means we may accept compressed frames too early
2836 * (supposedly not a problem), but may also mean we send compressed frames
2837 * too early, which may turn out to be a problem.
2838 * This part of state machine should actually be handled by (i)pppd, but
2839 * that's too big of a change now. --kai
2840 */
2841
2842/* Actually, we might turn this into an advantage: deal with the RFC in
2843 * the old tradition of beeing generous on what we accept, but beeing
2844 * strict on what we send. Thus we should just
2845 * - accept compressed frames as soon as decompression is negotiated
2846 * - send compressed frames only when decomp *and* comp are negotiated
2847 * - drop rx compressed frames if we cannot decomp (instead of pushing them
2848 * up to ipppd)
2849 * and I tried to modify this file according to that. --abp
2850 */
2851
2852static void isdn_ppp_send_ccp(isdn_net_dev *net_dev, isdn_net_local *lp, struct sk_buff *skb)
2853{
2854 struct ippp_struct *mis, *is;
2855 int proto, slot = lp->ppp_slot;
2856 unsigned char *data;
2857
2858 if (!skb || skb->len < 3)
2859 return;
2860 if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
2861 printk(KERN_ERR "%s: lp->ppp_slot(%d) out of range\n",
2862 __func__, slot);
2863 return;
2864 }
2865 is = ippp_table[slot];
2866 /* Daemon may send with or without address and control field comp */
2867 data = skb->data;
2868 if (!(is->pppcfg & SC_COMP_AC) && data[0] == 0xff && data[1] == 0x03) {
2869 data += 2;
2870 if (skb->len < 5)
2871 return;
2872 }
2873
2874 proto = ((int)data[0]<<8) + data[1];
2875 if (proto != PPP_CCP && proto != PPP_CCPFRAG)
2876 return;
2877
2878 printk(KERN_DEBUG "Received CCP frame from daemon:\n");
2879 isdn_ppp_frame_log("ccp-xmit", skb->data, skb->len, 32, is->unit, lp->ppp_slot);
2880
2881 if (lp->master) {
2882 slot = ISDN_MASTER_PRIV(lp)->ppp_slot;
2883 if (slot < 0 || slot >= ISDN_MAX_CHANNELS) {
2884 printk(KERN_ERR "%s: slot(%d) out of range\n",
2885 __func__, slot);
2886 return;
2887 }
2888 mis = ippp_table[slot];
2889 } else
2890 mis = is;
2891 if (mis != is)
2892 printk(KERN_DEBUG "isdn_ppp: Ouch! Master CCP sends on slave slot!\n");
2893
2894 switch (data[2]) {
2895 case CCP_CONFREQ:
2896 if (is->debug & 0x10)
2897 printk(KERN_DEBUG "Disable decompression here!\n");
2898 if (proto == PPP_CCP)
2899 is->compflags &= ~SC_DECOMP_ON;
2900 else
2901 is->compflags &= ~SC_LINK_DECOMP_ON;
2902 break;
2903 case CCP_TERMREQ:
2904 case CCP_TERMACK:
2905 if (is->debug & 0x10)
2906 printk(KERN_DEBUG "Disable (de)compression here!\n");
2907 if (proto == PPP_CCP)
2908 is->compflags &= ~(SC_DECOMP_ON | SC_COMP_ON);
2909 else
2910 is->compflags &= ~(SC_LINK_DECOMP_ON | SC_LINK_COMP_ON);
2911 break;
2912 case CCP_CONFACK:
2913 /* if we SEND an ackowledge we can/must enable the compressor */
2914 if (is->debug & 0x10)
2915 printk(KERN_DEBUG "Enable compression here!\n");
2916 if (proto == PPP_CCP) {
2917 if (!is->compressor)
2918 break;
2919 is->compflags |= SC_COMP_ON;
2920 } else {
2921 if (!is->compressor)
2922 break;
2923 is->compflags |= SC_LINK_COMP_ON;
2924 }
2925 break;
2926 case CCP_RESETACK:
2927 /* If we send a ACK we should reset our compressor */
2928 if (is->debug & 0x10)
2929 printk(KERN_DEBUG "Reset decompression state here!\n");
2930 printk(KERN_DEBUG "ResetAck from daemon passed by\n");
2931 if (proto == PPP_CCP) {
2932 /* link to master? */
2933 if (is->compressor && is->comp_stat)
2934 is->compressor->reset(is->comp_stat, 0, 0,
2935 NULL, 0, NULL);
2936 is->compflags &= ~SC_COMP_DISCARD;
2937 }
2938 else {
2939 if (is->link_compressor && is->link_comp_stat)
2940 is->link_compressor->reset(is->link_comp_stat,
2941 0, 0, NULL, 0, NULL);
2942 is->compflags &= ~SC_LINK_COMP_DISCARD;
2943 }
2944 break;
2945 case CCP_RESETREQ:
2946 /* Just let it pass by */
2947 printk(KERN_DEBUG "ResetReq from daemon passed by\n");
2948 break;
2949 }
2950}
2951
2952int isdn_ppp_register_compressor(struct isdn_ppp_compressor *ipc)
2953{
2954 ipc->next = ipc_head;
2955 ipc->prev = NULL;
2956 if (ipc_head) {
2957 ipc_head->prev = ipc;
2958 }
2959 ipc_head = ipc;
2960 return 0;
2961}
2962
2963int isdn_ppp_unregister_compressor(struct isdn_ppp_compressor *ipc)
2964{
2965 if (ipc->prev)
2966 ipc->prev->next = ipc->next;
2967 else
2968 ipc_head = ipc->next;
2969 if (ipc->next)
2970 ipc->next->prev = ipc->prev;
2971 ipc->prev = ipc->next = NULL;
2972 return 0;
2973}
2974
2975static int isdn_ppp_set_compressor(struct ippp_struct *is, struct isdn_ppp_comp_data *data)
2976{
2977 struct isdn_ppp_compressor *ipc = ipc_head;
2978 int ret;
2979 void *stat;
2980 int num = data->num;
2981
2982 if (is->debug & 0x10)
2983 printk(KERN_DEBUG "[%d] Set %s type %d\n", is->unit,
2984 (data->flags & IPPP_COMP_FLAG_XMIT) ? "compressor" : "decompressor", num);
2985
2986 /* If is has no valid reset state vector, we cannot allocate a
2987 decompressor. The decompressor would cause reset transactions
2988 sooner or later, and they need that vector. */
2989
2990 if (!(data->flags & IPPP_COMP_FLAG_XMIT) && !is->reset) {
2991 printk(KERN_ERR "ippp_ccp: no reset data structure - can't"
2992 " allow decompression.\n");
2993 return -ENOMEM;
2994 }
2995
2996 while (ipc) {
2997 if (ipc->num == num) {
2998 stat = ipc->alloc(data);
2999 if (stat) {
3000 ret = ipc->init(stat, data, is->unit, 0);
3001 if (!ret) {
3002 printk(KERN_ERR "Can't init (de)compression!\n");
3003 ipc->free(stat);
3004 stat = NULL;
3005 break;
3006 }
3007 }
3008 else {
3009 printk(KERN_ERR "Can't alloc (de)compression!\n");
3010 break;
3011 }
3012
3013 if (data->flags & IPPP_COMP_FLAG_XMIT) {
3014 if (data->flags & IPPP_COMP_FLAG_LINK) {
3015 if (is->link_comp_stat)
3016 is->link_compressor->free(is->link_comp_stat);
3017 is->link_comp_stat = stat;
3018 is->link_compressor = ipc;
3019 }
3020 else {
3021 if (is->comp_stat)
3022 is->compressor->free(is->comp_stat);
3023 is->comp_stat = stat;
3024 is->compressor = ipc;
3025 }
3026 }
3027 else {
3028 if (data->flags & IPPP_COMP_FLAG_LINK) {
3029 if (is->link_decomp_stat)
3030 is->link_decompressor->free(is->link_decomp_stat);
3031 is->link_decomp_stat = stat;
3032 is->link_decompressor = ipc;
3033 }
3034 else {
3035 if (is->decomp_stat)
3036 is->decompressor->free(is->decomp_stat);
3037 is->decomp_stat = stat;
3038 is->decompressor = ipc;
3039 }
3040 }
3041 return 0;
3042 }
3043 ipc = ipc->next;
3044 }
3045 return -EINVAL;
3046}
diff --git a/drivers/isdn/i4l/isdn_ppp.h b/drivers/isdn/i4l/isdn_ppp.h
deleted file mode 100644
index 34b8a2ce84f3..000000000000
--- a/drivers/isdn/i4l/isdn_ppp.h
+++ /dev/null
@@ -1,41 +0,0 @@
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 __poll_t 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
diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c
deleted file mode 100644
index 43700fc19a31..000000000000
--- a/drivers/isdn/i4l/isdn_tty.c
+++ /dev/null
@@ -1,3756 +0,0 @@
1/*
2 * Linux ISDN subsystem, tty functions and AT-command emulator (linklevel).
3 *
4 * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de)
5 * Copyright 1995,96 by Thinking Objects Software GmbH Wuerzburg
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#undef ISDN_TTY_STAT_DEBUG
12
13#include <linux/isdn.h>
14#include <linux/serial.h> /* ASYNC_* flags */
15#include <linux/slab.h>
16#include <linux/delay.h>
17#include <linux/mutex.h>
18#include <linux/sched/signal.h>
19#include "isdn_common.h"
20#include "isdn_tty.h"
21#ifdef CONFIG_ISDN_AUDIO
22#include "isdn_audio.h"
23#define VBUF 0x3e0
24#define VBUFX (VBUF/16)
25#endif
26
27#define FIX_FILE_TRANSFER
28#define DUMMY_HAYES_AT
29
30/* Prototypes */
31
32static DEFINE_MUTEX(modem_info_mutex);
33static int isdn_tty_edit_at(const char *, int, modem_info *);
34static void isdn_tty_check_esc(const u_char *, u_char, int, int *, u_long *);
35static void isdn_tty_modem_reset_regs(modem_info *, int);
36static void isdn_tty_cmd_ATA(modem_info *);
37static void isdn_tty_flush_buffer(struct tty_struct *);
38static void isdn_tty_modem_result(int, modem_info *);
39#ifdef CONFIG_ISDN_AUDIO
40static int isdn_tty_countDLE(unsigned char *, int);
41#endif
42
43/* Leave this unchanged unless you know what you do! */
44#define MODEM_PARANOIA_CHECK
45#define MODEM_DO_RESTART
46
47static int bit2si[8] =
48{1, 5, 7, 7, 7, 7, 7, 7};
49static int si2bit[8] =
50{4, 1, 4, 4, 4, 4, 4, 4};
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 struct tty_port *port = &info->port;
65 int c;
66 int len;
67 char last;
68
69 if (!info->online)
70 return 0;
71
72 if (!(info->mcr & UART_MCR_RTS))
73 return 0;
74
75 len = skb->len
76#ifdef CONFIG_ISDN_AUDIO
77 + ISDN_AUDIO_SKB_DLECOUNT(skb)
78#endif
79 ;
80
81 c = tty_buffer_request_room(port, len);
82 if (c < len)
83 return 0;
84
85#ifdef CONFIG_ISDN_AUDIO
86 if (ISDN_AUDIO_SKB_DLECOUNT(skb)) {
87 int l = skb->len;
88 unsigned char *dp = skb->data;
89 while (--l) {
90 if (*dp == DLE)
91 tty_insert_flip_char(port, DLE, 0);
92 tty_insert_flip_char(port, *dp++, 0);
93 }
94 if (*dp == DLE)
95 tty_insert_flip_char(port, DLE, 0);
96 last = *dp;
97 } else {
98#endif
99 if (len > 1)
100 tty_insert_flip_string(port, skb->data, len - 1);
101 last = skb->data[len - 1];
102#ifdef CONFIG_ISDN_AUDIO
103 }
104#endif
105 if (info->emu.mdmreg[REG_CPPP] & BIT_CPPP)
106 tty_insert_flip_char(port, last, 0xFF);
107 else
108 tty_insert_flip_char(port, last, TTY_NORMAL);
109 tty_flip_buffer_push(port);
110 kfree_skb(skb);
111
112 return 1;
113}
114
115/* isdn_tty_readmodem() is called periodically from within timer-interrupt.
116 * It tries getting received data from the receive queue an stuff it into
117 * the tty's flip-buffer.
118 */
119void
120isdn_tty_readmodem(void)
121{
122 int resched = 0;
123 int midx;
124 int i;
125 int r;
126 modem_info *info;
127
128 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
129 midx = dev->m_idx[i];
130 if (midx < 0)
131 continue;
132
133 info = &dev->mdm.info[midx];
134 if (!info->online)
135 continue;
136
137 r = 0;
138#ifdef CONFIG_ISDN_AUDIO
139 isdn_audio_eval_dtmf(info);
140 if ((info->vonline & 1) && (info->emu.vpar[1]))
141 isdn_audio_eval_silence(info);
142#endif
143 if (info->mcr & UART_MCR_RTS) {
144 /* CISCO AsyncPPP Hack */
145 if (!(info->emu.mdmreg[REG_CPPP] & BIT_CPPP))
146 r = isdn_readbchan_tty(info->isdn_driver,
147 info->isdn_channel,
148 &info->port, 0);
149 else
150 r = isdn_readbchan_tty(info->isdn_driver,
151 info->isdn_channel,
152 &info->port, 1);
153 if (r)
154 tty_flip_buffer_push(&info->port);
155 } else
156 r = 1;
157
158 if (r) {
159 info->rcvsched = 0;
160 resched = 1;
161 } else
162 info->rcvsched = 1;
163 }
164 if (!resched)
165 isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 0);
166}
167
168int
169isdn_tty_rcv_skb(int i, int di, int channel, struct sk_buff *skb)
170{
171 ulong flags;
172 int midx;
173#ifdef CONFIG_ISDN_AUDIO
174 int ifmt;
175#endif
176 modem_info *info;
177
178 if ((midx = dev->m_idx[i]) < 0) {
179 /* if midx is invalid, packet is not for tty */
180 return 0;
181 }
182 info = &dev->mdm.info[midx];
183#ifdef CONFIG_ISDN_AUDIO
184 ifmt = 1;
185
186 if ((info->vonline) && (!info->emu.vpar[4]))
187 isdn_audio_calc_dtmf(info, skb->data, skb->len, ifmt);
188 if ((info->vonline & 1) && (info->emu.vpar[1]))
189 isdn_audio_calc_silence(info, skb->data, skb->len, ifmt);
190#endif
191 if ((info->online < 2)
192#ifdef CONFIG_ISDN_AUDIO
193 && (!(info->vonline & 1))
194#endif
195 ) {
196 /* If Modem not listening, drop data */
197 kfree_skb(skb);
198 return 1;
199 }
200 if (info->emu.mdmreg[REG_T70] & BIT_T70) {
201 if (info->emu.mdmreg[REG_T70] & BIT_T70_EXT) {
202 /* T.70 decoding: throw away the T.70 header (2 or 4 bytes) */
203 if (skb->data[0] == 3) /* pure data packet -> 4 byte headers */
204 skb_pull(skb, 4);
205 else
206 if (skb->data[0] == 1) /* keepalive packet -> 2 byte hdr */
207 skb_pull(skb, 2);
208 } else
209 /* T.70 decoding: Simply throw away the T.70 header (4 bytes) */
210 if ((skb->data[0] == 1) && ((skb->data[1] == 0) || (skb->data[1] == 1)))
211 skb_pull(skb, 4);
212 }
213#ifdef CONFIG_ISDN_AUDIO
214 ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;
215 ISDN_AUDIO_SKB_LOCK(skb) = 0;
216 if (info->vonline & 1) {
217 /* voice conversion/compression */
218 switch (info->emu.vpar[3]) {
219 case 2:
220 case 3:
221 case 4:
222 /* adpcm
223 * Since compressed data takes less
224 * space, we can overwrite the buffer.
225 */
226 skb_trim(skb, isdn_audio_xlaw2adpcm(info->adpcmr,
227 ifmt,
228 skb->data,
229 skb->data,
230 skb->len));
231 break;
232 case 5:
233 /* a-law */
234 if (!ifmt)
235 isdn_audio_ulaw2alaw(skb->data, skb->len);
236 break;
237 case 6:
238 /* u-law */
239 if (ifmt)
240 isdn_audio_alaw2ulaw(skb->data, skb->len);
241 break;
242 }
243 ISDN_AUDIO_SKB_DLECOUNT(skb) =
244 isdn_tty_countDLE(skb->data, skb->len);
245 }
246#ifdef CONFIG_ISDN_TTY_FAX
247 else {
248 if (info->faxonline & 2) {
249 isdn_tty_fax_bitorder(info, skb);
250 ISDN_AUDIO_SKB_DLECOUNT(skb) =
251 isdn_tty_countDLE(skb->data, skb->len);
252 }
253 }
254#endif
255#endif
256 /* Try to deliver directly via tty-buf if queue is empty */
257 spin_lock_irqsave(&info->readlock, flags);
258 if (skb_queue_empty(&dev->drv[di]->rpqueue[channel]))
259 if (isdn_tty_try_read(info, skb)) {
260 spin_unlock_irqrestore(&info->readlock, flags);
261 return 1;
262 }
263 /* Direct deliver failed or queue wasn't empty.
264 * Queue up for later dequeueing via timer-irq.
265 */
266 __skb_queue_tail(&dev->drv[di]->rpqueue[channel], skb);
267 dev->drv[di]->rcvcount[channel] +=
268 (skb->len
269#ifdef CONFIG_ISDN_AUDIO
270 + ISDN_AUDIO_SKB_DLECOUNT(skb)
271#endif
272 );
273 spin_unlock_irqrestore(&info->readlock, flags);
274 /* Schedule dequeuing */
275 if ((dev->modempoll) && (info->rcvsched))
276 isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
277 return 1;
278}
279
280static void
281isdn_tty_cleanup_xmit(modem_info *info)
282{
283 skb_queue_purge(&info->xmit_queue);
284#ifdef CONFIG_ISDN_AUDIO
285 skb_queue_purge(&info->dtmf_queue);
286#endif
287}
288
289static void
290isdn_tty_tint(modem_info *info)
291{
292 struct sk_buff *skb = skb_dequeue(&info->xmit_queue);
293 int len, slen;
294
295 if (!skb)
296 return;
297 len = skb->len;
298 if ((slen = isdn_writebuf_skb_stub(info->isdn_driver,
299 info->isdn_channel, 1, skb)) == len) {
300 struct tty_struct *tty = info->port.tty;
301 info->send_outstanding++;
302 info->msr &= ~UART_MSR_CTS;
303 info->lsr &= ~UART_LSR_TEMT;
304 tty_wakeup(tty);
305 return;
306 }
307 if (slen < 0) {
308 /* Error: no channel, already shutdown, or wrong parameter */
309 dev_kfree_skb(skb);
310 return;
311 }
312 skb_queue_head(&info->xmit_queue, skb);
313}
314
315#ifdef CONFIG_ISDN_AUDIO
316static int
317isdn_tty_countDLE(unsigned char *buf, int len)
318{
319 int count = 0;
320
321 while (len--)
322 if (*buf++ == DLE)
323 count++;
324 return count;
325}
326
327/* This routine is called from within isdn_tty_write() to perform
328 * DLE-decoding when sending audio-data.
329 */
330static int
331isdn_tty_handleDLEdown(modem_info *info, atemu *m, int len)
332{
333 unsigned char *p = &info->port.xmit_buf[info->xmit_count];
334 int count = 0;
335
336 while (len > 0) {
337 if (m->lastDLE) {
338 m->lastDLE = 0;
339 switch (*p) {
340 case DLE:
341 /* Escape code */
342 if (len > 1)
343 memmove(p, p + 1, len - 1);
344 p--;
345 count++;
346 break;
347 case ETX:
348 /* End of data */
349 info->vonline |= 4;
350 return count;
351 case DC4:
352 /* Abort RX */
353 info->vonline &= ~1;
354#ifdef ISDN_DEBUG_MODEM_VOICE
355 printk(KERN_DEBUG
356 "DLEdown: got DLE-DC4, send DLE-ETX on ttyI%d\n",
357 info->line);
358#endif
359 isdn_tty_at_cout("\020\003", info);
360 if (!info->vonline) {
361#ifdef ISDN_DEBUG_MODEM_VOICE
362 printk(KERN_DEBUG
363 "DLEdown: send VCON on ttyI%d\n",
364 info->line);
365#endif
366 isdn_tty_at_cout("\r\nVCON\r\n", info);
367 }
368 /* Fall through */
369 case 'q':
370 case 's':
371 /* Silence */
372 if (len > 1)
373 memmove(p, p + 1, len - 1);
374 p--;
375 break;
376 }
377 } else {
378 if (*p == DLE)
379 m->lastDLE = 1;
380 else
381 count++;
382 }
383 p++;
384 len--;
385 }
386 if (len < 0) {
387 printk(KERN_WARNING "isdn_tty: len<0 in DLEdown\n");
388 return 0;
389 }
390 return count;
391}
392
393/* This routine is called from within isdn_tty_write() when receiving
394 * audio-data. It interrupts receiving, if an character other than
395 * ^S or ^Q is sent.
396 */
397static int
398isdn_tty_end_vrx(const char *buf, int c)
399{
400 char ch;
401
402 while (c--) {
403 ch = *buf;
404 if ((ch != 0x11) && (ch != 0x13))
405 return 1;
406 buf++;
407 }
408 return 0;
409}
410
411static int voice_cf[7] =
412{0, 0, 4, 3, 2, 0, 0};
413
414#endif /* CONFIG_ISDN_AUDIO */
415
416/* isdn_tty_senddown() is called either directly from within isdn_tty_write()
417 * or via timer-interrupt from within isdn_tty_modem_xmit(). It pulls
418 * outgoing data from the tty's xmit-buffer, handles voice-decompression or
419 * T.70 if necessary, and finally queues it up for sending via isdn_tty_tint.
420 */
421static void
422isdn_tty_senddown(modem_info *info)
423{
424 int buflen;
425 int skb_res;
426#ifdef CONFIG_ISDN_AUDIO
427 int audio_len;
428#endif
429 struct sk_buff *skb;
430
431#ifdef CONFIG_ISDN_AUDIO
432 if (info->vonline & 4) {
433 info->vonline &= ~6;
434 if (!info->vonline) {
435#ifdef ISDN_DEBUG_MODEM_VOICE
436 printk(KERN_DEBUG
437 "senddown: send VCON on ttyI%d\n",
438 info->line);
439#endif
440 isdn_tty_at_cout("\r\nVCON\r\n", info);
441 }
442 }
443#endif
444 if (!(buflen = info->xmit_count))
445 return;
446 if ((info->emu.mdmreg[REG_CTS] & BIT_CTS) != 0)
447 info->msr &= ~UART_MSR_CTS;
448 info->lsr &= ~UART_LSR_TEMT;
449 /* info->xmit_count is modified here and in isdn_tty_write().
450 * So we return here if isdn_tty_write() is in the
451 * critical section.
452 */
453 atomic_inc(&info->xmit_lock);
454 if (!(atomic_dec_and_test(&info->xmit_lock)))
455 return;
456 if (info->isdn_driver < 0) {
457 info->xmit_count = 0;
458 return;
459 }
460 skb_res = dev->drv[info->isdn_driver]->interface->hl_hdrlen + 4;
461#ifdef CONFIG_ISDN_AUDIO
462 if (info->vonline & 2)
463 audio_len = buflen * voice_cf[info->emu.vpar[3]];
464 else
465 audio_len = 0;
466 skb = dev_alloc_skb(skb_res + buflen + audio_len);
467#else
468 skb = dev_alloc_skb(skb_res + buflen);
469#endif
470 if (!skb) {
471 printk(KERN_WARNING
472 "isdn_tty: Out of memory in ttyI%d senddown\n",
473 info->line);
474 return;
475 }
476 skb_reserve(skb, skb_res);
477 skb_put_data(skb, info->port.xmit_buf, buflen);
478 info->xmit_count = 0;
479#ifdef CONFIG_ISDN_AUDIO
480 if (info->vonline & 2) {
481 /* For now, ifmt is fixed to 1 (alaw), since this
482 * is used with ISDN everywhere in the world, except
483 * US, Canada and Japan.
484 * Later, when US-ISDN protocols are implemented,
485 * this setting will depend on the D-channel protocol.
486 */
487 int ifmt = 1;
488
489 /* voice conversion/decompression */
490 switch (info->emu.vpar[3]) {
491 case 2:
492 case 3:
493 case 4:
494 /* adpcm, compatible to ZyXel 1496 modem
495 * with ROM revision 6.01
496 */
497 audio_len = isdn_audio_adpcm2xlaw(info->adpcms,
498 ifmt,
499 skb->data,
500 skb_put(skb, audio_len),
501 buflen);
502 skb_pull(skb, buflen);
503 skb_trim(skb, audio_len);
504 break;
505 case 5:
506 /* a-law */
507 if (!ifmt)
508 isdn_audio_alaw2ulaw(skb->data,
509 buflen);
510 break;
511 case 6:
512 /* u-law */
513 if (ifmt)
514 isdn_audio_ulaw2alaw(skb->data,
515 buflen);
516 break;
517 }
518 }
519#endif /* CONFIG_ISDN_AUDIO */
520 if (info->emu.mdmreg[REG_T70] & BIT_T70) {
521 /* Add T.70 simplified header */
522 if (info->emu.mdmreg[REG_T70] & BIT_T70_EXT)
523 memcpy(skb_push(skb, 2), "\1\0", 2);
524 else
525 memcpy(skb_push(skb, 4), "\1\0\1\0", 4);
526 }
527 skb_queue_tail(&info->xmit_queue, skb);
528}
529
530/************************************************************
531 *
532 * Modem-functions
533 *
534 * mostly "stolen" from original Linux-serial.c and friends.
535 *
536 ************************************************************/
537
538/* The next routine is called once from within timer-interrupt
539 * triggered within isdn_tty_modem_ncarrier(). It calls
540 * isdn_tty_modem_result() to stuff a "NO CARRIER" Message
541 * into the tty's buffer.
542 */
543static void
544isdn_tty_modem_do_ncarrier(struct timer_list *t)
545{
546 modem_info *info = from_timer(info, t, nc_timer);
547 isdn_tty_modem_result(RESULT_NO_CARRIER, info);
548}
549
550/* Next routine is called, whenever the DTR-signal is raised.
551 * It checks the ncarrier-flag, and triggers the above routine
552 * when necessary. The ncarrier-flag is set, whenever DTR goes
553 * low.
554 */
555static void
556isdn_tty_modem_ncarrier(modem_info *info)
557{
558 if (info->ncarrier) {
559 info->nc_timer.expires = jiffies + HZ;
560 add_timer(&info->nc_timer);
561 }
562}
563
564/*
565 * return the usage calculated by si and layer 2 protocol
566 */
567static int
568isdn_calc_usage(int si, int l2)
569{
570 int usg = ISDN_USAGE_MODEM;
571
572#ifdef CONFIG_ISDN_AUDIO
573 if (si == 1) {
574 switch (l2) {
575 case ISDN_PROTO_L2_MODEM:
576 usg = ISDN_USAGE_MODEM;
577 break;
578#ifdef CONFIG_ISDN_TTY_FAX
579 case ISDN_PROTO_L2_FAX:
580 usg = ISDN_USAGE_FAX;
581 break;
582#endif
583 case ISDN_PROTO_L2_TRANS:
584 default:
585 usg = ISDN_USAGE_VOICE;
586 break;
587 }
588 }
589#endif
590 return (usg);
591}
592
593/* isdn_tty_dial() performs dialing of a tty an the necessary
594 * setup of the lower levels before that.
595 */
596static void
597isdn_tty_dial(char *n, modem_info *info, atemu *m)
598{
599 int usg = ISDN_USAGE_MODEM;
600 int si = 7;
601 int l2 = m->mdmreg[REG_L2PROT];
602 u_long flags;
603 isdn_ctrl cmd;
604 int i;
605 int j;
606
607 for (j = 7; j >= 0; j--)
608 if (m->mdmreg[REG_SI1] & (1 << j)) {
609 si = bit2si[j];
610 break;
611 }
612 usg = isdn_calc_usage(si, l2);
613#ifdef CONFIG_ISDN_AUDIO
614 if ((si == 1) &&
615 (l2 != ISDN_PROTO_L2_MODEM)
616#ifdef CONFIG_ISDN_TTY_FAX
617 && (l2 != ISDN_PROTO_L2_FAX)
618#endif
619 ) {
620 l2 = ISDN_PROTO_L2_TRANS;
621 usg = ISDN_USAGE_VOICE;
622 }
623#endif
624 m->mdmreg[REG_SI1I] = si2bit[si];
625 spin_lock_irqsave(&dev->lock, flags);
626 i = isdn_get_free_channel(usg, l2, m->mdmreg[REG_L3PROT], -1, -1, m->msn);
627 if (i < 0) {
628 spin_unlock_irqrestore(&dev->lock, flags);
629 isdn_tty_modem_result(RESULT_NO_DIALTONE, info);
630 } else {
631 info->isdn_driver = dev->drvmap[i];
632 info->isdn_channel = dev->chanmap[i];
633 info->drv_index = i;
634 dev->m_idx[i] = info->line;
635 dev->usage[i] |= ISDN_USAGE_OUTGOING;
636 info->last_dir = 1;
637 strcpy(info->last_num, n);
638 isdn_info_update();
639 spin_unlock_irqrestore(&dev->lock, flags);
640 cmd.driver = info->isdn_driver;
641 cmd.arg = info->isdn_channel;
642 cmd.command = ISDN_CMD_CLREAZ;
643 isdn_command(&cmd);
644 strcpy(cmd.parm.num, isdn_map_eaz2msn(m->msn, info->isdn_driver));
645 cmd.driver = info->isdn_driver;
646 cmd.command = ISDN_CMD_SETEAZ;
647 isdn_command(&cmd);
648 cmd.driver = info->isdn_driver;
649 cmd.command = ISDN_CMD_SETL2;
650 info->last_l2 = l2;
651 cmd.arg = info->isdn_channel + (l2 << 8);
652 isdn_command(&cmd);
653 cmd.driver = info->isdn_driver;
654 cmd.command = ISDN_CMD_SETL3;
655 cmd.arg = info->isdn_channel + (m->mdmreg[REG_L3PROT] << 8);
656#ifdef CONFIG_ISDN_TTY_FAX
657 if (l2 == ISDN_PROTO_L2_FAX) {
658 cmd.parm.fax = info->fax;
659 info->fax->direction = ISDN_TTY_FAX_CONN_OUT;
660 }
661#endif
662 isdn_command(&cmd);
663 cmd.driver = info->isdn_driver;
664 cmd.arg = info->isdn_channel;
665 sprintf(cmd.parm.setup.phone, "%s", n);
666 sprintf(cmd.parm.setup.eazmsn, "%s",
667 isdn_map_eaz2msn(m->msn, info->isdn_driver));
668 cmd.parm.setup.si1 = si;
669 cmd.parm.setup.si2 = m->mdmreg[REG_SI2];
670 cmd.command = ISDN_CMD_DIAL;
671 info->dialing = 1;
672 info->emu.carrierwait = 0;
673 strcpy(dev->num[i], n);
674 isdn_info_update();
675 isdn_command(&cmd);
676 isdn_timer_ctrl(ISDN_TIMER_CARRIER, 1);
677 }
678}
679
680/* isdn_tty_hangup() disassociates a tty from the real
681 * ISDN-line (hangup). The usage-status is cleared
682 * and some cleanup is done also.
683 */
684void
685isdn_tty_modem_hup(modem_info *info, int local)
686{
687 isdn_ctrl cmd;
688 int di, ch;
689
690 if (!info)
691 return;
692
693 di = info->isdn_driver;
694 ch = info->isdn_channel;
695 if (di < 0 || ch < 0)
696 return;
697
698 info->isdn_driver = -1;
699 info->isdn_channel = -1;
700
701#ifdef ISDN_DEBUG_MODEM_HUP
702 printk(KERN_DEBUG "Mhup ttyI%d\n", info->line);
703#endif
704 info->rcvsched = 0;
705 isdn_tty_flush_buffer(info->port.tty);
706 if (info->online) {
707 info->last_lhup = local;
708 info->online = 0;
709 isdn_tty_modem_result(RESULT_NO_CARRIER, info);
710 }
711#ifdef CONFIG_ISDN_AUDIO
712 info->vonline = 0;
713#ifdef CONFIG_ISDN_TTY_FAX
714 info->faxonline = 0;
715 info->fax->phase = ISDN_FAX_PHASE_IDLE;
716#endif
717 info->emu.vpar[4] = 0;
718 info->emu.vpar[5] = 8;
719 kfree(info->dtmf_state);
720 info->dtmf_state = NULL;
721 kfree(info->silence_state);
722 info->silence_state = NULL;
723 kfree(info->adpcms);
724 info->adpcms = NULL;
725 kfree(info->adpcmr);
726 info->adpcmr = NULL;
727#endif
728 if ((info->msr & UART_MSR_RI) &&
729 (info->emu.mdmreg[REG_RUNG] & BIT_RUNG))
730 isdn_tty_modem_result(RESULT_RUNG, info);
731 info->msr &= ~(UART_MSR_DCD | UART_MSR_RI);
732 info->lsr |= UART_LSR_TEMT;
733
734 if (local) {
735 cmd.driver = di;
736 cmd.command = ISDN_CMD_HANGUP;
737 cmd.arg = ch;
738 isdn_command(&cmd);
739 }
740
741 isdn_all_eaz(di, ch);
742 info->emu.mdmreg[REG_RINGCNT] = 0;
743 isdn_free_channel(di, ch, 0);
744
745 if (info->drv_index >= 0) {
746 dev->m_idx[info->drv_index] = -1;
747 info->drv_index = -1;
748 }
749}
750
751/*
752 * Begin of a CAPI like interface, currently used only for
753 * supplementary service (CAPI 2.0 part III)
754 */
755#include <linux/isdn/capicmd.h>
756#include <linux/module.h>
757
758int
759isdn_tty_capi_facility(capi_msg *cm) {
760 return (-1); /* dummy */
761}
762
763/* isdn_tty_suspend() tries to suspend the current tty connection
764 */
765static void
766isdn_tty_suspend(char *id, modem_info *info, atemu *m)
767{
768 isdn_ctrl cmd;
769
770 int l;
771
772 if (!info)
773 return;
774
775#ifdef ISDN_DEBUG_MODEM_SERVICES
776 printk(KERN_DEBUG "Msusp ttyI%d\n", info->line);
777#endif
778 l = strlen(id);
779 if ((info->isdn_driver >= 0)) {
780 cmd.parm.cmsg.Length = l + 18;
781 cmd.parm.cmsg.Command = CAPI_FACILITY;
782 cmd.parm.cmsg.Subcommand = CAPI_REQ;
783 cmd.parm.cmsg.adr.Controller = info->isdn_driver + 1;
784 cmd.parm.cmsg.para[0] = 3; /* 16 bit 0x0003 suplementary service */
785 cmd.parm.cmsg.para[1] = 0;
786 cmd.parm.cmsg.para[2] = l + 3;
787 cmd.parm.cmsg.para[3] = 4; /* 16 bit 0x0004 Suspend */
788 cmd.parm.cmsg.para[4] = 0;
789 cmd.parm.cmsg.para[5] = l;
790 memcpy(&cmd.parm.cmsg.para[6], id, l);
791 cmd.command = CAPI_PUT_MESSAGE;
792 cmd.driver = info->isdn_driver;
793 cmd.arg = info->isdn_channel;
794 isdn_command(&cmd);
795 }
796}
797
798/* isdn_tty_resume() tries to resume a suspended call
799 * setup of the lower levels before that. unfortunately here is no
800 * checking for compatibility of used protocols implemented by Q931
801 * It does the same things like isdn_tty_dial, the last command
802 * is different, may be we can merge it.
803 */
804
805static void
806isdn_tty_resume(char *id, modem_info *info, atemu *m)
807{
808 int usg = ISDN_USAGE_MODEM;
809 int si = 7;
810 int l2 = m->mdmreg[REG_L2PROT];
811 isdn_ctrl cmd;
812 ulong flags;
813 int i;
814 int j;
815 int l;
816
817 l = strlen(id);
818 for (j = 7; j >= 0; j--)
819 if (m->mdmreg[REG_SI1] & (1 << j)) {
820 si = bit2si[j];
821 break;
822 }
823 usg = isdn_calc_usage(si, l2);
824#ifdef CONFIG_ISDN_AUDIO
825 if ((si == 1) &&
826 (l2 != ISDN_PROTO_L2_MODEM)
827#ifdef CONFIG_ISDN_TTY_FAX
828 && (l2 != ISDN_PROTO_L2_FAX)
829#endif
830 ) {
831 l2 = ISDN_PROTO_L2_TRANS;
832 usg = ISDN_USAGE_VOICE;
833 }
834#endif
835 m->mdmreg[REG_SI1I] = si2bit[si];
836 spin_lock_irqsave(&dev->lock, flags);
837 i = isdn_get_free_channel(usg, l2, m->mdmreg[REG_L3PROT], -1, -1, m->msn);
838 if (i < 0) {
839 spin_unlock_irqrestore(&dev->lock, flags);
840 isdn_tty_modem_result(RESULT_NO_DIALTONE, info);
841 } else {
842 info->isdn_driver = dev->drvmap[i];
843 info->isdn_channel = dev->chanmap[i];
844 info->drv_index = i;
845 dev->m_idx[i] = info->line;
846 dev->usage[i] |= ISDN_USAGE_OUTGOING;
847 info->last_dir = 1;
848// strcpy(info->last_num, n);
849 isdn_info_update();
850 spin_unlock_irqrestore(&dev->lock, flags);
851 cmd.driver = info->isdn_driver;
852 cmd.arg = info->isdn_channel;
853 cmd.command = ISDN_CMD_CLREAZ;
854 isdn_command(&cmd);
855 strcpy(cmd.parm.num, isdn_map_eaz2msn(m->msn, info->isdn_driver));
856 cmd.driver = info->isdn_driver;
857 cmd.command = ISDN_CMD_SETEAZ;
858 isdn_command(&cmd);
859 cmd.driver = info->isdn_driver;
860 cmd.command = ISDN_CMD_SETL2;
861 info->last_l2 = l2;
862 cmd.arg = info->isdn_channel + (l2 << 8);
863 isdn_command(&cmd);
864 cmd.driver = info->isdn_driver;
865 cmd.command = ISDN_CMD_SETL3;
866 cmd.arg = info->isdn_channel + (m->mdmreg[REG_L3PROT] << 8);
867 isdn_command(&cmd);
868 cmd.driver = info->isdn_driver;
869 cmd.arg = info->isdn_channel;
870 cmd.parm.cmsg.Length = l + 18;
871 cmd.parm.cmsg.Command = CAPI_FACILITY;
872 cmd.parm.cmsg.Subcommand = CAPI_REQ;
873 cmd.parm.cmsg.adr.Controller = info->isdn_driver + 1;
874 cmd.parm.cmsg.para[0] = 3; /* 16 bit 0x0003 suplementary service */
875 cmd.parm.cmsg.para[1] = 0;
876 cmd.parm.cmsg.para[2] = l + 3;
877 cmd.parm.cmsg.para[3] = 5; /* 16 bit 0x0005 Resume */
878 cmd.parm.cmsg.para[4] = 0;
879 cmd.parm.cmsg.para[5] = l;
880 memcpy(&cmd.parm.cmsg.para[6], id, l);
881 cmd.command = CAPI_PUT_MESSAGE;
882 info->dialing = 1;
883// strcpy(dev->num[i], n);
884 isdn_info_update();
885 isdn_command(&cmd);
886 isdn_timer_ctrl(ISDN_TIMER_CARRIER, 1);
887 }
888}
889
890/* isdn_tty_send_msg() sends a message to a HL driver
891 * This is used for hybrid modem cards to send AT commands to it
892 */
893
894static void
895isdn_tty_send_msg(modem_info *info, atemu *m, char *msg)
896{
897 int usg = ISDN_USAGE_MODEM;
898 int si = 7;
899 int l2 = m->mdmreg[REG_L2PROT];
900 isdn_ctrl cmd;
901 ulong flags;
902 int i;
903 int j;
904 int l;
905
906 l = min(strlen(msg), sizeof(cmd.parm) - sizeof(cmd.parm.cmsg)
907 + sizeof(cmd.parm.cmsg.para) - 2);
908
909 if (!l) {
910 isdn_tty_modem_result(RESULT_ERROR, info);
911 return;
912 }
913 for (j = 7; j >= 0; j--)
914 if (m->mdmreg[REG_SI1] & (1 << j)) {
915 si = bit2si[j];
916 break;
917 }
918 usg = isdn_calc_usage(si, l2);
919#ifdef CONFIG_ISDN_AUDIO
920 if ((si == 1) &&
921 (l2 != ISDN_PROTO_L2_MODEM)
922#ifdef CONFIG_ISDN_TTY_FAX
923 && (l2 != ISDN_PROTO_L2_FAX)
924#endif
925 ) {
926 l2 = ISDN_PROTO_L2_TRANS;
927 usg = ISDN_USAGE_VOICE;
928 }
929#endif
930 m->mdmreg[REG_SI1I] = si2bit[si];
931 spin_lock_irqsave(&dev->lock, flags);
932 i = isdn_get_free_channel(usg, l2, m->mdmreg[REG_L3PROT], -1, -1, m->msn);
933 if (i < 0) {
934 spin_unlock_irqrestore(&dev->lock, flags);
935 isdn_tty_modem_result(RESULT_NO_DIALTONE, info);
936 } else {
937 info->isdn_driver = dev->drvmap[i];
938 info->isdn_channel = dev->chanmap[i];
939 info->drv_index = i;
940 dev->m_idx[i] = info->line;
941 dev->usage[i] |= ISDN_USAGE_OUTGOING;
942 info->last_dir = 1;
943 isdn_info_update();
944 spin_unlock_irqrestore(&dev->lock, flags);
945 cmd.driver = info->isdn_driver;
946 cmd.arg = info->isdn_channel;
947 cmd.command = ISDN_CMD_CLREAZ;
948 isdn_command(&cmd);
949 strcpy(cmd.parm.num, isdn_map_eaz2msn(m->msn, info->isdn_driver));
950 cmd.driver = info->isdn_driver;
951 cmd.command = ISDN_CMD_SETEAZ;
952 isdn_command(&cmd);
953 cmd.driver = info->isdn_driver;
954 cmd.command = ISDN_CMD_SETL2;
955 info->last_l2 = l2;
956 cmd.arg = info->isdn_channel + (l2 << 8);
957 isdn_command(&cmd);
958 cmd.driver = info->isdn_driver;
959 cmd.command = ISDN_CMD_SETL3;
960 cmd.arg = info->isdn_channel + (m->mdmreg[REG_L3PROT] << 8);
961 isdn_command(&cmd);
962 cmd.driver = info->isdn_driver;
963 cmd.arg = info->isdn_channel;
964 cmd.parm.cmsg.Length = l + 14;
965 cmd.parm.cmsg.Command = CAPI_MANUFACTURER;
966 cmd.parm.cmsg.Subcommand = CAPI_REQ;
967 cmd.parm.cmsg.adr.Controller = info->isdn_driver + 1;
968 cmd.parm.cmsg.para[0] = l + 1;
969 strncpy(&cmd.parm.cmsg.para[1], msg, l);
970 cmd.parm.cmsg.para[l + 1] = 0xd;
971 cmd.command = CAPI_PUT_MESSAGE;
972/* info->dialing = 1;
973 strcpy(dev->num[i], n);
974 isdn_info_update();
975*/
976 isdn_command(&cmd);
977 }
978}
979
980static inline int
981isdn_tty_paranoia_check(modem_info *info, char *name, const char *routine)
982{
983#ifdef MODEM_PARANOIA_CHECK
984 if (!info) {
985 printk(KERN_WARNING "isdn_tty: null info_struct for %s in %s\n",
986 name, routine);
987 return 1;
988 }
989 if (info->magic != ISDN_ASYNC_MAGIC) {
990 printk(KERN_WARNING "isdn_tty: bad magic for modem struct %s in %s\n",
991 name, routine);
992 return 1;
993 }
994#endif
995 return 0;
996}
997
998/*
999 * This routine is called to set the UART divisor registers to match
1000 * the specified baud rate for a serial port.
1001 */
1002static void
1003isdn_tty_change_speed(modem_info *info)
1004{
1005 struct tty_port *port = &info->port;
1006 uint cflag,
1007 cval,
1008 quot;
1009 int i;
1010
1011 if (!port->tty)
1012 return;
1013 cflag = port->tty->termios.c_cflag;
1014
1015 quot = i = cflag & CBAUD;
1016 if (i & CBAUDEX) {
1017 i &= ~CBAUDEX;
1018 if (i < 1 || i > 2)
1019 port->tty->termios.c_cflag &= ~CBAUDEX;
1020 else
1021 i += 15;
1022 }
1023 if (quot) {
1024 info->mcr |= UART_MCR_DTR;
1025 isdn_tty_modem_ncarrier(info);
1026 } else {
1027 info->mcr &= ~UART_MCR_DTR;
1028 if (info->emu.mdmreg[REG_DTRHUP] & BIT_DTRHUP) {
1029#ifdef ISDN_DEBUG_MODEM_HUP
1030 printk(KERN_DEBUG "Mhup in changespeed\n");
1031#endif
1032 if (info->online)
1033 info->ncarrier = 1;
1034 isdn_tty_modem_reset_regs(info, 0);
1035 isdn_tty_modem_hup(info, 1);
1036 }
1037 return;
1038 }
1039 /* byte size and parity */
1040 cval = cflag & (CSIZE | CSTOPB);
1041 cval >>= 4;
1042 if (cflag & PARENB)
1043 cval |= UART_LCR_PARITY;
1044 if (!(cflag & PARODD))
1045 cval |= UART_LCR_EPAR;
1046
1047 tty_port_set_check_carrier(port, ~cflag & CLOCAL);
1048}
1049
1050static int
1051isdn_tty_startup(modem_info *info)
1052{
1053 if (tty_port_initialized(&info->port))
1054 return 0;
1055 isdn_lock_drivers();
1056#ifdef ISDN_DEBUG_MODEM_OPEN
1057 printk(KERN_DEBUG "starting up ttyi%d ...\n", info->line);
1058#endif
1059 /*
1060 * Now, initialize the UART
1061 */
1062 info->mcr = UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2;
1063 if (info->port.tty)
1064 clear_bit(TTY_IO_ERROR, &info->port.tty->flags);
1065 /*
1066 * and set the speed of the serial port
1067 */
1068 isdn_tty_change_speed(info);
1069
1070 tty_port_set_initialized(&info->port, 1);
1071 info->msr |= (UART_MSR_DSR | UART_MSR_CTS);
1072 info->send_outstanding = 0;
1073 return 0;
1074}
1075
1076/*
1077 * This routine will shutdown a serial port; interrupts are disabled, and
1078 * DTR is dropped if the hangup on close termio flag is on.
1079 */
1080static void
1081isdn_tty_shutdown(modem_info *info)
1082{
1083 if (!tty_port_initialized(&info->port))
1084 return;
1085#ifdef ISDN_DEBUG_MODEM_OPEN
1086 printk(KERN_DEBUG "Shutting down isdnmodem port %d ....\n", info->line);
1087#endif
1088 isdn_unlock_drivers();
1089 info->msr &= ~UART_MSR_RI;
1090 if (!info->port.tty || (info->port.tty->termios.c_cflag & HUPCL)) {
1091 info->mcr &= ~(UART_MCR_DTR | UART_MCR_RTS);
1092 if (info->emu.mdmreg[REG_DTRHUP] & BIT_DTRHUP) {
1093 isdn_tty_modem_reset_regs(info, 0);
1094#ifdef ISDN_DEBUG_MODEM_HUP
1095 printk(KERN_DEBUG "Mhup in isdn_tty_shutdown\n");
1096#endif
1097 isdn_tty_modem_hup(info, 1);
1098 }
1099 }
1100 if (info->port.tty)
1101 set_bit(TTY_IO_ERROR, &info->port.tty->flags);
1102
1103 tty_port_set_initialized(&info->port, 0);
1104}
1105
1106/* isdn_tty_write() is the main send-routine. It is called from the upper
1107 * levels within the kernel to perform sending data. Depending on the
1108 * online-flag it either directs output to the at-command-interpreter or
1109 * to the lower level. Additional tasks done here:
1110 * - If online, check for escape-sequence (+++)
1111 * - If sending audio-data, call isdn_tty_DLEdown() to parse DLE-codes.
1112 * - If receiving audio-data, call isdn_tty_end_vrx() to abort if needed.
1113 * - If dialing, abort dial.
1114 */
1115static int
1116isdn_tty_write(struct tty_struct *tty, const u_char *buf, int count)
1117{
1118 int c;
1119 int total = 0;
1120 modem_info *info = (modem_info *) tty->driver_data;
1121 atemu *m = &info->emu;
1122
1123 if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_write"))
1124 return 0;
1125 /* See isdn_tty_senddown() */
1126 atomic_inc(&info->xmit_lock);
1127 while (1) {
1128 c = count;
1129 if (c > info->xmit_size - info->xmit_count)
1130 c = info->xmit_size - info->xmit_count;
1131 if (info->isdn_driver >= 0 && c > dev->drv[info->isdn_driver]->maxbufsize)
1132 c = dev->drv[info->isdn_driver]->maxbufsize;
1133 if (c <= 0)
1134 break;
1135 if ((info->online > 1)
1136#ifdef CONFIG_ISDN_AUDIO
1137 || (info->vonline & 3)
1138#endif
1139 ) {
1140#ifdef CONFIG_ISDN_AUDIO
1141 if (!info->vonline)
1142#endif
1143 isdn_tty_check_esc(buf, m->mdmreg[REG_ESC], c,
1144 &(m->pluscount),
1145 &(m->lastplus));
1146 memcpy(&info->port.xmit_buf[info->xmit_count], buf, c);
1147#ifdef CONFIG_ISDN_AUDIO
1148 if (info->vonline) {
1149 int cc = isdn_tty_handleDLEdown(info, m, c);
1150 if (info->vonline & 2) {
1151 if (!cc) {
1152 /* If DLE decoding results in zero-transmit, but
1153 * c originally was non-zero, do a wakeup.
1154 */
1155 tty_wakeup(tty);
1156 info->msr |= UART_MSR_CTS;
1157 info->lsr |= UART_LSR_TEMT;
1158 }
1159 info->xmit_count += cc;
1160 }
1161 if ((info->vonline & 3) == 1) {
1162 /* Do NOT handle Ctrl-Q or Ctrl-S
1163 * when in full-duplex audio mode.
1164 */
1165 if (isdn_tty_end_vrx(buf, c)) {
1166 info->vonline &= ~1;
1167#ifdef ISDN_DEBUG_MODEM_VOICE
1168 printk(KERN_DEBUG
1169 "got !^Q/^S, send DLE-ETX,VCON on ttyI%d\n",
1170 info->line);
1171#endif
1172 isdn_tty_at_cout("\020\003\r\nVCON\r\n", info);
1173 }
1174 }
1175 } else
1176 if (TTY_IS_FCLASS1(info)) {
1177 int cc = isdn_tty_handleDLEdown(info, m, c);
1178
1179 if (info->vonline & 4) { /* ETX seen */
1180 isdn_ctrl c;
1181
1182 c.command = ISDN_CMD_FAXCMD;
1183 c.driver = info->isdn_driver;
1184 c.arg = info->isdn_channel;
1185 c.parm.aux.cmd = ISDN_FAX_CLASS1_CTRL;
1186 c.parm.aux.subcmd = ETX;
1187 isdn_command(&c);
1188 }
1189 info->vonline = 0;
1190#ifdef ISDN_DEBUG_MODEM_VOICE
1191 printk(KERN_DEBUG "fax dle cc/c %d/%d\n", cc, c);
1192#endif
1193 info->xmit_count += cc;
1194 } else
1195#endif
1196 info->xmit_count += c;
1197 } else {
1198 info->msr |= UART_MSR_CTS;
1199 info->lsr |= UART_LSR_TEMT;
1200 if (info->dialing) {
1201 info->dialing = 0;
1202#ifdef ISDN_DEBUG_MODEM_HUP
1203 printk(KERN_DEBUG "Mhup in isdn_tty_write\n");
1204#endif
1205 isdn_tty_modem_result(RESULT_NO_CARRIER, info);
1206 isdn_tty_modem_hup(info, 1);
1207 } else
1208 c = isdn_tty_edit_at(buf, c, info);
1209 }
1210 buf += c;
1211 count -= c;
1212 total += c;
1213 }
1214 atomic_dec(&info->xmit_lock);
1215 if ((info->xmit_count) || !skb_queue_empty(&info->xmit_queue)) {
1216 if (m->mdmreg[REG_DXMT] & BIT_DXMT) {
1217 isdn_tty_senddown(info);
1218 isdn_tty_tint(info);
1219 }
1220 isdn_timer_ctrl(ISDN_TIMER_MODEMXMIT, 1);
1221 }
1222 return total;
1223}
1224
1225static int
1226isdn_tty_write_room(struct tty_struct *tty)
1227{
1228 modem_info *info = (modem_info *) tty->driver_data;
1229 int ret;
1230
1231 if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_write_room"))
1232 return 0;
1233 if (!info->online)
1234 return info->xmit_size;
1235 ret = info->xmit_size - info->xmit_count;
1236 return (ret < 0) ? 0 : ret;
1237}
1238
1239static int
1240isdn_tty_chars_in_buffer(struct tty_struct *tty)
1241{
1242 modem_info *info = (modem_info *) tty->driver_data;
1243
1244 if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_chars_in_buffer"))
1245 return 0;
1246 if (!info->online)
1247 return 0;
1248 return (info->xmit_count);
1249}
1250
1251static void
1252isdn_tty_flush_buffer(struct tty_struct *tty)
1253{
1254 modem_info *info;
1255
1256 if (!tty) {
1257 return;
1258 }
1259 info = (modem_info *) tty->driver_data;
1260 if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_flush_buffer")) {
1261 return;
1262 }
1263 isdn_tty_cleanup_xmit(info);
1264 info->xmit_count = 0;
1265 tty_wakeup(tty);
1266}
1267
1268static void
1269isdn_tty_flush_chars(struct tty_struct *tty)
1270{
1271 modem_info *info = (modem_info *) tty->driver_data;
1272
1273 if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_flush_chars"))
1274 return;
1275 if ((info->xmit_count) || !skb_queue_empty(&info->xmit_queue))
1276 isdn_timer_ctrl(ISDN_TIMER_MODEMXMIT, 1);
1277}
1278
1279/*
1280 * ------------------------------------------------------------
1281 * isdn_tty_throttle()
1282 *
1283 * This routine is called by the upper-layer tty layer to signal that
1284 * incoming characters should be throttled.
1285 * ------------------------------------------------------------
1286 */
1287static void
1288isdn_tty_throttle(struct tty_struct *tty)
1289{
1290 modem_info *info = (modem_info *) tty->driver_data;
1291
1292 if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_throttle"))
1293 return;
1294 if (I_IXOFF(tty))
1295 info->x_char = STOP_CHAR(tty);
1296 info->mcr &= ~UART_MCR_RTS;
1297}
1298
1299static void
1300isdn_tty_unthrottle(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_unthrottle"))
1305 return;
1306 if (I_IXOFF(tty)) {
1307 if (info->x_char)
1308 info->x_char = 0;
1309 else
1310 info->x_char = START_CHAR(tty);
1311 }
1312 info->mcr |= UART_MCR_RTS;
1313}
1314
1315/*
1316 * ------------------------------------------------------------
1317 * isdn_tty_ioctl() and friends
1318 * ------------------------------------------------------------
1319 */
1320
1321/*
1322 * isdn_tty_get_lsr_info - get line status register info
1323 *
1324 * Purpose: Let user call ioctl() to get info when the UART physically
1325 * is emptied. On bus types like RS485, the transmitter must
1326 * release the bus after transmitting. This must be done when
1327 * the transmit shift register is empty, not be done when the
1328 * transmit holding register is empty. This functionality
1329 * allows RS485 driver to be written in user space.
1330 */
1331static int
1332isdn_tty_get_lsr_info(modem_info *info, uint __user *value)
1333{
1334 u_char status;
1335 uint result;
1336
1337 status = info->lsr;
1338 result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
1339 return put_user(result, value);
1340}
1341
1342
1343static int
1344isdn_tty_tiocmget(struct tty_struct *tty)
1345{
1346 modem_info *info = (modem_info *) tty->driver_data;
1347 u_char control, status;
1348
1349 if (isdn_tty_paranoia_check(info, tty->name, __func__))
1350 return -ENODEV;
1351 if (tty_io_error(tty))
1352 return -EIO;
1353
1354 mutex_lock(&modem_info_mutex);
1355#ifdef ISDN_DEBUG_MODEM_IOCTL
1356 printk(KERN_DEBUG "ttyI%d ioctl TIOCMGET\n", info->line);
1357#endif
1358
1359 control = info->mcr;
1360 status = info->msr;
1361 mutex_unlock(&modem_info_mutex);
1362 return ((control & UART_MCR_RTS) ? TIOCM_RTS : 0)
1363 | ((control & UART_MCR_DTR) ? TIOCM_DTR : 0)
1364 | ((status & UART_MSR_DCD) ? TIOCM_CAR : 0)
1365 | ((status & UART_MSR_RI) ? TIOCM_RNG : 0)
1366 | ((status & UART_MSR_DSR) ? TIOCM_DSR : 0)
1367 | ((status & UART_MSR_CTS) ? TIOCM_CTS : 0);
1368}
1369
1370static int
1371isdn_tty_tiocmset(struct tty_struct *tty,
1372 unsigned int set, unsigned int clear)
1373{
1374 modem_info *info = (modem_info *) tty->driver_data;
1375
1376 if (isdn_tty_paranoia_check(info, tty->name, __func__))
1377 return -ENODEV;
1378 if (tty_io_error(tty))
1379 return -EIO;
1380
1381#ifdef ISDN_DEBUG_MODEM_IOCTL
1382 printk(KERN_DEBUG "ttyI%d ioctl TIOCMxxx: %x %x\n", info->line, set, clear);
1383#endif
1384
1385 mutex_lock(&modem_info_mutex);
1386 if (set & TIOCM_RTS)
1387 info->mcr |= UART_MCR_RTS;
1388 if (set & TIOCM_DTR) {
1389 info->mcr |= UART_MCR_DTR;
1390 isdn_tty_modem_ncarrier(info);
1391 }
1392
1393 if (clear & TIOCM_RTS)
1394 info->mcr &= ~UART_MCR_RTS;
1395 if (clear & TIOCM_DTR) {
1396 info->mcr &= ~UART_MCR_DTR;
1397 if (info->emu.mdmreg[REG_DTRHUP] & BIT_DTRHUP) {
1398 isdn_tty_modem_reset_regs(info, 0);
1399#ifdef ISDN_DEBUG_MODEM_HUP
1400 printk(KERN_DEBUG "Mhup in TIOCMSET\n");
1401#endif
1402 if (info->online)
1403 info->ncarrier = 1;
1404 isdn_tty_modem_hup(info, 1);
1405 }
1406 }
1407 mutex_unlock(&modem_info_mutex);
1408 return 0;
1409}
1410
1411static int
1412isdn_tty_ioctl(struct tty_struct *tty, uint cmd, ulong arg)
1413{
1414 modem_info *info = (modem_info *) tty->driver_data;
1415
1416 if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_ioctl"))
1417 return -ENODEV;
1418 if (tty_io_error(tty))
1419 return -EIO;
1420 switch (cmd) {
1421 case TIOCSERGETLSR: /* Get line status register */
1422#ifdef ISDN_DEBUG_MODEM_IOCTL
1423 printk(KERN_DEBUG "ttyI%d ioctl TIOCSERGETLSR\n", info->line);
1424#endif
1425 return isdn_tty_get_lsr_info(info, (uint __user *) arg);
1426 default:
1427#ifdef ISDN_DEBUG_MODEM_IOCTL
1428 printk(KERN_DEBUG "UNKNOWN ioctl 0x%08x on ttyi%d\n", cmd, info->line);
1429#endif
1430 return -ENOIOCTLCMD;
1431 }
1432 return 0;
1433}
1434
1435static void
1436isdn_tty_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
1437{
1438 modem_info *info = (modem_info *) tty->driver_data;
1439
1440 mutex_lock(&modem_info_mutex);
1441 if (!old_termios)
1442 isdn_tty_change_speed(info);
1443 else {
1444 if (tty->termios.c_cflag == old_termios->c_cflag &&
1445 tty->termios.c_ispeed == old_termios->c_ispeed &&
1446 tty->termios.c_ospeed == old_termios->c_ospeed) {
1447 mutex_unlock(&modem_info_mutex);
1448 return;
1449 }
1450 isdn_tty_change_speed(info);
1451 }
1452 mutex_unlock(&modem_info_mutex);
1453}
1454
1455/*
1456 * ------------------------------------------------------------
1457 * isdn_tty_open() and friends
1458 * ------------------------------------------------------------
1459 */
1460
1461static int isdn_tty_install(struct tty_driver *driver, struct tty_struct *tty)
1462{
1463 modem_info *info = &dev->mdm.info[tty->index];
1464
1465 if (isdn_tty_paranoia_check(info, tty->name, __func__))
1466 return -ENODEV;
1467
1468 tty->driver_data = info;
1469
1470 return tty_port_install(&info->port, driver, tty);
1471}
1472
1473/*
1474 * This routine is called whenever a serial port is opened. It
1475 * enables interrupts for a serial port, linking in its async structure into
1476 * the IRQ chain. It also performs the serial-specific
1477 * initialization for the tty structure.
1478 */
1479static int
1480isdn_tty_open(struct tty_struct *tty, struct file *filp)
1481{
1482 modem_info *info = tty->driver_data;
1483 struct tty_port *port = &info->port;
1484 int retval;
1485
1486#ifdef ISDN_DEBUG_MODEM_OPEN
1487 printk(KERN_DEBUG "isdn_tty_open %s, count = %d\n", tty->name,
1488 port->count);
1489#endif
1490 port->count++;
1491 port->tty = tty;
1492 /*
1493 * Start up serial port
1494 */
1495 retval = isdn_tty_startup(info);
1496 if (retval) {
1497#ifdef ISDN_DEBUG_MODEM_OPEN
1498 printk(KERN_DEBUG "isdn_tty_open return after startup\n");
1499#endif
1500 return retval;
1501 }
1502 retval = tty_port_block_til_ready(port, tty, filp);
1503 if (retval) {
1504#ifdef ISDN_DEBUG_MODEM_OPEN
1505 printk(KERN_DEBUG "isdn_tty_open return after isdn_tty_block_til_ready \n");
1506#endif
1507 return retval;
1508 }
1509#ifdef ISDN_DEBUG_MODEM_OPEN
1510 printk(KERN_DEBUG "isdn_tty_open ttyi%d successful...\n", info->line);
1511#endif
1512 dev->modempoll++;
1513#ifdef ISDN_DEBUG_MODEM_OPEN
1514 printk(KERN_DEBUG "isdn_tty_open normal exit\n");
1515#endif
1516 return 0;
1517}
1518
1519static void
1520isdn_tty_close(struct tty_struct *tty, struct file *filp)
1521{
1522 modem_info *info = (modem_info *) tty->driver_data;
1523 struct tty_port *port = &info->port;
1524 ulong timeout;
1525
1526 if (!info || isdn_tty_paranoia_check(info, tty->name, "isdn_tty_close"))
1527 return;
1528 if (tty_hung_up_p(filp)) {
1529#ifdef ISDN_DEBUG_MODEM_OPEN
1530 printk(KERN_DEBUG "isdn_tty_close return after tty_hung_up_p\n");
1531#endif
1532 return;
1533 }
1534 if ((tty->count == 1) && (port->count != 1)) {
1535 /*
1536 * Uh, oh. tty->count is 1, which means that the tty
1537 * structure will be freed. Info->count should always
1538 * be one in these conditions. If it's greater than
1539 * one, we've got real problems, since it means the
1540 * serial port won't be shutdown.
1541 */
1542 printk(KERN_ERR "isdn_tty_close: bad port count; tty->count is 1, "
1543 "info->count is %d\n", port->count);
1544 port->count = 1;
1545 }
1546 if (--port->count < 0) {
1547 printk(KERN_ERR "isdn_tty_close: bad port count for ttyi%d: %d\n",
1548 info->line, port->count);
1549 port->count = 0;
1550 }
1551 if (port->count) {
1552#ifdef ISDN_DEBUG_MODEM_OPEN
1553 printk(KERN_DEBUG "isdn_tty_close after info->count != 0\n");
1554#endif
1555 return;
1556 }
1557 info->closing = 1;
1558
1559 tty->closing = 1;
1560 /*
1561 * At this point we stop accepting input. To do this, we
1562 * disable the receive line status interrupts, and tell the
1563 * interrupt driver to stop checking the data ready bit in the
1564 * line status register.
1565 */
1566 if (tty_port_initialized(port)) {
1567 tty_wait_until_sent(tty, 3000); /* 30 seconds timeout */
1568 /*
1569 * Before we drop DTR, make sure the UART transmitter
1570 * has completely drained; this is especially
1571 * important if there is a transmit FIFO!
1572 */
1573 timeout = jiffies + HZ;
1574 while (!(info->lsr & UART_LSR_TEMT)) {
1575 schedule_timeout_interruptible(20);
1576 if (time_after(jiffies, timeout))
1577 break;
1578 }
1579 }
1580 dev->modempoll--;
1581 isdn_tty_shutdown(info);
1582 isdn_tty_flush_buffer(tty);
1583 tty_ldisc_flush(tty);
1584 port->tty = NULL;
1585 info->ncarrier = 0;
1586
1587 tty_port_close_end(port, tty);
1588 info->closing = 0;
1589#ifdef ISDN_DEBUG_MODEM_OPEN
1590 printk(KERN_DEBUG "isdn_tty_close normal exit\n");
1591#endif
1592}
1593
1594/*
1595 * isdn_tty_hangup() --- called by tty_hangup() when a hangup is signaled.
1596 */
1597static void
1598isdn_tty_hangup(struct tty_struct *tty)
1599{
1600 modem_info *info = (modem_info *) tty->driver_data;
1601 struct tty_port *port = &info->port;
1602
1603 if (isdn_tty_paranoia_check(info, tty->name, "isdn_tty_hangup"))
1604 return;
1605 isdn_tty_shutdown(info);
1606 port->count = 0;
1607 tty_port_set_active(port, 0);
1608 port->tty = NULL;
1609 wake_up_interruptible(&port->open_wait);
1610}
1611
1612/* This routine initializes all emulator-data.
1613 */
1614static void
1615isdn_tty_reset_profile(atemu *m)
1616{
1617 m->profile[0] = 0;
1618 m->profile[1] = 0;
1619 m->profile[2] = 43;
1620 m->profile[3] = 13;
1621 m->profile[4] = 10;
1622 m->profile[5] = 8;
1623 m->profile[6] = 3;
1624 m->profile[7] = 60;
1625 m->profile[8] = 2;
1626 m->profile[9] = 6;
1627 m->profile[10] = 7;
1628 m->profile[11] = 70;
1629 m->profile[12] = 0x45;
1630 m->profile[13] = 4;
1631 m->profile[14] = ISDN_PROTO_L2_X75I;
1632 m->profile[15] = ISDN_PROTO_L3_TRANS;
1633 m->profile[16] = ISDN_SERIAL_XMIT_SIZE / 16;
1634 m->profile[17] = ISDN_MODEM_WINSIZE;
1635 m->profile[18] = 4;
1636 m->profile[19] = 0;
1637 m->profile[20] = 0;
1638 m->profile[23] = 0;
1639 m->pmsn[0] = '\0';
1640 m->plmsn[0] = '\0';
1641}
1642
1643#ifdef CONFIG_ISDN_AUDIO
1644static void
1645isdn_tty_modem_reset_vpar(atemu *m)
1646{
1647 m->vpar[0] = 2; /* Voice-device (2 = phone line) */
1648 m->vpar[1] = 0; /* Silence detection level (0 = none ) */
1649 m->vpar[2] = 70; /* Silence interval (7 sec. ) */
1650 m->vpar[3] = 2; /* Compression type (1 = ADPCM-2 ) */
1651 m->vpar[4] = 0; /* DTMF detection level (0 = softcode ) */
1652 m->vpar[5] = 8; /* DTMF interval (8 * 5 ms. ) */
1653}
1654#endif
1655
1656#ifdef CONFIG_ISDN_TTY_FAX
1657static void
1658isdn_tty_modem_reset_faxpar(modem_info *info)
1659{
1660 T30_s *f = info->fax;
1661
1662 f->code = 0;
1663 f->phase = ISDN_FAX_PHASE_IDLE;
1664 f->direction = 0;
1665 f->resolution = 1; /* fine */
1666 f->rate = 5; /* 14400 bit/s */
1667 f->width = 0;
1668 f->length = 0;
1669 f->compression = 0;
1670 f->ecm = 0;
1671 f->binary = 0;
1672 f->scantime = 0;
1673 memset(&f->id[0], 32, FAXIDLEN - 1);
1674 f->id[FAXIDLEN - 1] = 0;
1675 f->badlin = 0;
1676 f->badmul = 0;
1677 f->bor = 0;
1678 f->nbc = 0;
1679 f->cq = 0;
1680 f->cr = 0;
1681 f->ctcrty = 0;
1682 f->minsp = 0;
1683 f->phcto = 30;
1684 f->rel = 0;
1685 memset(&f->pollid[0], 32, FAXIDLEN - 1);
1686 f->pollid[FAXIDLEN - 1] = 0;
1687}
1688#endif
1689
1690static void
1691isdn_tty_modem_reset_regs(modem_info *info, int force)
1692{
1693 atemu *m = &info->emu;
1694 if ((m->mdmreg[REG_DTRR] & BIT_DTRR) || force) {
1695 memcpy(m->mdmreg, m->profile, ISDN_MODEM_NUMREG);
1696 memcpy(m->msn, m->pmsn, ISDN_MSNLEN);
1697 memcpy(m->lmsn, m->plmsn, ISDN_LMSNLEN);
1698 info->xmit_size = m->mdmreg[REG_PSIZE] * 16;
1699 }
1700#ifdef CONFIG_ISDN_AUDIO
1701 isdn_tty_modem_reset_vpar(m);
1702#endif
1703#ifdef CONFIG_ISDN_TTY_FAX
1704 isdn_tty_modem_reset_faxpar(info);
1705#endif
1706 m->mdmcmdl = 0;
1707}
1708
1709static void
1710modem_write_profile(atemu *m)
1711{
1712 memcpy(m->profile, m->mdmreg, ISDN_MODEM_NUMREG);
1713 memcpy(m->pmsn, m->msn, ISDN_MSNLEN);
1714 memcpy(m->plmsn, m->lmsn, ISDN_LMSNLEN);
1715 if (dev->profd)
1716 send_sig(SIGIO, dev->profd, 1);
1717}
1718
1719static const struct tty_operations modem_ops = {
1720 .install = isdn_tty_install,
1721 .open = isdn_tty_open,
1722 .close = isdn_tty_close,
1723 .write = isdn_tty_write,
1724 .flush_chars = isdn_tty_flush_chars,
1725 .write_room = isdn_tty_write_room,
1726 .chars_in_buffer = isdn_tty_chars_in_buffer,
1727 .flush_buffer = isdn_tty_flush_buffer,
1728 .ioctl = isdn_tty_ioctl,
1729 .throttle = isdn_tty_throttle,
1730 .unthrottle = isdn_tty_unthrottle,
1731 .set_termios = isdn_tty_set_termios,
1732 .hangup = isdn_tty_hangup,
1733 .tiocmget = isdn_tty_tiocmget,
1734 .tiocmset = isdn_tty_tiocmset,
1735};
1736
1737static int isdn_tty_carrier_raised(struct tty_port *port)
1738{
1739 modem_info *info = container_of(port, modem_info, port);
1740 return info->msr & UART_MSR_DCD;
1741}
1742
1743static const struct tty_port_operations isdn_tty_port_ops = {
1744 .carrier_raised = isdn_tty_carrier_raised,
1745};
1746
1747int
1748isdn_tty_modem_init(void)
1749{
1750 isdn_modem_t *m;
1751 int i, retval;
1752 modem_info *info;
1753
1754 m = &dev->mdm;
1755 m->tty_modem = alloc_tty_driver(ISDN_MAX_CHANNELS);
1756 if (!m->tty_modem)
1757 return -ENOMEM;
1758 m->tty_modem->name = "ttyI";
1759 m->tty_modem->major = ISDN_TTY_MAJOR;
1760 m->tty_modem->minor_start = 0;
1761 m->tty_modem->type = TTY_DRIVER_TYPE_SERIAL;
1762 m->tty_modem->subtype = SERIAL_TYPE_NORMAL;
1763 m->tty_modem->init_termios = tty_std_termios;
1764 m->tty_modem->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
1765 m->tty_modem->flags = TTY_DRIVER_REAL_RAW;
1766 m->tty_modem->driver_name = "isdn_tty";
1767 tty_set_operations(m->tty_modem, &modem_ops);
1768 retval = tty_register_driver(m->tty_modem);
1769 if (retval) {
1770 printk(KERN_WARNING "isdn_tty: Couldn't register modem-device\n");
1771 goto err;
1772 }
1773 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
1774 info = &m->info[i];
1775#ifdef CONFIG_ISDN_TTY_FAX
1776 if (!(info->fax = kmalloc(sizeof(T30_s), GFP_KERNEL))) {
1777 printk(KERN_ERR "Could not allocate fax t30-buffer\n");
1778 retval = -ENOMEM;
1779 goto err_unregister;
1780 }
1781#endif
1782 tty_port_init(&info->port);
1783 info->port.ops = &isdn_tty_port_ops;
1784 spin_lock_init(&info->readlock);
1785 sprintf(info->last_cause, "0000");
1786 sprintf(info->last_num, "none");
1787 info->last_dir = 0;
1788 info->last_lhup = 1;
1789 info->last_l2 = -1;
1790 info->last_si = 0;
1791 isdn_tty_reset_profile(&info->emu);
1792 isdn_tty_modem_reset_regs(info, 1);
1793 info->magic = ISDN_ASYNC_MAGIC;
1794 info->line = i;
1795 info->x_char = 0;
1796 info->isdn_driver = -1;
1797 info->isdn_channel = -1;
1798 info->drv_index = -1;
1799 info->xmit_size = ISDN_SERIAL_XMIT_SIZE;
1800 timer_setup(&info->nc_timer, isdn_tty_modem_do_ncarrier, 0);
1801 skb_queue_head_init(&info->xmit_queue);
1802#ifdef CONFIG_ISDN_AUDIO
1803 skb_queue_head_init(&info->dtmf_queue);
1804#endif
1805 info->port.xmit_buf = kmalloc(ISDN_SERIAL_XMIT_MAX + 5,
1806 GFP_KERNEL);
1807 if (!info->port.xmit_buf) {
1808 printk(KERN_ERR "Could not allocate modem xmit-buffer\n");
1809 retval = -ENOMEM;
1810 goto err_unregister;
1811 }
1812 /* Make room for T.70 header */
1813 info->port.xmit_buf += 4;
1814 }
1815 return 0;
1816err_unregister:
1817 for (i--; i >= 0; i--) {
1818 info = &m->info[i];
1819#ifdef CONFIG_ISDN_TTY_FAX
1820 kfree(info->fax);
1821#endif
1822 kfree(info->port.xmit_buf - 4);
1823 info->port.xmit_buf = NULL;
1824 tty_port_destroy(&info->port);
1825 }
1826 tty_unregister_driver(m->tty_modem);
1827err:
1828 put_tty_driver(m->tty_modem);
1829 m->tty_modem = NULL;
1830 return retval;
1831}
1832
1833void
1834isdn_tty_exit(void)
1835{
1836 modem_info *info;
1837 int i;
1838
1839 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
1840 info = &dev->mdm.info[i];
1841 isdn_tty_cleanup_xmit(info);
1842#ifdef CONFIG_ISDN_TTY_FAX
1843 kfree(info->fax);
1844#endif
1845 kfree(info->port.xmit_buf - 4);
1846 info->port.xmit_buf = NULL;
1847 tty_port_destroy(&info->port);
1848 }
1849 tty_unregister_driver(dev->mdm.tty_modem);
1850 put_tty_driver(dev->mdm.tty_modem);
1851 dev->mdm.tty_modem = NULL;
1852}
1853
1854
1855/*
1856 * isdn_tty_match_icall(char *MSN, atemu *tty_emulator, int dev_idx)
1857 * match the MSN against the MSNs (glob patterns) defined for tty_emulator,
1858 * and return 0 for match, 1 for no match, 2 if MSN could match if longer.
1859 */
1860
1861static int
1862isdn_tty_match_icall(char *cid, atemu *emu, int di)
1863{
1864#ifdef ISDN_DEBUG_MODEM_ICALL
1865 printk(KERN_DEBUG "m_fi: msn=%s lmsn=%s mmsn=%s mreg[SI1]=%d mreg[SI2]=%d\n",
1866 emu->msn, emu->lmsn, isdn_map_eaz2msn(emu->msn, di),
1867 emu->mdmreg[REG_SI1], emu->mdmreg[REG_SI2]);
1868#endif
1869 if (strlen(emu->lmsn)) {
1870 char *p = emu->lmsn;
1871 char *q;
1872 int tmp;
1873 int ret = 0;
1874
1875 while (1) {
1876 if ((q = strchr(p, ';')))
1877 *q = '\0';
1878 if ((tmp = isdn_msncmp(cid, isdn_map_eaz2msn(p, di))) > ret)
1879 ret = tmp;
1880#ifdef ISDN_DEBUG_MODEM_ICALL
1881 printk(KERN_DEBUG "m_fi: lmsnX=%s mmsn=%s -> tmp=%d\n",
1882 p, isdn_map_eaz2msn(emu->msn, di), tmp);
1883#endif
1884 if (q) {
1885 *q = ';';
1886 p = q;
1887 p++;
1888 }
1889 if (!tmp)
1890 return 0;
1891 if (!q)
1892 break;
1893 }
1894 return ret;
1895 } else {
1896 int tmp;
1897 tmp = isdn_msncmp(cid, isdn_map_eaz2msn(emu->msn, di));
1898#ifdef ISDN_DEBUG_MODEM_ICALL
1899 printk(KERN_DEBUG "m_fi: mmsn=%s -> tmp=%d\n",
1900 isdn_map_eaz2msn(emu->msn, di), tmp);
1901#endif
1902 return tmp;
1903 }
1904}
1905
1906/*
1907 * An incoming call-request has arrived.
1908 * Search the tty-devices for an appropriate device and bind
1909 * it to the ISDN-Channel.
1910 * Return:
1911 *
1912 * 0 = No matching device found.
1913 * 1 = A matching device found.
1914 * 3 = No match found, but eventually would match, if
1915 * CID is longer.
1916 */
1917int
1918isdn_tty_find_icall(int di, int ch, setup_parm *setup)
1919{
1920 char *eaz;
1921 int i;
1922 int wret;
1923 int idx;
1924 int si1;
1925 int si2;
1926 char *nr;
1927 ulong flags;
1928
1929 if (!setup->phone[0]) {
1930 nr = "0";
1931 printk(KERN_INFO "isdn_tty: Incoming call without OAD, assuming '0'\n");
1932 } else
1933 nr = setup->phone;
1934 si1 = (int) setup->si1;
1935 si2 = (int) setup->si2;
1936 if (!setup->eazmsn[0]) {
1937 printk(KERN_WARNING "isdn_tty: Incoming call without CPN, assuming '0'\n");
1938 eaz = "0";
1939 } else
1940 eaz = setup->eazmsn;
1941#ifdef ISDN_DEBUG_MODEM_ICALL
1942 printk(KERN_DEBUG "m_fi: eaz=%s si1=%d si2=%d\n", eaz, si1, si2);
1943#endif
1944 wret = 0;
1945 spin_lock_irqsave(&dev->lock, flags);
1946 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
1947 modem_info *info = &dev->mdm.info[i];
1948
1949 if (info->port.count == 0)
1950 continue;
1951 if ((info->emu.mdmreg[REG_SI1] & si2bit[si1]) && /* SI1 is matching */
1952 (info->emu.mdmreg[REG_SI2] == si2)) { /* SI2 is matching */
1953 idx = isdn_dc2minor(di, ch);
1954#ifdef ISDN_DEBUG_MODEM_ICALL
1955 printk(KERN_DEBUG "m_fi: match1 wret=%d\n", wret);
1956 printk(KERN_DEBUG "m_fi: idx=%d flags=%08lx drv=%d ch=%d usg=%d\n", idx,
1957 info->port.flags, info->isdn_driver,
1958 info->isdn_channel, dev->usage[idx]);
1959#endif
1960 if (
1961#ifndef FIX_FILE_TRANSFER
1962 tty_port_active(&info->port) &&
1963#endif
1964 (info->isdn_driver == -1) &&
1965 (info->isdn_channel == -1) &&
1966 (USG_NONE(dev->usage[idx]))) {
1967 int matchret;
1968
1969 if ((matchret = isdn_tty_match_icall(eaz, &info->emu, di)) > wret)
1970 wret = matchret;
1971 if (!matchret) { /* EAZ is matching */
1972 info->isdn_driver = di;
1973 info->isdn_channel = ch;
1974 info->drv_index = idx;
1975 dev->m_idx[idx] = info->line;
1976 dev->usage[idx] &= ISDN_USAGE_EXCLUSIVE;
1977 dev->usage[idx] |= isdn_calc_usage(si1, info->emu.mdmreg[REG_L2PROT]);
1978 strcpy(dev->num[idx], nr);
1979 strcpy(info->emu.cpn, eaz);
1980 info->emu.mdmreg[REG_SI1I] = si2bit[si1];
1981 info->emu.mdmreg[REG_PLAN] = setup->plan;
1982 info->emu.mdmreg[REG_SCREEN] = setup->screen;
1983 isdn_info_update();
1984 spin_unlock_irqrestore(&dev->lock, flags);
1985 printk(KERN_INFO "isdn_tty: call from %s, -> RING on ttyI%d\n", nr,
1986 info->line);
1987 info->msr |= UART_MSR_RI;
1988 isdn_tty_modem_result(RESULT_RING, info);
1989 isdn_timer_ctrl(ISDN_TIMER_MODEMRING, 1);
1990 return 1;
1991 }
1992 }
1993 }
1994 }
1995 spin_unlock_irqrestore(&dev->lock, flags);
1996 printk(KERN_INFO "isdn_tty: call from %s -> %s %s\n", nr, eaz,
1997 ((dev->drv[di]->flags & DRV_FLAG_REJBUS) && (wret != 2)) ? "rejected" : "ignored");
1998 return (wret == 2) ? 3 : 0;
1999}
2000
2001int
2002isdn_tty_stat_callback(int i, isdn_ctrl *c)
2003{
2004 int mi;
2005 modem_info *info;
2006 char *e;
2007
2008 if (i < 0)
2009 return 0;
2010 if ((mi = dev->m_idx[i]) >= 0) {
2011 info = &dev->mdm.info[mi];
2012 switch (c->command) {
2013 case ISDN_STAT_CINF:
2014 printk(KERN_DEBUG "CHARGEINFO on ttyI%d: %ld %s\n", info->line, c->arg, c->parm.num);
2015 info->emu.charge = (unsigned) simple_strtoul(c->parm.num, &e, 10);
2016 if (e == (char *)c->parm.num)
2017 info->emu.charge = 0;
2018
2019 break;
2020 case ISDN_STAT_BSENT:
2021#ifdef ISDN_TTY_STAT_DEBUG
2022 printk(KERN_DEBUG "tty_STAT_BSENT ttyI%d\n", info->line);
2023#endif
2024 if ((info->isdn_driver == c->driver) &&
2025 (info->isdn_channel == c->arg)) {
2026 info->msr |= UART_MSR_CTS;
2027 if (info->send_outstanding)
2028 if (!(--info->send_outstanding))
2029 info->lsr |= UART_LSR_TEMT;
2030 isdn_tty_tint(info);
2031 return 1;
2032 }
2033 break;
2034 case ISDN_STAT_CAUSE:
2035#ifdef ISDN_TTY_STAT_DEBUG
2036 printk(KERN_DEBUG "tty_STAT_CAUSE ttyI%d\n", info->line);
2037#endif
2038 /* Signal cause to tty-device */
2039 strncpy(info->last_cause, c->parm.num, 5);
2040 return 1;
2041 case ISDN_STAT_DISPLAY:
2042#ifdef ISDN_TTY_STAT_DEBUG
2043 printk(KERN_DEBUG "tty_STAT_DISPLAY ttyI%d\n", info->line);
2044#endif
2045 /* Signal display to tty-device */
2046 if ((info->emu.mdmreg[REG_DISPLAY] & BIT_DISPLAY) &&
2047 !(info->emu.mdmreg[REG_RESPNUM] & BIT_RESPNUM)) {
2048 isdn_tty_at_cout("\r\n", info);
2049 isdn_tty_at_cout("DISPLAY: ", info);
2050 isdn_tty_at_cout(c->parm.display, info);
2051 isdn_tty_at_cout("\r\n", info);
2052 }
2053 return 1;
2054 case ISDN_STAT_DCONN:
2055#ifdef ISDN_TTY_STAT_DEBUG
2056 printk(KERN_DEBUG "tty_STAT_DCONN ttyI%d\n", info->line);
2057#endif
2058 if (tty_port_active(&info->port)) {
2059 if (info->dialing == 1) {
2060 info->dialing = 2;
2061 return 1;
2062 }
2063 }
2064 break;
2065 case ISDN_STAT_DHUP:
2066#ifdef ISDN_TTY_STAT_DEBUG
2067 printk(KERN_DEBUG "tty_STAT_DHUP ttyI%d\n", info->line);
2068#endif
2069 if (tty_port_active(&info->port)) {
2070 if (info->dialing == 1)
2071 isdn_tty_modem_result(RESULT_BUSY, info);
2072 if (info->dialing > 1)
2073 isdn_tty_modem_result(RESULT_NO_CARRIER, info);
2074 info->dialing = 0;
2075#ifdef ISDN_DEBUG_MODEM_HUP
2076 printk(KERN_DEBUG "Mhup in ISDN_STAT_DHUP\n");
2077#endif
2078 isdn_tty_modem_hup(info, 0);
2079 return 1;
2080 }
2081 break;
2082 case ISDN_STAT_BCONN:
2083#ifdef ISDN_TTY_STAT_DEBUG
2084 printk(KERN_DEBUG "tty_STAT_BCONN ttyI%d\n", info->line);
2085#endif
2086 /* Wake up any processes waiting
2087 * for incoming call of this device when
2088 * DCD follow the state of incoming carrier
2089 */
2090 if (info->port.blocked_open &&
2091 (info->emu.mdmreg[REG_DCD] & BIT_DCD)) {
2092 wake_up_interruptible(&info->port.open_wait);
2093 }
2094
2095 /* Schedule CONNECT-Message to any tty
2096 * waiting for it and
2097 * set DCD-bit of its modem-status.
2098 */
2099 if (tty_port_active(&info->port) ||
2100 (info->port.blocked_open &&
2101 (info->emu.mdmreg[REG_DCD] & BIT_DCD))) {
2102 info->msr |= UART_MSR_DCD;
2103 info->emu.charge = 0;
2104 if (info->dialing & 0xf)
2105 info->last_dir = 1;
2106 else
2107 info->last_dir = 0;
2108 info->dialing = 0;
2109 info->rcvsched = 1;
2110 if (USG_MODEM(dev->usage[i])) {
2111 if (info->emu.mdmreg[REG_L2PROT] == ISDN_PROTO_L2_MODEM) {
2112 strcpy(info->emu.connmsg, c->parm.num);
2113 isdn_tty_modem_result(RESULT_CONNECT, info);
2114 } else
2115 isdn_tty_modem_result(RESULT_CONNECT64000, info);
2116 }
2117 if (USG_VOICE(dev->usage[i]))
2118 isdn_tty_modem_result(RESULT_VCON, info);
2119 return 1;
2120 }
2121 break;
2122 case ISDN_STAT_BHUP:
2123#ifdef ISDN_TTY_STAT_DEBUG
2124 printk(KERN_DEBUG "tty_STAT_BHUP ttyI%d\n", info->line);
2125#endif
2126 if (tty_port_active(&info->port)) {
2127#ifdef ISDN_DEBUG_MODEM_HUP
2128 printk(KERN_DEBUG "Mhup in ISDN_STAT_BHUP\n");
2129#endif
2130 isdn_tty_modem_hup(info, 0);
2131 return 1;
2132 }
2133 break;
2134 case ISDN_STAT_NODCH:
2135#ifdef ISDN_TTY_STAT_DEBUG
2136 printk(KERN_DEBUG "tty_STAT_NODCH ttyI%d\n", info->line);
2137#endif
2138 if (tty_port_active(&info->port)) {
2139 if (info->dialing) {
2140 info->dialing = 0;
2141 info->last_l2 = -1;
2142 info->last_si = 0;
2143 sprintf(info->last_cause, "0000");
2144 isdn_tty_modem_result(RESULT_NO_DIALTONE, info);
2145 }
2146 isdn_tty_modem_hup(info, 0);
2147 return 1;
2148 }
2149 break;
2150 case ISDN_STAT_UNLOAD:
2151#ifdef ISDN_TTY_STAT_DEBUG
2152 printk(KERN_DEBUG "tty_STAT_UNLOAD ttyI%d\n", info->line);
2153#endif
2154 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
2155 info = &dev->mdm.info[i];
2156 if (info->isdn_driver == c->driver) {
2157 if (info->online)
2158 isdn_tty_modem_hup(info, 1);
2159 }
2160 }
2161 return 1;
2162#ifdef CONFIG_ISDN_TTY_FAX
2163 case ISDN_STAT_FAXIND:
2164 if (tty_port_active(&info->port)) {
2165 isdn_tty_fax_command(info, c);
2166 }
2167 break;
2168#endif
2169#ifdef CONFIG_ISDN_AUDIO
2170 case ISDN_STAT_AUDIO:
2171 if (tty_port_active(&info->port)) {
2172 switch (c->parm.num[0]) {
2173 case ISDN_AUDIO_DTMF:
2174 if (info->vonline) {
2175 isdn_audio_put_dle_code(info,
2176 c->parm.num[1]);
2177 }
2178 break;
2179 }
2180 }
2181 break;
2182#endif
2183 }
2184 }
2185 return 0;
2186}
2187
2188/*********************************************************************
2189 Modem-Emulator-Routines
2190*********************************************************************/
2191
2192#define cmdchar(c) ((c >= ' ') && (c <= 0x7f))
2193
2194/*
2195 * Put a message from the AT-emulator into receive-buffer of tty,
2196 * convert CR, LF, and BS to values in modem-registers 3, 4 and 5.
2197 */
2198void
2199isdn_tty_at_cout(char *msg, modem_info *info)
2200{
2201 struct tty_port *port = &info->port;
2202 atemu *m = &info->emu;
2203 char *p;
2204 char c;
2205 u_long flags;
2206 struct sk_buff *skb = NULL;
2207 char *sp = NULL;
2208 int l;
2209
2210 if (!msg) {
2211 printk(KERN_WARNING "isdn_tty: Null-Message in isdn_tty_at_cout\n");
2212 return;
2213 }
2214
2215 l = strlen(msg);
2216
2217 spin_lock_irqsave(&info->readlock, flags);
2218 if (info->closing) {
2219 spin_unlock_irqrestore(&info->readlock, flags);
2220 return;
2221 }
2222
2223 /* use queue instead of direct, if online and */
2224 /* data is in queue or buffer is full */
2225 if (info->online && ((tty_buffer_request_room(port, l) < l) ||
2226 !skb_queue_empty(&dev->drv[info->isdn_driver]->rpqueue[info->isdn_channel]))) {
2227 skb = alloc_skb(l, GFP_ATOMIC);
2228 if (!skb) {
2229 spin_unlock_irqrestore(&info->readlock, flags);
2230 return;
2231 }
2232 sp = skb_put(skb, l);
2233#ifdef CONFIG_ISDN_AUDIO
2234 ISDN_AUDIO_SKB_DLECOUNT(skb) = 0;
2235 ISDN_AUDIO_SKB_LOCK(skb) = 0;
2236#endif
2237 }
2238
2239 for (p = msg; *p; p++) {
2240 switch (*p) {
2241 case '\r':
2242 c = m->mdmreg[REG_CR];
2243 break;
2244 case '\n':
2245 c = m->mdmreg[REG_LF];
2246 break;
2247 case '\b':
2248 c = m->mdmreg[REG_BS];
2249 break;
2250 default:
2251 c = *p;
2252 }
2253 if (skb) {
2254 *sp++ = c;
2255 } else {
2256 if (tty_insert_flip_char(port, c, TTY_NORMAL) == 0)
2257 break;
2258 }
2259 }
2260 if (skb) {
2261 __skb_queue_tail(&dev->drv[info->isdn_driver]->rpqueue[info->isdn_channel], skb);
2262 dev->drv[info->isdn_driver]->rcvcount[info->isdn_channel] += skb->len;
2263 spin_unlock_irqrestore(&info->readlock, flags);
2264 /* Schedule dequeuing */
2265 if (dev->modempoll && info->rcvsched)
2266 isdn_timer_ctrl(ISDN_TIMER_MODEMREAD, 1);
2267
2268 } else {
2269 spin_unlock_irqrestore(&info->readlock, flags);
2270 tty_flip_buffer_push(port);
2271 }
2272}
2273
2274/*
2275 * Perform ATH Hangup
2276 */
2277static void
2278isdn_tty_on_hook(modem_info *info)
2279{
2280 if (info->isdn_channel >= 0) {
2281#ifdef ISDN_DEBUG_MODEM_HUP
2282 printk(KERN_DEBUG "Mhup in isdn_tty_on_hook\n");
2283#endif
2284 isdn_tty_modem_hup(info, 1);
2285 }
2286}
2287
2288static void
2289isdn_tty_off_hook(void)
2290{
2291 printk(KERN_DEBUG "isdn_tty_off_hook\n");
2292}
2293
2294#define PLUSWAIT1 (HZ / 2) /* 0.5 sec. */
2295#define PLUSWAIT2 (HZ * 3 / 2) /* 1.5 sec */
2296
2297/*
2298 * Check Buffer for Modem-escape-sequence, activate timer-callback to
2299 * isdn_tty_modem_escape() if sequence found.
2300 *
2301 * Parameters:
2302 * p pointer to databuffer
2303 * plus escape-character
2304 * count length of buffer
2305 * pluscount count of valid escape-characters so far
2306 * lastplus timestamp of last character
2307 */
2308static void
2309isdn_tty_check_esc(const u_char *p, u_char plus, int count, int *pluscount,
2310 u_long *lastplus)
2311{
2312 if (plus > 127)
2313 return;
2314 if (count > 3) {
2315 p += count - 3;
2316 count = 3;
2317 *pluscount = 0;
2318 }
2319 while (count > 0) {
2320 if (*(p++) == plus) {
2321 if ((*pluscount)++) {
2322 /* Time since last '+' > 0.5 sec. ? */
2323 if (time_after(jiffies, *lastplus + PLUSWAIT1))
2324 *pluscount = 1;
2325 } else {
2326 /* Time since last non-'+' < 1.5 sec. ? */
2327 if (time_before(jiffies, *lastplus + PLUSWAIT2))
2328 *pluscount = 0;
2329 }
2330 if ((*pluscount == 3) && (count == 1))
2331 isdn_timer_ctrl(ISDN_TIMER_MODEMPLUS, 1);
2332 if (*pluscount > 3)
2333 *pluscount = 1;
2334 } else
2335 *pluscount = 0;
2336 *lastplus = jiffies;
2337 count--;
2338 }
2339}
2340
2341/*
2342 * Return result of AT-emulator to tty-receive-buffer, depending on
2343 * modem-register 12, bit 0 and 1.
2344 * For CONNECT-messages also switch to online-mode.
2345 * For RING-message handle auto-ATA if register 0 != 0
2346 */
2347
2348static void
2349isdn_tty_modem_result(int code, modem_info *info)
2350{
2351 atemu *m = &info->emu;
2352 static char *msg[] =
2353 {"OK", "CONNECT", "RING", "NO CARRIER", "ERROR",
2354 "CONNECT 64000", "NO DIALTONE", "BUSY", "NO ANSWER",
2355 "RINGING", "NO MSN/EAZ", "VCON", "RUNG"};
2356 char s[ISDN_MSNLEN + 10];
2357
2358 switch (code) {
2359 case RESULT_RING:
2360 m->mdmreg[REG_RINGCNT]++;
2361 if (m->mdmreg[REG_RINGCNT] == m->mdmreg[REG_RINGATA])
2362 /* Automatically accept incoming call */
2363 isdn_tty_cmd_ATA(info);
2364 break;
2365 case RESULT_NO_CARRIER:
2366#ifdef ISDN_DEBUG_MODEM_HUP
2367 printk(KERN_DEBUG "modem_result: NO CARRIER %d %d\n",
2368 info->closing, !info->port.tty);
2369#endif
2370 m->mdmreg[REG_RINGCNT] = 0;
2371 del_timer(&info->nc_timer);
2372 info->ncarrier = 0;
2373 if (info->closing || !info->port.tty)
2374 return;
2375
2376#ifdef CONFIG_ISDN_AUDIO
2377 if (info->vonline & 1) {
2378#ifdef ISDN_DEBUG_MODEM_VOICE
2379 printk(KERN_DEBUG "res3: send DLE-ETX on ttyI%d\n",
2380 info->line);
2381#endif
2382 /* voice-recording, add DLE-ETX */
2383 isdn_tty_at_cout("\020\003", info);
2384 }
2385 if (info->vonline & 2) {
2386#ifdef ISDN_DEBUG_MODEM_VOICE
2387 printk(KERN_DEBUG "res3: send DLE-DC4 on ttyI%d\n",
2388 info->line);
2389#endif
2390 /* voice-playing, add DLE-DC4 */
2391 isdn_tty_at_cout("\020\024", info);
2392 }
2393#endif
2394 break;
2395 case RESULT_CONNECT:
2396 case RESULT_CONNECT64000:
2397 sprintf(info->last_cause, "0000");
2398 if (!info->online)
2399 info->online = 2;
2400 break;
2401 case RESULT_VCON:
2402#ifdef ISDN_DEBUG_MODEM_VOICE
2403 printk(KERN_DEBUG "res3: send VCON on ttyI%d\n",
2404 info->line);
2405#endif
2406 sprintf(info->last_cause, "0000");
2407 if (!info->online)
2408 info->online = 1;
2409 break;
2410 } /* switch (code) */
2411
2412 if (m->mdmreg[REG_RESP] & BIT_RESP) {
2413 /* Show results */
2414 if (m->mdmreg[REG_RESPNUM] & BIT_RESPNUM) {
2415 /* Show numeric results only */
2416 sprintf(s, "\r\n%d\r\n", code);
2417 isdn_tty_at_cout(s, info);
2418 } else {
2419 if (code == RESULT_RING) {
2420 /* return if "show RUNG" and ringcounter>1 */
2421 if ((m->mdmreg[REG_RUNG] & BIT_RUNG) &&
2422 (m->mdmreg[REG_RINGCNT] > 1))
2423 return;
2424 /* print CID, _before_ _every_ ring */
2425 if (!(m->mdmreg[REG_CIDONCE] & BIT_CIDONCE)) {
2426 isdn_tty_at_cout("\r\nCALLER NUMBER: ", info);
2427 isdn_tty_at_cout(dev->num[info->drv_index], info);
2428 if (m->mdmreg[REG_CDN] & BIT_CDN) {
2429 isdn_tty_at_cout("\r\nCALLED NUMBER: ", info);
2430 isdn_tty_at_cout(info->emu.cpn, info);
2431 }
2432 }
2433 }
2434 isdn_tty_at_cout("\r\n", info);
2435 isdn_tty_at_cout(msg[code], info);
2436 switch (code) {
2437 case RESULT_CONNECT:
2438 switch (m->mdmreg[REG_L2PROT]) {
2439 case ISDN_PROTO_L2_MODEM:
2440 isdn_tty_at_cout(" ", info);
2441 isdn_tty_at_cout(m->connmsg, info);
2442 break;
2443 }
2444 break;
2445 case RESULT_RING:
2446 /* Append CPN, if enabled */
2447 if ((m->mdmreg[REG_CPN] & BIT_CPN)) {
2448 sprintf(s, "/%s", m->cpn);
2449 isdn_tty_at_cout(s, info);
2450 }
2451 /* Print CID only once, _after_ 1st RING */
2452 if ((m->mdmreg[REG_CIDONCE] & BIT_CIDONCE) &&
2453 (m->mdmreg[REG_RINGCNT] == 1)) {
2454 isdn_tty_at_cout("\r\n", info);
2455 isdn_tty_at_cout("CALLER NUMBER: ", info);
2456 isdn_tty_at_cout(dev->num[info->drv_index], info);
2457 if (m->mdmreg[REG_CDN] & BIT_CDN) {
2458 isdn_tty_at_cout("\r\nCALLED NUMBER: ", info);
2459 isdn_tty_at_cout(info->emu.cpn, info);
2460 }
2461 }
2462 break;
2463 case RESULT_NO_CARRIER:
2464 case RESULT_NO_DIALTONE:
2465 case RESULT_BUSY:
2466 case RESULT_NO_ANSWER:
2467 m->mdmreg[REG_RINGCNT] = 0;
2468 /* Append Cause-Message if enabled */
2469 if (m->mdmreg[REG_RESPXT] & BIT_RESPXT) {
2470 sprintf(s, "/%s", info->last_cause);
2471 isdn_tty_at_cout(s, info);
2472 }
2473 break;
2474 case RESULT_CONNECT64000:
2475 /* Append Protocol to CONNECT message */
2476 switch (m->mdmreg[REG_L2PROT]) {
2477 case ISDN_PROTO_L2_X75I:
2478 case ISDN_PROTO_L2_X75UI:
2479 case ISDN_PROTO_L2_X75BUI:
2480 isdn_tty_at_cout("/X.75", info);
2481 break;
2482 case ISDN_PROTO_L2_HDLC:
2483 isdn_tty_at_cout("/HDLC", info);
2484 break;
2485 case ISDN_PROTO_L2_V11096:
2486 isdn_tty_at_cout("/V110/9600", info);
2487 break;
2488 case ISDN_PROTO_L2_V11019:
2489 isdn_tty_at_cout("/V110/19200", info);
2490 break;
2491 case ISDN_PROTO_L2_V11038:
2492 isdn_tty_at_cout("/V110/38400", info);
2493 break;
2494 }
2495 if (m->mdmreg[REG_T70] & BIT_T70) {
2496 isdn_tty_at_cout("/T.70", info);
2497 if (m->mdmreg[REG_T70] & BIT_T70_EXT)
2498 isdn_tty_at_cout("+", info);
2499 }
2500 break;
2501 }
2502 isdn_tty_at_cout("\r\n", info);
2503 }
2504 }
2505 if (code == RESULT_NO_CARRIER) {
2506 if (info->closing || (!info->port.tty))
2507 return;
2508
2509 if (tty_port_check_carrier(&info->port))
2510 tty_hangup(info->port.tty);
2511 }
2512}
2513
2514
2515/*
2516 * Display a modem-register-value.
2517 */
2518static void
2519isdn_tty_show_profile(int ridx, modem_info *info)
2520{
2521 char v[6];
2522
2523 sprintf(v, "\r\n%d", info->emu.mdmreg[ridx]);
2524 isdn_tty_at_cout(v, info);
2525}
2526
2527/*
2528 * Get MSN-string from char-pointer, set pointer to end of number
2529 */
2530static void
2531isdn_tty_get_msnstr(char *n, char **p)
2532{
2533 int limit = ISDN_MSNLEN - 1;
2534
2535 while (((*p[0] >= '0' && *p[0] <= '9') ||
2536 /* Why a comma ??? */
2537 (*p[0] == ',') || (*p[0] == ':')) &&
2538 (limit--))
2539 *n++ = *p[0]++;
2540 *n = '\0';
2541}
2542
2543/*
2544 * Get phone-number from modem-commandbuffer
2545 */
2546static void
2547isdn_tty_getdial(char *p, char *q, int cnt)
2548{
2549 int first = 1;
2550 int limit = ISDN_MSNLEN - 1; /* MUST match the size of interface var to avoid
2551 buffer overflow */
2552
2553 while (strchr(" 0123456789,#.*WPTSR-", *p) && *p && --cnt > 0) {
2554 if ((*p >= '0' && *p <= '9') || ((*p == 'S') && first) ||
2555 ((*p == 'R') && first) ||
2556 (*p == '*') || (*p == '#')) {
2557 *q++ = *p;
2558 limit--;
2559 }
2560 if (!limit)
2561 break;
2562 p++;
2563 first = 0;
2564 }
2565 *q = 0;
2566}
2567
2568#define PARSE_ERROR { isdn_tty_modem_result(RESULT_ERROR, info); return; }
2569#define PARSE_ERROR1 { isdn_tty_modem_result(RESULT_ERROR, info); return 1; }
2570
2571static void
2572isdn_tty_report(modem_info *info)
2573{
2574 atemu *m = &info->emu;
2575 char s[80];
2576
2577 isdn_tty_at_cout("\r\nStatistics of last connection:\r\n\r\n", info);
2578 sprintf(s, " Remote Number: %s\r\n", info->last_num);
2579 isdn_tty_at_cout(s, info);
2580 sprintf(s, " Direction: %s\r\n", info->last_dir ? "outgoing" : "incoming");
2581 isdn_tty_at_cout(s, info);
2582 isdn_tty_at_cout(" Layer-2 Protocol: ", info);
2583 switch (info->last_l2) {
2584 case ISDN_PROTO_L2_X75I:
2585 isdn_tty_at_cout("X.75i", info);
2586 break;
2587 case ISDN_PROTO_L2_X75UI:
2588 isdn_tty_at_cout("X.75ui", info);
2589 break;
2590 case ISDN_PROTO_L2_X75BUI:
2591 isdn_tty_at_cout("X.75bui", info);
2592 break;
2593 case ISDN_PROTO_L2_HDLC:
2594 isdn_tty_at_cout("HDLC", info);
2595 break;
2596 case ISDN_PROTO_L2_V11096:
2597 isdn_tty_at_cout("V.110 9600 Baud", info);
2598 break;
2599 case ISDN_PROTO_L2_V11019:
2600 isdn_tty_at_cout("V.110 19200 Baud", info);
2601 break;
2602 case ISDN_PROTO_L2_V11038:
2603 isdn_tty_at_cout("V.110 38400 Baud", info);
2604 break;
2605 case ISDN_PROTO_L2_TRANS:
2606 isdn_tty_at_cout("transparent", info);
2607 break;
2608 case ISDN_PROTO_L2_MODEM:
2609 isdn_tty_at_cout("modem", info);
2610 break;
2611 case ISDN_PROTO_L2_FAX:
2612 isdn_tty_at_cout("fax", info);
2613 break;
2614 default:
2615 isdn_tty_at_cout("unknown", info);
2616 break;
2617 }
2618 if (m->mdmreg[REG_T70] & BIT_T70) {
2619 isdn_tty_at_cout("/T.70", info);
2620 if (m->mdmreg[REG_T70] & BIT_T70_EXT)
2621 isdn_tty_at_cout("+", info);
2622 }
2623 isdn_tty_at_cout("\r\n", info);
2624 isdn_tty_at_cout(" Service: ", info);
2625 switch (info->last_si) {
2626 case 1:
2627 isdn_tty_at_cout("audio\r\n", info);
2628 break;
2629 case 5:
2630 isdn_tty_at_cout("btx\r\n", info);
2631 break;
2632 case 7:
2633 isdn_tty_at_cout("data\r\n", info);
2634 break;
2635 default:
2636 sprintf(s, "%d\r\n", info->last_si);
2637 isdn_tty_at_cout(s, info);
2638 break;
2639 }
2640 sprintf(s, " Hangup location: %s\r\n", info->last_lhup ? "local" : "remote");
2641 isdn_tty_at_cout(s, info);
2642 sprintf(s, " Last cause: %s\r\n", info->last_cause);
2643 isdn_tty_at_cout(s, info);
2644}
2645
2646/*
2647 * Parse AT&.. commands.
2648 */
2649static int
2650isdn_tty_cmd_ATand(char **p, modem_info *info)
2651{
2652 atemu *m = &info->emu;
2653 int i;
2654 char rb[100];
2655
2656#define MAXRB (sizeof(rb) - 1)
2657
2658 switch (*p[0]) {
2659 case 'B':
2660 /* &B - Set Buffersize */
2661 p[0]++;
2662 i = isdn_getnum(p);
2663 if ((i < 0) || (i > ISDN_SERIAL_XMIT_MAX))
2664 PARSE_ERROR1;
2665#ifdef CONFIG_ISDN_AUDIO
2666 if ((m->mdmreg[REG_SI1] & 1) && (i > VBUF))
2667 PARSE_ERROR1;
2668#endif
2669 m->mdmreg[REG_PSIZE] = i / 16;
2670 info->xmit_size = m->mdmreg[REG_PSIZE] * 16;
2671 switch (m->mdmreg[REG_L2PROT]) {
2672 case ISDN_PROTO_L2_V11096:
2673 case ISDN_PROTO_L2_V11019:
2674 case ISDN_PROTO_L2_V11038:
2675 info->xmit_size /= 10;
2676 }
2677 break;
2678 case 'C':
2679 /* &C - DCD Status */
2680 p[0]++;
2681 switch (isdn_getnum(p)) {
2682 case 0:
2683 m->mdmreg[REG_DCD] &= ~BIT_DCD;
2684 break;
2685 case 1:
2686 m->mdmreg[REG_DCD] |= BIT_DCD;
2687 break;
2688 default:
2689 PARSE_ERROR1
2690 }
2691 break;
2692 case 'D':
2693 /* &D - Set DTR-Low-behavior */
2694 p[0]++;
2695 switch (isdn_getnum(p)) {
2696 case 0:
2697 m->mdmreg[REG_DTRHUP] &= ~BIT_DTRHUP;
2698 m->mdmreg[REG_DTRR] &= ~BIT_DTRR;
2699 break;
2700 case 2:
2701 m->mdmreg[REG_DTRHUP] |= BIT_DTRHUP;
2702 m->mdmreg[REG_DTRR] &= ~BIT_DTRR;
2703 break;
2704 case 3:
2705 m->mdmreg[REG_DTRHUP] |= BIT_DTRHUP;
2706 m->mdmreg[REG_DTRR] |= BIT_DTRR;
2707 break;
2708 default:
2709 PARSE_ERROR1
2710 }
2711 break;
2712 case 'E':
2713 /* &E -Set EAZ/MSN */
2714 p[0]++;
2715 isdn_tty_get_msnstr(m->msn, p);
2716 break;
2717 case 'F':
2718 /* &F -Set Factory-Defaults */
2719 p[0]++;
2720 if (info->msr & UART_MSR_DCD)
2721 PARSE_ERROR1;
2722 isdn_tty_reset_profile(m);
2723 isdn_tty_modem_reset_regs(info, 1);
2724 break;
2725#ifdef DUMMY_HAYES_AT
2726 case 'K':
2727 /* only for be compilant with common scripts */
2728 /* &K Flowcontrol - no function */
2729 p[0]++;
2730 isdn_getnum(p);
2731 break;
2732#endif
2733 case 'L':
2734 /* &L -Set Numbers to listen on */
2735 p[0]++;
2736 i = 0;
2737 while (*p[0] && (strchr("0123456789,-*[]?;", *p[0])) &&
2738 (i < ISDN_LMSNLEN - 1))
2739 m->lmsn[i++] = *p[0]++;
2740 m->lmsn[i] = '\0';
2741 break;
2742 case 'R':
2743 /* &R - Set V.110 bitrate adaption */
2744 p[0]++;
2745 i = isdn_getnum(p);
2746 switch (i) {
2747 case 0:
2748 /* Switch off V.110, back to X.75 */
2749 m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_X75I;
2750 m->mdmreg[REG_SI2] = 0;
2751 info->xmit_size = m->mdmreg[REG_PSIZE] * 16;
2752 break;
2753 case 9600:
2754 m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_V11096;
2755 m->mdmreg[REG_SI2] = 197;
2756 info->xmit_size = m->mdmreg[REG_PSIZE] * 16 / 10;
2757 break;
2758 case 19200:
2759 m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_V11019;
2760 m->mdmreg[REG_SI2] = 199;
2761 info->xmit_size = m->mdmreg[REG_PSIZE] * 16 / 10;
2762 break;
2763 case 38400:
2764 m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_V11038;
2765 m->mdmreg[REG_SI2] = 198; /* no existing standard for this */
2766 info->xmit_size = m->mdmreg[REG_PSIZE] * 16 / 10;
2767 break;
2768 default:
2769 PARSE_ERROR1;
2770 }
2771 /* Switch off T.70 */
2772 m->mdmreg[REG_T70] &= ~(BIT_T70 | BIT_T70_EXT);
2773 /* Set Service 7 */
2774 m->mdmreg[REG_SI1] |= 4;
2775 break;
2776 case 'S':
2777 /* &S - Set Windowsize */
2778 p[0]++;
2779 i = isdn_getnum(p);
2780 if ((i > 0) && (i < 9))
2781 m->mdmreg[REG_WSIZE] = i;
2782 else
2783 PARSE_ERROR1;
2784 break;
2785 case 'V':
2786 /* &V - Show registers */
2787 p[0]++;
2788 isdn_tty_at_cout("\r\n", info);
2789 for (i = 0; i < ISDN_MODEM_NUMREG; i++) {
2790 sprintf(rb, "S%02d=%03d%s", i,
2791 m->mdmreg[i], ((i + 1) % 10) ? " " : "\r\n");
2792 isdn_tty_at_cout(rb, info);
2793 }
2794 sprintf(rb, "\r\nEAZ/MSN: %.50s\r\n",
2795 strlen(m->msn) ? m->msn : "None");
2796 isdn_tty_at_cout(rb, info);
2797 if (strlen(m->lmsn)) {
2798 isdn_tty_at_cout("\r\nListen: ", info);
2799 isdn_tty_at_cout(m->lmsn, info);
2800 isdn_tty_at_cout("\r\n", info);
2801 }
2802 break;
2803 case 'W':
2804 /* &W - Write Profile */
2805 p[0]++;
2806 switch (*p[0]) {
2807 case '0':
2808 p[0]++;
2809 modem_write_profile(m);
2810 break;
2811 default:
2812 PARSE_ERROR1;
2813 }
2814 break;
2815 case 'X':
2816 /* &X - Switch to BTX-Mode and T.70 */
2817 p[0]++;
2818 switch (isdn_getnum(p)) {
2819 case 0:
2820 m->mdmreg[REG_T70] &= ~(BIT_T70 | BIT_T70_EXT);
2821 info->xmit_size = m->mdmreg[REG_PSIZE] * 16;
2822 break;
2823 case 1:
2824 m->mdmreg[REG_T70] |= BIT_T70;
2825 m->mdmreg[REG_T70] &= ~BIT_T70_EXT;
2826 m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_X75I;
2827 info->xmit_size = 112;
2828 m->mdmreg[REG_SI1] = 4;
2829 m->mdmreg[REG_SI2] = 0;
2830 break;
2831 case 2:
2832 m->mdmreg[REG_T70] |= (BIT_T70 | BIT_T70_EXT);
2833 m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_X75I;
2834 info->xmit_size = 112;
2835 m->mdmreg[REG_SI1] = 4;
2836 m->mdmreg[REG_SI2] = 0;
2837 break;
2838 default:
2839 PARSE_ERROR1;
2840 }
2841 break;
2842 default:
2843 PARSE_ERROR1;
2844 }
2845 return 0;
2846}
2847
2848static int
2849isdn_tty_check_ats(int mreg, int mval, modem_info *info, atemu *m)
2850{
2851 /* Some plausibility checks */
2852 switch (mreg) {
2853 case REG_L2PROT:
2854 if (mval > ISDN_PROTO_L2_MAX)
2855 return 1;
2856 break;
2857 case REG_PSIZE:
2858 if ((mval * 16) > ISDN_SERIAL_XMIT_MAX)
2859 return 1;
2860#ifdef CONFIG_ISDN_AUDIO
2861 if ((m->mdmreg[REG_SI1] & 1) && (mval > VBUFX))
2862 return 1;
2863#endif
2864 info->xmit_size = mval * 16;
2865 switch (m->mdmreg[REG_L2PROT]) {
2866 case ISDN_PROTO_L2_V11096:
2867 case ISDN_PROTO_L2_V11019:
2868 case ISDN_PROTO_L2_V11038:
2869 info->xmit_size /= 10;
2870 }
2871 break;
2872 case REG_SI1I:
2873 case REG_PLAN:
2874 case REG_SCREEN:
2875 /* readonly registers */
2876 return 1;
2877 }
2878 return 0;
2879}
2880
2881/*
2882 * Perform ATS command
2883 */
2884static int
2885isdn_tty_cmd_ATS(char **p, modem_info *info)
2886{
2887 atemu *m = &info->emu;
2888 int bitpos;
2889 int mreg;
2890 int mval;
2891 int bval;
2892
2893 mreg = isdn_getnum(p);
2894 if (mreg < 0 || mreg >= ISDN_MODEM_NUMREG)
2895 PARSE_ERROR1;
2896 switch (*p[0]) {
2897 case '=':
2898 p[0]++;
2899 mval = isdn_getnum(p);
2900 if (mval < 0 || mval > 255)
2901 PARSE_ERROR1;
2902 if (isdn_tty_check_ats(mreg, mval, info, m))
2903 PARSE_ERROR1;
2904 m->mdmreg[mreg] = mval;
2905 break;
2906 case '.':
2907 /* Set/Clear a single bit */
2908 p[0]++;
2909 bitpos = isdn_getnum(p);
2910 if ((bitpos < 0) || (bitpos > 7))
2911 PARSE_ERROR1;
2912 switch (*p[0]) {
2913 case '=':
2914 p[0]++;
2915 bval = isdn_getnum(p);
2916 if (bval < 0 || bval > 1)
2917 PARSE_ERROR1;
2918 if (bval)
2919 mval = m->mdmreg[mreg] | (1 << bitpos);
2920 else
2921 mval = m->mdmreg[mreg] & ~(1 << bitpos);
2922 if (isdn_tty_check_ats(mreg, mval, info, m))
2923 PARSE_ERROR1;
2924 m->mdmreg[mreg] = mval;
2925 break;
2926 case '?':
2927 p[0]++;
2928 isdn_tty_at_cout("\r\n", info);
2929 isdn_tty_at_cout((m->mdmreg[mreg] & (1 << bitpos)) ? "1" : "0",
2930 info);
2931 break;
2932 default:
2933 PARSE_ERROR1;
2934 }
2935 break;
2936 case '?':
2937 p[0]++;
2938 isdn_tty_show_profile(mreg, info);
2939 break;
2940 default:
2941 PARSE_ERROR1;
2942 break;
2943 }
2944 return 0;
2945}
2946
2947/*
2948 * Perform ATA command
2949 */
2950static void
2951isdn_tty_cmd_ATA(modem_info *info)
2952{
2953 atemu *m = &info->emu;
2954 isdn_ctrl cmd;
2955 int l2;
2956
2957 if (info->msr & UART_MSR_RI) {
2958 /* Accept incoming call */
2959 info->last_dir = 0;
2960 strcpy(info->last_num, dev->num[info->drv_index]);
2961 m->mdmreg[REG_RINGCNT] = 0;
2962 info->msr &= ~UART_MSR_RI;
2963 l2 = m->mdmreg[REG_L2PROT];
2964#ifdef CONFIG_ISDN_AUDIO
2965 /* If more than one bit set in reg18, autoselect Layer2 */
2966 if ((m->mdmreg[REG_SI1] & m->mdmreg[REG_SI1I]) != m->mdmreg[REG_SI1]) {
2967 if (m->mdmreg[REG_SI1I] == 1) {
2968 if ((l2 != ISDN_PROTO_L2_MODEM) && (l2 != ISDN_PROTO_L2_FAX))
2969 l2 = ISDN_PROTO_L2_TRANS;
2970 } else
2971 l2 = ISDN_PROTO_L2_X75I;
2972 }
2973#endif
2974 cmd.driver = info->isdn_driver;
2975 cmd.command = ISDN_CMD_SETL2;
2976 cmd.arg = info->isdn_channel + (l2 << 8);
2977 info->last_l2 = l2;
2978 isdn_command(&cmd);
2979 cmd.driver = info->isdn_driver;
2980 cmd.command = ISDN_CMD_SETL3;
2981 cmd.arg = info->isdn_channel + (m->mdmreg[REG_L3PROT] << 8);
2982#ifdef CONFIG_ISDN_TTY_FAX
2983 if (l2 == ISDN_PROTO_L2_FAX) {
2984 cmd.parm.fax = info->fax;
2985 info->fax->direction = ISDN_TTY_FAX_CONN_IN;
2986 }
2987#endif
2988 isdn_command(&cmd);
2989 cmd.driver = info->isdn_driver;
2990 cmd.arg = info->isdn_channel;
2991 cmd.command = ISDN_CMD_ACCEPTD;
2992 info->dialing = 16;
2993 info->emu.carrierwait = 0;
2994 isdn_command(&cmd);
2995 isdn_timer_ctrl(ISDN_TIMER_CARRIER, 1);
2996 } else
2997 isdn_tty_modem_result(RESULT_NO_ANSWER, info);
2998}
2999
3000#ifdef CONFIG_ISDN_AUDIO
3001/*
3002 * Parse AT+F.. commands
3003 */
3004static int
3005isdn_tty_cmd_PLUSF(char **p, modem_info *info)
3006{
3007 atemu *m = &info->emu;
3008 char rs[20];
3009
3010 if (!strncmp(p[0], "CLASS", 5)) {
3011 p[0] += 5;
3012 switch (*p[0]) {
3013 case '?':
3014 p[0]++;
3015 sprintf(rs, "\r\n%d",
3016 (m->mdmreg[REG_SI1] & 1) ? 8 : 0);
3017#ifdef CONFIG_ISDN_TTY_FAX
3018 if (TTY_IS_FCLASS2(info))
3019 sprintf(rs, "\r\n2");
3020 else if (TTY_IS_FCLASS1(info))
3021 sprintf(rs, "\r\n1");
3022#endif
3023 isdn_tty_at_cout(rs, info);
3024 break;
3025 case '=':
3026 p[0]++;
3027 switch (*p[0]) {
3028 case '0':
3029 p[0]++;
3030 m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_X75I;
3031 m->mdmreg[REG_L3PROT] = ISDN_PROTO_L3_TRANS;
3032 m->mdmreg[REG_SI1] = 4;
3033 info->xmit_size =
3034 m->mdmreg[REG_PSIZE] * 16;
3035 break;
3036#ifdef CONFIG_ISDN_TTY_FAX
3037 case '1':
3038 p[0]++;
3039 if (!(dev->global_features &
3040 ISDN_FEATURE_L3_FCLASS1))
3041 PARSE_ERROR1;
3042 m->mdmreg[REG_SI1] = 1;
3043 m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_FAX;
3044 m->mdmreg[REG_L3PROT] = ISDN_PROTO_L3_FCLASS1;
3045 info->xmit_size =
3046 m->mdmreg[REG_PSIZE] * 16;
3047 break;
3048 case '2':
3049 p[0]++;
3050 if (!(dev->global_features &
3051 ISDN_FEATURE_L3_FCLASS2))
3052 PARSE_ERROR1;
3053 m->mdmreg[REG_SI1] = 1;
3054 m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_FAX;
3055 m->mdmreg[REG_L3PROT] = ISDN_PROTO_L3_FCLASS2;
3056 info->xmit_size =
3057 m->mdmreg[REG_PSIZE] * 16;
3058 break;
3059#endif
3060 case '8':
3061 p[0]++;
3062 /* L2 will change on dialout with si=1 */
3063 m->mdmreg[REG_L2PROT] = ISDN_PROTO_L2_X75I;
3064 m->mdmreg[REG_L3PROT] = ISDN_PROTO_L3_TRANS;
3065 m->mdmreg[REG_SI1] = 5;
3066 info->xmit_size = VBUF;
3067 break;
3068 case '?':
3069 p[0]++;
3070 strcpy(rs, "\r\n0,");
3071#ifdef CONFIG_ISDN_TTY_FAX
3072 if (dev->global_features &
3073 ISDN_FEATURE_L3_FCLASS1)
3074 strcat(rs, "1,");
3075 if (dev->global_features &
3076 ISDN_FEATURE_L3_FCLASS2)
3077 strcat(rs, "2,");
3078#endif
3079 strcat(rs, "8");
3080 isdn_tty_at_cout(rs, info);
3081 break;
3082 default:
3083 PARSE_ERROR1;
3084 }
3085 break;
3086 default:
3087 PARSE_ERROR1;
3088 }
3089 return 0;
3090 }
3091#ifdef CONFIG_ISDN_TTY_FAX
3092 return (isdn_tty_cmd_PLUSF_FAX(p, info));
3093#else
3094 PARSE_ERROR1;
3095#endif
3096}
3097
3098/*
3099 * Parse AT+V.. commands
3100 */
3101static int
3102isdn_tty_cmd_PLUSV(char **p, modem_info *info)
3103{
3104 atemu *m = &info->emu;
3105 isdn_ctrl cmd;
3106 static char *vcmd[] =
3107 {"NH", "IP", "LS", "RX", "SD", "SM", "TX", "DD", NULL};
3108 int i;
3109 int par1;
3110 int par2;
3111 char rs[20];
3112
3113 i = 0;
3114 while (vcmd[i]) {
3115 if (!strncmp(vcmd[i], p[0], 2)) {
3116 p[0] += 2;
3117 break;
3118 }
3119 i++;
3120 }
3121 switch (i) {
3122 case 0:
3123 /* AT+VNH - Auto hangup feature */
3124 switch (*p[0]) {
3125 case '?':
3126 p[0]++;
3127 isdn_tty_at_cout("\r\n1", info);
3128 break;
3129 case '=':
3130 p[0]++;
3131 switch (*p[0]) {
3132 case '1':
3133 p[0]++;
3134 break;
3135 case '?':
3136 p[0]++;
3137 isdn_tty_at_cout("\r\n1", info);
3138 break;
3139 default:
3140 PARSE_ERROR1;
3141 }
3142 break;
3143 default:
3144 PARSE_ERROR1;
3145 }
3146 break;
3147 case 1:
3148 /* AT+VIP - Reset all voice parameters */
3149 isdn_tty_modem_reset_vpar(m);
3150 break;
3151 case 2:
3152 /* AT+VLS - Select device, accept incoming call */
3153 switch (*p[0]) {
3154 case '?':
3155 p[0]++;
3156 sprintf(rs, "\r\n%d", m->vpar[0]);
3157 isdn_tty_at_cout(rs, info);
3158 break;
3159 case '=':
3160 p[0]++;
3161 switch (*p[0]) {
3162 case '0':
3163 p[0]++;
3164 m->vpar[0] = 0;
3165 break;
3166 case '2':
3167 p[0]++;
3168 m->vpar[0] = 2;
3169 break;
3170 case '?':
3171 p[0]++;
3172 isdn_tty_at_cout("\r\n0,2", info);
3173 break;
3174 default:
3175 PARSE_ERROR1;
3176 }
3177 break;
3178 default:
3179 PARSE_ERROR1;
3180 }
3181 break;
3182 case 3:
3183 /* AT+VRX - Start recording */
3184 if (!m->vpar[0])
3185 PARSE_ERROR1;
3186 if (info->online != 1) {
3187 isdn_tty_modem_result(RESULT_NO_ANSWER, info);
3188 return 1;
3189 }
3190 info->dtmf_state = isdn_audio_dtmf_init(info->dtmf_state);
3191 if (!info->dtmf_state) {
3192 printk(KERN_WARNING "isdn_tty: Couldn't malloc dtmf state\n");
3193 PARSE_ERROR1;
3194 }
3195 info->silence_state = isdn_audio_silence_init(info->silence_state);
3196 if (!info->silence_state) {
3197 printk(KERN_WARNING "isdn_tty: Couldn't malloc silence state\n");
3198 PARSE_ERROR1;
3199 }
3200 if (m->vpar[3] < 5) {
3201 info->adpcmr = isdn_audio_adpcm_init(info->adpcmr, m->vpar[3]);
3202 if (!info->adpcmr) {
3203 printk(KERN_WARNING "isdn_tty: Couldn't malloc adpcm state\n");
3204 PARSE_ERROR1;
3205 }
3206 }
3207#ifdef ISDN_DEBUG_AT
3208 printk(KERN_DEBUG "AT: +VRX\n");
3209#endif
3210 info->vonline |= 1;
3211 isdn_tty_modem_result(RESULT_CONNECT, info);
3212 return 0;
3213 break;
3214 case 4:
3215 /* AT+VSD - Silence detection */
3216 switch (*p[0]) {
3217 case '?':
3218 p[0]++;
3219 sprintf(rs, "\r\n<%d>,<%d>",
3220 m->vpar[1],
3221 m->vpar[2]);
3222 isdn_tty_at_cout(rs, info);
3223 break;
3224 case '=':
3225 p[0]++;
3226 if ((*p[0] >= '0') && (*p[0] <= '9')) {
3227 par1 = isdn_getnum(p);
3228 if ((par1 < 0) || (par1 > 31))
3229 PARSE_ERROR1;
3230 if (*p[0] != ',')
3231 PARSE_ERROR1;
3232 p[0]++;
3233 par2 = isdn_getnum(p);
3234 if ((par2 < 0) || (par2 > 255))
3235 PARSE_ERROR1;
3236 m->vpar[1] = par1;
3237 m->vpar[2] = par2;
3238 break;
3239 } else
3240 if (*p[0] == '?') {
3241 p[0]++;
3242 isdn_tty_at_cout("\r\n<0-31>,<0-255>",
3243 info);
3244 break;
3245 } else
3246 PARSE_ERROR1;
3247 break;
3248 default:
3249 PARSE_ERROR1;
3250 }
3251 break;
3252 case 5:
3253 /* AT+VSM - Select compression */
3254 switch (*p[0]) {
3255 case '?':
3256 p[0]++;
3257 sprintf(rs, "\r\n<%d>,<%d><8000>",
3258 m->vpar[3],
3259 m->vpar[1]);
3260 isdn_tty_at_cout(rs, info);
3261 break;
3262 case '=':
3263 p[0]++;
3264 switch (*p[0]) {
3265 case '2':
3266 case '3':
3267 case '4':
3268 case '5':
3269 case '6':
3270 par1 = isdn_getnum(p);
3271 if ((par1 < 2) || (par1 > 6))
3272 PARSE_ERROR1;
3273 m->vpar[3] = par1;
3274 break;
3275 case '?':
3276 p[0]++;
3277 isdn_tty_at_cout("\r\n2;ADPCM;2;0;(8000)\r\n",
3278 info);
3279 isdn_tty_at_cout("3;ADPCM;3;0;(8000)\r\n",
3280 info);
3281 isdn_tty_at_cout("4;ADPCM;4;0;(8000)\r\n",
3282 info);
3283 isdn_tty_at_cout("5;ALAW;8;0;(8000)\r\n",
3284 info);
3285 isdn_tty_at_cout("6;ULAW;8;0;(8000)\r\n",
3286 info);
3287 break;
3288 default:
3289 PARSE_ERROR1;
3290 }
3291 break;
3292 default:
3293 PARSE_ERROR1;
3294 }
3295 break;
3296 case 6:
3297 /* AT+VTX - Start sending */
3298 if (!m->vpar[0])
3299 PARSE_ERROR1;
3300 if (info->online != 1) {
3301 isdn_tty_modem_result(RESULT_NO_ANSWER, info);
3302 return 1;
3303 }
3304 info->dtmf_state = isdn_audio_dtmf_init(info->dtmf_state);
3305 if (!info->dtmf_state) {
3306 printk(KERN_WARNING "isdn_tty: Couldn't malloc dtmf state\n");
3307 PARSE_ERROR1;
3308 }
3309 if (m->vpar[3] < 5) {
3310 info->adpcms = isdn_audio_adpcm_init(info->adpcms, m->vpar[3]);
3311 if (!info->adpcms) {
3312 printk(KERN_WARNING "isdn_tty: Couldn't malloc adpcm state\n");
3313 PARSE_ERROR1;
3314 }
3315 }
3316#ifdef ISDN_DEBUG_AT
3317 printk(KERN_DEBUG "AT: +VTX\n");
3318#endif
3319 m->lastDLE = 0;
3320 info->vonline |= 2;
3321 isdn_tty_modem_result(RESULT_CONNECT, info);
3322 return 0;
3323 break;
3324 case 7:
3325 /* AT+VDD - DTMF detection */
3326 switch (*p[0]) {
3327 case '?':
3328 p[0]++;
3329 sprintf(rs, "\r\n<%d>,<%d>",
3330 m->vpar[4],
3331 m->vpar[5]);
3332 isdn_tty_at_cout(rs, info);
3333 break;
3334 case '=':
3335 p[0]++;
3336 if ((*p[0] >= '0') && (*p[0] <= '9')) {
3337 if (info->online != 1)
3338 PARSE_ERROR1;
3339 par1 = isdn_getnum(p);
3340 if ((par1 < 0) || (par1 > 15))
3341 PARSE_ERROR1;
3342 if (*p[0] != ',')
3343 PARSE_ERROR1;
3344 p[0]++;
3345 par2 = isdn_getnum(p);
3346 if ((par2 < 0) || (par2 > 255))
3347 PARSE_ERROR1;
3348 m->vpar[4] = par1;
3349 m->vpar[5] = par2;
3350 cmd.driver = info->isdn_driver;
3351 cmd.command = ISDN_CMD_AUDIO;
3352 cmd.arg = info->isdn_channel + (ISDN_AUDIO_SETDD << 8);
3353 cmd.parm.num[0] = par1;
3354 cmd.parm.num[1] = par2;
3355 isdn_command(&cmd);
3356 break;
3357 } else
3358 if (*p[0] == '?') {
3359 p[0]++;
3360 isdn_tty_at_cout("\r\n<0-15>,<0-255>",
3361 info);
3362 break;
3363 } else
3364 PARSE_ERROR1;
3365 break;
3366 default:
3367 PARSE_ERROR1;
3368 }
3369 break;
3370 default:
3371 PARSE_ERROR1;
3372 }
3373 return 0;
3374}
3375#endif /* CONFIG_ISDN_AUDIO */
3376
3377/*
3378 * Parse and perform an AT-command-line.
3379 */
3380static void
3381isdn_tty_parse_at(modem_info *info)
3382{
3383 atemu *m = &info->emu;
3384 char *p;
3385 char ds[ISDN_MSNLEN];
3386
3387#ifdef ISDN_DEBUG_AT
3388 printk(KERN_DEBUG "AT: '%s'\n", m->mdmcmd);
3389#endif
3390 for (p = &m->mdmcmd[2]; *p;) {
3391 switch (*p) {
3392 case ' ':
3393 p++;
3394 break;
3395 case 'A':
3396 /* A - Accept incoming call */
3397 p++;
3398 isdn_tty_cmd_ATA(info);
3399 return;
3400 case 'D':
3401 /* D - Dial */
3402 if (info->msr & UART_MSR_DCD)
3403 PARSE_ERROR;
3404 if (info->msr & UART_MSR_RI) {
3405 isdn_tty_modem_result(RESULT_NO_CARRIER, info);
3406 return;
3407 }
3408 isdn_tty_getdial(++p, ds, sizeof ds);
3409 p += strlen(p);
3410 if (!strlen(m->msn))
3411 isdn_tty_modem_result(RESULT_NO_MSN_EAZ, info);
3412 else if (strlen(ds))
3413 isdn_tty_dial(ds, info, m);
3414 else
3415 PARSE_ERROR;
3416 return;
3417 case 'E':
3418 /* E - Turn Echo on/off */
3419 p++;
3420 switch (isdn_getnum(&p)) {
3421 case 0:
3422 m->mdmreg[REG_ECHO] &= ~BIT_ECHO;
3423 break;
3424 case 1:
3425 m->mdmreg[REG_ECHO] |= BIT_ECHO;
3426 break;
3427 default:
3428 PARSE_ERROR;
3429 }
3430 break;
3431 case 'H':
3432 /* H - On/Off-hook */
3433 p++;
3434 switch (*p) {
3435 case '0':
3436 p++;
3437 isdn_tty_on_hook(info);
3438 break;
3439 case '1':
3440 p++;
3441 isdn_tty_off_hook();
3442 break;
3443 default:
3444 isdn_tty_on_hook(info);
3445 break;
3446 }
3447 break;
3448 case 'I':
3449 /* I - Information */
3450 p++;
3451 isdn_tty_at_cout("\r\nLinux ISDN", info);
3452 switch (*p) {
3453 case '0':
3454 case '1':
3455 p++;
3456 break;
3457 case '2':
3458 p++;
3459 isdn_tty_report(info);
3460 break;
3461 case '3':
3462 p++;
3463 snprintf(ds, sizeof(ds), "\r\n%d", info->emu.charge);
3464 isdn_tty_at_cout(ds, info);
3465 break;
3466 default:;
3467 }
3468 break;
3469#ifdef DUMMY_HAYES_AT
3470 case 'L':
3471 case 'M':
3472 /* only for be compilant with common scripts */
3473 /* no function */
3474 p++;
3475 isdn_getnum(&p);
3476 break;
3477#endif
3478 case 'O':
3479 /* O - Go online */
3480 p++;
3481 if (info->msr & UART_MSR_DCD)
3482 /* if B-Channel is up */
3483 isdn_tty_modem_result((m->mdmreg[REG_L2PROT] == ISDN_PROTO_L2_MODEM) ? RESULT_CONNECT : RESULT_CONNECT64000, info);
3484 else
3485 isdn_tty_modem_result(RESULT_NO_CARRIER, info);
3486 return;
3487 case 'Q':
3488 /* Q - Turn Emulator messages on/off */
3489 p++;
3490 switch (isdn_getnum(&p)) {
3491 case 0:
3492 m->mdmreg[REG_RESP] |= BIT_RESP;
3493 break;
3494 case 1:
3495 m->mdmreg[REG_RESP] &= ~BIT_RESP;
3496 break;
3497 default:
3498 PARSE_ERROR;
3499 }
3500 break;
3501 case 'S':
3502 /* S - Set/Get Register */
3503 p++;
3504 if (isdn_tty_cmd_ATS(&p, info))
3505 return;
3506 break;
3507 case 'V':
3508 /* V - Numeric or ASCII Emulator-messages */
3509 p++;
3510 switch (isdn_getnum(&p)) {
3511 case 0:
3512 m->mdmreg[REG_RESP] |= BIT_RESPNUM;
3513 break;
3514 case 1:
3515 m->mdmreg[REG_RESP] &= ~BIT_RESPNUM;
3516 break;
3517 default:
3518 PARSE_ERROR;
3519 }
3520 break;
3521 case 'Z':
3522 /* Z - Load Registers from Profile */
3523 p++;
3524 if (info->msr & UART_MSR_DCD) {
3525 info->online = 0;
3526 isdn_tty_on_hook(info);
3527 }
3528 isdn_tty_modem_reset_regs(info, 1);
3529 break;
3530 case '+':
3531 p++;
3532 switch (*p) {
3533#ifdef CONFIG_ISDN_AUDIO
3534 case 'F':
3535 p++;
3536 if (isdn_tty_cmd_PLUSF(&p, info))
3537 return;
3538 break;
3539 case 'V':
3540 if ((!(m->mdmreg[REG_SI1] & 1)) ||
3541 (m->mdmreg[REG_L2PROT] == ISDN_PROTO_L2_MODEM))
3542 PARSE_ERROR;
3543 p++;
3544 if (isdn_tty_cmd_PLUSV(&p, info))
3545 return;
3546 break;
3547#endif /* CONFIG_ISDN_AUDIO */
3548 case 'S': /* SUSPEND */
3549 p++;
3550 isdn_tty_get_msnstr(ds, &p);
3551 isdn_tty_suspend(ds, info, m);
3552 break;
3553 case 'R': /* RESUME */
3554 p++;
3555 isdn_tty_get_msnstr(ds, &p);
3556 isdn_tty_resume(ds, info, m);
3557 break;
3558 case 'M': /* MESSAGE */
3559 p++;
3560 isdn_tty_send_msg(info, m, p);
3561 break;
3562 default:
3563 PARSE_ERROR;
3564 }
3565 break;
3566 case '&':
3567 p++;
3568 if (isdn_tty_cmd_ATand(&p, info))
3569 return;
3570 break;
3571 default:
3572 PARSE_ERROR;
3573 }
3574 }
3575#ifdef CONFIG_ISDN_AUDIO
3576 if (!info->vonline)
3577#endif
3578 isdn_tty_modem_result(RESULT_OK, info);
3579}
3580
3581/* Need own toupper() because standard-toupper is not available
3582 * within modules.
3583 */
3584#define my_toupper(c) (((c >= 'a') && (c <= 'z')) ? (c & 0xdf) : c)
3585
3586/*
3587 * Perform line-editing of AT-commands
3588 *
3589 * Parameters:
3590 * p inputbuffer
3591 * count length of buffer
3592 * channel index to line (minor-device)
3593 */
3594static int
3595isdn_tty_edit_at(const char *p, int count, modem_info *info)
3596{
3597 atemu *m = &info->emu;
3598 int total = 0;
3599 u_char c;
3600 char eb[2];
3601 int cnt;
3602
3603 for (cnt = count; cnt > 0; p++, cnt--) {
3604 c = *p;
3605 total++;
3606 if (c == m->mdmreg[REG_CR] || c == m->mdmreg[REG_LF]) {
3607 /* Separator (CR or LF) */
3608 m->mdmcmd[m->mdmcmdl] = 0;
3609 if (m->mdmreg[REG_ECHO] & BIT_ECHO) {
3610 eb[0] = c;
3611 eb[1] = 0;
3612 isdn_tty_at_cout(eb, info);
3613 }
3614 if ((m->mdmcmdl >= 2) && (!(strncmp(m->mdmcmd, "AT", 2))))
3615 isdn_tty_parse_at(info);
3616 m->mdmcmdl = 0;
3617 continue;
3618 }
3619 if (c == m->mdmreg[REG_BS] && m->mdmreg[REG_BS] < 128) {
3620 /* Backspace-Function */
3621 if ((m->mdmcmdl > 2) || (!m->mdmcmdl)) {
3622 if (m->mdmcmdl)
3623 m->mdmcmdl--;
3624 if (m->mdmreg[REG_ECHO] & BIT_ECHO)
3625 isdn_tty_at_cout("\b", info);
3626 }
3627 continue;
3628 }
3629 if (cmdchar(c)) {
3630 if (m->mdmreg[REG_ECHO] & BIT_ECHO) {
3631 eb[0] = c;
3632 eb[1] = 0;
3633 isdn_tty_at_cout(eb, info);
3634 }
3635 if (m->mdmcmdl < 255) {
3636 c = my_toupper(c);
3637 switch (m->mdmcmdl) {
3638 case 1:
3639 if (c == 'T') {
3640 m->mdmcmd[m->mdmcmdl] = c;
3641 m->mdmcmd[++m->mdmcmdl] = 0;
3642 break;
3643 } else
3644 m->mdmcmdl = 0;
3645 /* Fall through - check for 'A' */
3646 case 0:
3647 if (c == 'A') {
3648 m->mdmcmd[m->mdmcmdl] = c;
3649 m->mdmcmd[++m->mdmcmdl] = 0;
3650 }
3651 break;
3652 default:
3653 m->mdmcmd[m->mdmcmdl] = c;
3654 m->mdmcmd[++m->mdmcmdl] = 0;
3655 }
3656 }
3657 }
3658 }
3659 return total;
3660}
3661
3662/*
3663 * Switch all modem-channels who are online and got a valid
3664 * escape-sequence 1.5 seconds ago, to command-mode.
3665 * This function is called every second via timer-interrupt from within
3666 * timer-dispatcher isdn_timer_function()
3667 */
3668void
3669isdn_tty_modem_escape(void)
3670{
3671 int ton = 0;
3672 int i;
3673 int midx;
3674
3675 for (i = 0; i < ISDN_MAX_CHANNELS; i++)
3676 if (USG_MODEM(dev->usage[i]) && (midx = dev->m_idx[i]) >= 0) {
3677 modem_info *info = &dev->mdm.info[midx];
3678 if (info->online) {
3679 ton = 1;
3680 if ((info->emu.pluscount == 3) &&
3681 time_after(jiffies,
3682 info->emu.lastplus + PLUSWAIT2)) {
3683 info->emu.pluscount = 0;
3684 info->online = 0;
3685 isdn_tty_modem_result(RESULT_OK, info);
3686 }
3687 }
3688 }
3689 isdn_timer_ctrl(ISDN_TIMER_MODEMPLUS, ton);
3690}
3691
3692/*
3693 * Put a RING-message to all modem-channels who have the RI-bit set.
3694 * This function is called every second via timer-interrupt from within
3695 * timer-dispatcher isdn_timer_function()
3696 */
3697void
3698isdn_tty_modem_ring(void)
3699{
3700 int ton = 0;
3701 int i;
3702
3703 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
3704 modem_info *info = &dev->mdm.info[i];
3705 if (info->msr & UART_MSR_RI) {
3706 ton = 1;
3707 isdn_tty_modem_result(RESULT_RING, info);
3708 }
3709 }
3710 isdn_timer_ctrl(ISDN_TIMER_MODEMRING, ton);
3711}
3712
3713/*
3714 * For all online tty's, try sending data to
3715 * the lower levels.
3716 */
3717void
3718isdn_tty_modem_xmit(void)
3719{
3720 int ton = 1;
3721 int i;
3722
3723 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
3724 modem_info *info = &dev->mdm.info[i];
3725 if (info->online) {
3726 ton = 1;
3727 isdn_tty_senddown(info);
3728 isdn_tty_tint(info);
3729 }
3730 }
3731 isdn_timer_ctrl(ISDN_TIMER_MODEMXMIT, ton);
3732}
3733
3734/*
3735 * Check all channels if we have a 'no carrier' timeout.
3736 * Timeout value is set by Register S7.
3737 */
3738void
3739isdn_tty_carrier_timeout(void)
3740{
3741 int ton = 0;
3742 int i;
3743
3744 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
3745 modem_info *info = &dev->mdm.info[i];
3746 if (!info->dialing)
3747 continue;
3748 if (info->emu.carrierwait++ > info->emu.mdmreg[REG_WAITC]) {
3749 info->dialing = 0;
3750 isdn_tty_modem_result(RESULT_NO_CARRIER, info);
3751 isdn_tty_modem_hup(info, 1);
3752 } else
3753 ton = 1;
3754 }
3755 isdn_timer_ctrl(ISDN_TIMER_CARRIER, ton);
3756}
diff --git a/drivers/isdn/i4l/isdn_tty.h b/drivers/isdn/i4l/isdn_tty.h
deleted file mode 100644
index a6f801d2263b..000000000000
--- a/drivers/isdn/i4l/isdn_tty.h
+++ /dev/null
@@ -1,120 +0,0 @@
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
14#define DLE 0x10
15#define ETX 0x03
16#define DC4 0x14
17
18
19/*
20 * Definition of some special Registers of AT-Emulator
21 */
22#define REG_RINGATA 0
23#define REG_RINGCNT 1 /* ring counter register */
24#define REG_ESC 2
25#define REG_CR 3
26#define REG_LF 4
27#define REG_BS 5
28
29#define REG_WAITC 7
30
31#define REG_RESP 12 /* show response messages register */
32#define BIT_RESP 1 /* show response messages bit */
33#define REG_RESPNUM 12 /* show numeric responses register */
34#define BIT_RESPNUM 2 /* show numeric responses bit */
35#define REG_ECHO 12
36#define BIT_ECHO 4
37#define REG_DCD 12
38#define BIT_DCD 8
39#define REG_CTS 12
40#define BIT_CTS 16
41#define REG_DTRR 12
42#define BIT_DTRR 32
43#define REG_DSR 12
44#define BIT_DSR 64
45#define REG_CPPP 12
46#define BIT_CPPP 128
47
48#define REG_DXMT 13
49#define BIT_DXMT 1
50#define REG_T70 13
51#define BIT_T70 2
52#define BIT_T70_EXT 32
53#define REG_DTRHUP 13
54#define BIT_DTRHUP 4
55#define REG_RESPXT 13
56#define BIT_RESPXT 8
57#define REG_CIDONCE 13
58#define BIT_CIDONCE 16
59#define REG_RUNG 13 /* show RUNG message register */
60#define BIT_RUNG 64 /* show RUNG message bit */
61#define REG_DISPLAY 13
62#define BIT_DISPLAY 128
63
64#define REG_L2PROT 14
65#define REG_L3PROT 15
66#define REG_PSIZE 16
67#define REG_WSIZE 17
68#define REG_SI1 18
69#define REG_SI2 19
70#define REG_SI1I 20
71#define REG_PLAN 21
72#define REG_SCREEN 22
73
74#define REG_CPN 23
75#define BIT_CPN 1
76#define REG_CPNFCON 23
77#define BIT_CPNFCON 2
78#define REG_CDN 23
79#define BIT_CDN 4
80
81/* defines for result codes */
82#define RESULT_OK 0
83#define RESULT_CONNECT 1
84#define RESULT_RING 2
85#define RESULT_NO_CARRIER 3
86#define RESULT_ERROR 4
87#define RESULT_CONNECT64000 5
88#define RESULT_NO_DIALTONE 6
89#define RESULT_BUSY 7
90#define RESULT_NO_ANSWER 8
91#define RESULT_RINGING 9
92#define RESULT_NO_MSN_EAZ 10
93#define RESULT_VCON 11
94#define RESULT_RUNG 12
95
96#define TTY_IS_FCLASS1(info) \
97 ((info->emu.mdmreg[REG_L2PROT] == ISDN_PROTO_L2_FAX) && \
98 (info->emu.mdmreg[REG_L3PROT] == ISDN_PROTO_L3_FCLASS1))
99#define TTY_IS_FCLASS2(info) \
100 ((info->emu.mdmreg[REG_L2PROT] == ISDN_PROTO_L2_FAX) && \
101 (info->emu.mdmreg[REG_L3PROT] == ISDN_PROTO_L3_FCLASS2))
102
103extern void isdn_tty_modem_escape(void);
104extern void isdn_tty_modem_ring(void);
105extern void isdn_tty_carrier_timeout(void);
106extern void isdn_tty_modem_xmit(void);
107extern int isdn_tty_modem_init(void);
108extern void isdn_tty_exit(void);
109extern void isdn_tty_readmodem(void);
110extern int isdn_tty_find_icall(int, int, setup_parm *);
111extern int isdn_tty_stat_callback(int, isdn_ctrl *);
112extern int isdn_tty_rcv_skb(int, int, int, struct sk_buff *);
113extern int isdn_tty_capi_facility(capi_msg *cm);
114extern void isdn_tty_at_cout(char *, modem_info *);
115extern void isdn_tty_modem_hup(modem_info *, int);
116#ifdef CONFIG_ISDN_TTY_FAX
117extern int isdn_tty_cmd_PLUSF_FAX(char **, modem_info *);
118extern int isdn_tty_fax_command(modem_info *, isdn_ctrl *);
119extern void isdn_tty_fax_bitorder(modem_info *, struct sk_buff *);
120#endif
diff --git a/drivers/isdn/i4l/isdn_ttyfax.c b/drivers/isdn/i4l/isdn_ttyfax.c
deleted file mode 100644
index 47aae4916730..000000000000
--- a/drivers/isdn/i4l/isdn_ttyfax.c
+++ /dev/null
@@ -1,1123 +0,0 @@
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
151static int
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
319static int
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
411static int
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 (threshold 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) ||
910 (!(info->faxonline & 1)))
911 PARSE_ERROR1;
912 par = isdn_getnum(p);
913 if ((par < 0) || (par > 2))
914 PARSE_ERROR1;
915 f->fet = par;
916 f->code = ISDN_TTY_FAX_ET;
917 cmd.driver = info->isdn_driver;
918 cmd.arg = info->isdn_channel;
919 cmd.command = ISDN_CMD_FAXCMD;
920 isdn_command(&cmd);
921#ifdef ISDN_TTY_FAX_STAT_DEBUG
922 printk(KERN_DEBUG "isdn_tty: Fax FET=%d\n", par);
923#endif
924 return 1;
925 }
926 return 0;
927 }
928 /* K - terminate */
929 if (!strncmp(p[0], "K", 1)) {
930 p[0] += 1;
931 if ((f->phase == ISDN_FAX_PHASE_IDLE) || (f->phase == ISDN_FAX_PHASE_E))
932 PARSE_ERROR1;
933 isdn_tty_modem_hup(info, 1);
934 return 1;
935 }
936 /* LID=string - local fax ID */
937 if (!strncmp(p[0], "LID", 3)) {
938 int i, r;
939 p[0] += 3;
940 switch (*p[0]) {
941 case '?':
942 p[0]++;
943 sprintf(rs, "\r\n\"%s\"", f->id);
944 isdn_tty_at_cout(rs, info);
945 break;
946 case '=':
947 p[0]++;
948 if (*p[0] == '?') {
949 p[0]++;
950 sprintf(rs, "\r\n\"STRING\"");
951 isdn_tty_at_cout(rs, info);
952 } else {
953 if (*p[0] == '"')
954 p[0]++;
955 for (i = 0; (*p[0]) && i < (FAXIDLEN - 1) && (*p[0] != '"'); i++) {
956 f->id[i] = *p[0]++;
957 }
958 if (*p[0] == '"')
959 p[0]++;
960 for (r = i; r < FAXIDLEN; r++) {
961 f->id[r] = 32;
962 }
963 f->id[FAXIDLEN - 1] = 0;
964#ifdef ISDN_TTY_FAX_STAT_DEBUG
965 printk(KERN_DEBUG "isdn_tty: Fax local ID \"%s\"\n", f->id);
966#endif
967 }
968 break;
969 default:
970 PARSE_ERROR1;
971 }
972 return 0;
973 }
974
975 /* MDL? - DCE Model */
976 if (!strncmp(p[0], "MDL?", 4)) {
977 p[0] += 4;
978#ifdef ISDN_TTY_FAX_STAT_DEBUG
979 printk(KERN_DEBUG "isdn_tty: FMDL?\n");
980#endif
981 isdn_tty_at_cout("\r\nisdn4linux", info);
982 return 0;
983 }
984 /* MFR? - DCE Manufacturer */
985 if (!strncmp(p[0], "MFR?", 4)) {
986 p[0] += 4;
987#ifdef ISDN_TTY_FAX_STAT_DEBUG
988 printk(KERN_DEBUG "isdn_tty: FMFR?\n");
989#endif
990 isdn_tty_at_cout("\r\nisdn4linux", info);
991 return 0;
992 }
993 /* MINSP=n - Minimum Speed for Phase C */
994 if (!strncmp(p[0], "MINSP", 5)) {
995 p[0] += 5;
996 switch (*p[0]) {
997 case '?':
998 p[0]++;
999 sprintf(rs, "\r\n%d", f->minsp);
1000 isdn_tty_at_cout(rs, info);
1001 break;
1002 case '=':
1003 p[0]++;
1004 if (*p[0] == '?') {
1005 p[0]++;
1006 sprintf(rs, "\r\n0-5");
1007 isdn_tty_at_cout(rs, info);
1008 } else {
1009 par = isdn_getnum(p);
1010 if ((par < 0) || (par > 5))
1011 PARSE_ERROR1;
1012 f->minsp = par;
1013#ifdef ISDN_TTY_FAX_STAT_DEBUG
1014 printk(KERN_DEBUG "isdn_tty: Fax FMINSP=%d\n", par);
1015#endif
1016 }
1017 break;
1018 default:
1019 PARSE_ERROR1;
1020 }
1021 return 0;
1022 }
1023 /* PHCTO=value - DTE phase C timeout */
1024 if (!strncmp(p[0], "PHCTO", 5)) {
1025 p[0] += 5;
1026 switch (*p[0]) {
1027 case '?':
1028 p[0]++;
1029 sprintf(rs, "\r\n%d", f->phcto);
1030 isdn_tty_at_cout(rs, info);
1031 break;
1032 case '=':
1033 p[0]++;
1034 if (*p[0] == '?') {
1035 p[0]++;
1036 sprintf(rs, "\r\n0-255");
1037 isdn_tty_at_cout(rs, info);
1038 } else {
1039 par = isdn_getnum(p);
1040 if ((par < 0) || (par > 255))
1041 PARSE_ERROR1;
1042 f->phcto = par;
1043#ifdef ISDN_TTY_FAX_STAT_DEBUG
1044 printk(KERN_DEBUG "isdn_tty: Fax FPHCTO=%d\n", par);
1045#endif
1046 }
1047 break;
1048 default:
1049 PARSE_ERROR1;
1050 }
1051 return 0;
1052 }
1053
1054 /* REL=n - Phase C received EOL alignment */
1055 if (!strncmp(p[0], "REL", 3)) {
1056 p[0] += 3;
1057 switch (*p[0]) {
1058 case '?':
1059 p[0]++;
1060 sprintf(rs, "\r\n%d", f->rel);
1061 isdn_tty_at_cout(rs, info);
1062 break;
1063 case '=':
1064 p[0]++;
1065 if (*p[0] == '?') {
1066 p[0]++;
1067 sprintf(rs, "\r\n0,1");
1068 isdn_tty_at_cout(rs, info);
1069 } else {
1070 par = isdn_getnum(p);
1071 if ((par < 0) || (par > 1))
1072 PARSE_ERROR1;
1073 f->rel = par;
1074#ifdef ISDN_TTY_FAX_STAT_DEBUG
1075 printk(KERN_DEBUG "isdn_tty: Fax FREL=%d\n", par);
1076#endif
1077 }
1078 break;
1079 default:
1080 PARSE_ERROR1;
1081 }
1082 return 0;
1083 }
1084 /* REV? - DCE Revision */
1085 if (!strncmp(p[0], "REV?", 4)) {
1086 p[0] += 4;
1087#ifdef ISDN_TTY_FAX_STAT_DEBUG
1088 printk(KERN_DEBUG "isdn_tty: FREV?\n");
1089#endif
1090 strcpy(rss, isdn_tty_fax_revision);
1091 sprintf(rs, "\r\nRev: %s", isdn_getrev(rss));
1092 isdn_tty_at_cout(rs, info);
1093 return 0;
1094 }
1095
1096 /* Phase C Transmit Data Block Size */
1097 if (!strncmp(p[0], "TBC=", 4)) { /* dummy, not used */
1098 p[0] += 4;
1099#ifdef ISDN_TTY_FAX_STAT_DEBUG
1100 printk(KERN_DEBUG "isdn_tty: Fax FTBC=%c\n", *p[0]);
1101#endif
1102 switch (*p[0]) {
1103 case '0':
1104 p[0]++;
1105 break;
1106 default:
1107 PARSE_ERROR1;
1108 }
1109 return 0;
1110 }
1111 printk(KERN_DEBUG "isdn_tty: unknown token=>AT+F%s<\n", p[0]);
1112 PARSE_ERROR1;
1113}
1114
1115int
1116isdn_tty_cmd_PLUSF_FAX(char **p, modem_info *info)
1117{
1118 if (TTY_IS_FCLASS2(info))
1119 return (isdn_tty_cmd_FCLASS2(p, info));
1120 else if (TTY_IS_FCLASS1(info))
1121 return (isdn_tty_cmd_FCLASS1(p, info));
1122 PARSE_ERROR1;
1123}
diff --git a/drivers/isdn/i4l/isdn_ttyfax.h b/drivers/isdn/i4l/isdn_ttyfax.h
deleted file mode 100644
index ccda4fcf8f7b..000000000000
--- a/drivers/isdn/i4l/isdn_ttyfax.h
+++ /dev/null
@@ -1,17 +0,0 @@
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
diff --git a/drivers/isdn/i4l/isdn_v110.c b/drivers/isdn/i4l/isdn_v110.c
deleted file mode 100644
index d11fe76f138f..000000000000
--- a/drivers/isdn/i4l/isdn_v110.c
+++ /dev/null
@@ -1,625 +0,0 @@
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 = kzalloc(sizeof(isdn_v110_stream), GFP_ATOMIC)) == NULL)
96 return NULL;
97 v->key = key;
98 v->nbits = 0;
99 for (i = 0; key & (1 << i); i++)
100 v->nbits++;
101
102 v->nbytes = 8 / v->nbits;
103 v->decodelen = 0;
104
105 switch (key) {
106 case V110_38400:
107 v->OnlineFrame = V110_OnMatrix_38400;
108 v->OfflineFrame = V110_OffMatrix_38400;
109 break;
110 case V110_19200:
111 v->OnlineFrame = V110_OnMatrix_19200;
112 v->OfflineFrame = V110_OffMatrix_19200;
113 break;
114 default:
115 v->OnlineFrame = V110_OnMatrix_9600;
116 v->OfflineFrame = V110_OffMatrix_9600;
117 break;
118 }
119 v->framelen = v->nbytes * 10;
120 v->SyncInit = 5;
121 v->introducer = 0;
122 v->dbit = 1;
123 v->b = 0;
124 v->skbres = hdrlen;
125 v->maxsize = maxsize - hdrlen;
126 if ((v->encodebuf = kmalloc(maxsize, GFP_ATOMIC)) == NULL) {
127 kfree(v);
128 return NULL;
129 }
130 return v;
131}
132
133/* isdn_v110_close frees private V.110 data structures */
134void
135isdn_v110_close(isdn_v110_stream *v)
136{
137 if (v == NULL)
138 return;
139#ifdef ISDN_V110_DEBUG
140 printk(KERN_DEBUG "v110 close\n");
141#endif
142 kfree(v->encodebuf);
143 kfree(v);
144}
145
146
147/*
148 * ValidHeaderBytes return the number of valid bytes in v->decodebuf
149 */
150static int
151ValidHeaderBytes(isdn_v110_stream *v)
152{
153 int i;
154 for (i = 0; (i < v->decodelen) && (i < v->nbytes); i++)
155 if ((v->decodebuf[i] & v->key) != 0)
156 break;
157 return i;
158}
159
160/*
161 * SyncHeader moves the decodebuf ptr to the next valid header
162 */
163static void
164SyncHeader(isdn_v110_stream *v)
165{
166 unsigned char *rbuf = v->decodebuf;
167 int len = v->decodelen;
168
169 if (len == 0)
170 return;
171 for (rbuf++, len--; len > 0; len--, rbuf++) /* such den SyncHeader in buf ! */
172 if ((*rbuf & v->key) == 0) /* erstes byte gefunden ? */
173 break; /* jupp! */
174 if (len)
175 memcpy(v->decodebuf, rbuf, len);
176
177 v->decodelen = len;
178#ifdef ISDN_V110_DEBUG
179 printk(KERN_DEBUG "isdn_v110: Header resync\n");
180#endif
181}
182
183/* DecodeMatrix takes n (n>=1) matrices (v110 frames, 10 bytes) where
184 len is the number of matrix-lines. len must be a multiple of 10, i.e.
185 only complete matices must be given.
186 From these, netto data is extracted and returned in buf. The return-value
187 is the bytecount of the decoded data.
188*/
189static int
190DecodeMatrix(isdn_v110_stream *v, unsigned char *m, int len, unsigned char *buf)
191{
192 int line = 0;
193 int buflen = 0;
194 int mbit = 64;
195 int introducer = v->introducer;
196 int dbit = v->dbit;
197 unsigned char b = v->b;
198
199 while (line < len) { /* Are we done with all lines of the matrix? */
200 if ((line % 10) == 0) { /* the 0. line of the matrix is always 0 ! */
201 if (m[line] != 0x00) { /* not 0 ? -> error! */
202#ifdef ISDN_V110_DEBUG
203 printk(KERN_DEBUG "isdn_v110: DecodeMatrix, V110 Bad Header\n");
204 /* returning now is not the right thing, though :-( */
205#endif
206 }
207 line++; /* next line of matrix */
208 continue;
209 } else if ((line % 10) == 5) { /* in line 5 there's only e-bits ! */
210 if ((m[line] & 0x70) != 0x30) { /* 011 has to be at the beginning! */
211#ifdef ISDN_V110_DEBUG
212 printk(KERN_DEBUG "isdn_v110: DecodeMatrix, V110 Bad 5th line\n");
213 /* returning now is not the right thing, though :-( */
214#endif
215 }
216 line++; /* next line */
217 continue;
218 } else if (!introducer) { /* every byte starts with 10 (stopbit, startbit) */
219 introducer = (m[line] & mbit) ? 0 : 1; /* current bit of the matrix */
220 next_byte:
221 if (mbit > 2) { /* was it the last bit in this line ? */
222 mbit >>= 1; /* no -> take next */
223 continue;
224 } /* otherwise start with leftmost bit in the next line */
225 mbit = 64;
226 line++;
227 continue;
228 } else { /* otherwise we need to set a data bit */
229 if (m[line] & mbit) /* was that bit set in the matrix ? */
230 b |= dbit; /* yes -> set it in the data byte */
231 else
232 b &= dbit - 1; /* no -> clear it in the data byte */
233 if (dbit < 128) /* is that data byte done ? */
234 dbit <<= 1; /* no, got the next bit */
235 else { /* data byte is done */
236 buf[buflen++] = b; /* copy byte into the output buffer */
237 introducer = b = 0; /* init of the intro sequence and of the data byte */
238 dbit = 1; /* next we look for the 0th bit */
239 }
240 goto next_byte; /* look for next bit in the matrix */
241 }
242 }
243 v->introducer = introducer;
244 v->dbit = dbit;
245 v->b = b;
246 return buflen; /* return number of bytes in the output buffer */
247}
248
249/*
250 * DecodeStream receives V.110 coded data from the input stream. It recovers the
251 * original frames.
252 * The input stream doesn't need to be framed
253 */
254struct sk_buff *
255isdn_v110_decode(isdn_v110_stream *v, struct sk_buff *skb)
256{
257 int i;
258 int j;
259 int len;
260 unsigned char *v110_buf;
261 unsigned char *rbuf;
262
263 if (!skb) {
264 printk(KERN_WARNING "isdn_v110_decode called with NULL skb!\n");
265 return NULL;
266 }
267 rbuf = skb->data;
268 len = skb->len;
269 if (v == NULL) {
270 /* invalid handle, no chance to proceed */
271 printk(KERN_WARNING "isdn_v110_decode called with NULL stream!\n");
272 dev_kfree_skb(skb);
273 return NULL;
274 }
275 if (v->decodelen == 0) /* cache empty? */
276 for (; len > 0; len--, rbuf++) /* scan for SyncHeader in buf */
277 if ((*rbuf & v->key) == 0)
278 break; /* found first byte */
279 if (len == 0) {
280 dev_kfree_skb(skb);
281 return NULL;
282 }
283 /* copy new data to decode-buffer */
284 memcpy(&(v->decodebuf[v->decodelen]), rbuf, len);
285 v->decodelen += len;
286ReSync:
287 if (v->decodelen < v->nbytes) { /* got a new header ? */
288 dev_kfree_skb(skb);
289 return NULL; /* no, try later */
290 }
291 if (ValidHeaderBytes(v) != v->nbytes) { /* is that a valid header? */
292 SyncHeader(v); /* no -> look for header */
293 goto ReSync;
294 }
295 len = (v->decodelen - (v->decodelen % (10 * v->nbytes))) / v->nbytes;
296 if ((v110_buf = kmalloc(len, GFP_ATOMIC)) == NULL) {
297 printk(KERN_WARNING "isdn_v110_decode: Couldn't allocate v110_buf\n");
298 dev_kfree_skb(skb);
299 return NULL;
300 }
301 for (i = 0; i < len; i++) {
302 v110_buf[i] = 0;
303 for (j = 0; j < v->nbytes; j++)
304 v110_buf[i] |= (v->decodebuf[(i * v->nbytes) + j] & v->key) << (8 - ((j + 1) * v->nbits));
305 v110_buf[i] = FlipBits(v110_buf[i], v->nbits);
306 }
307 v->decodelen = (v->decodelen % (10 * v->nbytes));
308 memcpy(v->decodebuf, &(v->decodebuf[len * v->nbytes]), v->decodelen);
309
310 skb_trim(skb, DecodeMatrix(v, v110_buf, len, skb->data));
311 kfree(v110_buf);
312 if (skb->len)
313 return skb;
314 else {
315 kfree_skb(skb);
316 return NULL;
317 }
318}
319
320/* EncodeMatrix takes input data in buf, len is the bytecount.
321 Data is encoded into v110 frames in m. Return value is the number of
322 matrix-lines generated.
323*/
324static int
325EncodeMatrix(unsigned char *buf, int len, unsigned char *m, int mlen)
326{
327 int line = 0;
328 int i = 0;
329 int mbit = 128;
330 int dbit = 1;
331 int introducer = 3;
332 int ibit[] = {0, 1, 1};
333
334 while ((i < len) && (line < mlen)) { /* while we still have input data */
335 switch (line % 10) { /* in which line of the matrix are we? */
336 case 0:
337 m[line++] = 0x00; /* line 0 is always 0 */
338 mbit = 128; /* go on with the 7th bit */
339 break;
340 case 5:
341 m[line++] = 0xbf; /* line 5 is always 10111111 */
342 mbit = 128; /* go on with the 7th bit */
343 break;
344 }
345 if (line >= mlen) {
346 printk(KERN_WARNING "isdn_v110 (EncodeMatrix): buffer full!\n");
347 return line;
348 }
349 next_bit:
350 switch (mbit) { /* leftmost or rightmost bit ? */
351 case 1:
352 line++; /* rightmost -> go to next line */
353 if (line >= mlen) {
354 printk(KERN_WARNING "isdn_v110 (EncodeMatrix): buffer full!\n");
355 return line;
356 }
357 /* fall through */
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 /* fall through */
391 case 2:
392 m[line++] = 0xfe;
393 /* fall through */
394 case 3:
395 m[line++] = 0xfe;
396 /* fall through */
397 case 4:
398 m[line++] = 0xfe;
399 /* fall through */
400 case 5:
401 m[line++] = 0xbf;
402 /* fall through */
403 case 6:
404 m[line++] = 0xfe;
405 /* fall through */
406 case 7:
407 m[line++] = 0xfe;
408 /* fall through */
409 case 8:
410 m[line++] = 0xfe;
411 /* fall through */
412 case 9:
413 m[line++] = 0xfe;
414 }
415 return line; /* that's how many lines we have */
416}
417
418/*
419 * Build a sync frame.
420 */
421static struct sk_buff *
422isdn_v110_sync(isdn_v110_stream *v)
423{
424 struct sk_buff *skb;
425
426 if (v == NULL) {
427 /* invalid handle, no chance to proceed */
428 printk(KERN_WARNING "isdn_v110_sync called with NULL stream!\n");
429 return NULL;
430 }
431 if ((skb = dev_alloc_skb(v->framelen + v->skbres))) {
432 skb_reserve(skb, v->skbres);
433 skb_put_data(skb, v->OfflineFrame, v->framelen);
434 }
435 return skb;
436}
437
438/*
439 * Build an idle frame.
440 */
441static struct sk_buff *
442isdn_v110_idle(isdn_v110_stream *v)
443{
444 struct sk_buff *skb;
445
446 if (v == NULL) {
447 /* invalid handle, no chance to proceed */
448 printk(KERN_WARNING "isdn_v110_sync called with NULL stream!\n");
449 return NULL;
450 }
451 if ((skb = dev_alloc_skb(v->framelen + v->skbres))) {
452 skb_reserve(skb, v->skbres);
453 skb_put_data(skb, v->OnlineFrame, v->framelen);
454 }
455 return skb;
456}
457
458struct sk_buff *
459isdn_v110_encode(isdn_v110_stream *v, struct sk_buff *skb)
460{
461 int i;
462 int j;
463 int rlen;
464 int mlen;
465 int olen;
466 int size;
467 int sval1;
468 int sval2;
469 int nframes;
470 unsigned char *v110buf;
471 unsigned char *rbuf;
472 struct sk_buff *nskb;
473
474 if (v == NULL) {
475 /* invalid handle, no chance to proceed */
476 printk(KERN_WARNING "isdn_v110_encode called with NULL stream!\n");
477 return NULL;
478 }
479 if (!skb) {
480 /* invalid skb, no chance to proceed */
481 printk(KERN_WARNING "isdn_v110_encode called with NULL skb!\n");
482 return NULL;
483 }
484 rlen = skb->len;
485 nframes = (rlen + 3) / 4;
486 v110buf = v->encodebuf;
487 if ((nframes * 40) > v->maxsize) {
488 size = v->maxsize;
489 rlen = v->maxsize / 40;
490 } else
491 size = nframes * 40;
492 if (!(nskb = dev_alloc_skb(size + v->skbres + sizeof(int)))) {
493 printk(KERN_WARNING "isdn_v110_encode: Couldn't alloc skb\n");
494 return NULL;
495 }
496 skb_reserve(nskb, v->skbres + sizeof(int));
497 if (skb->len == 0) {
498 skb_put_data(nskb, v->OnlineFrame, v->framelen);
499 *((int *)skb_push(nskb, sizeof(int))) = 0;
500 return nskb;
501 }
502 mlen = EncodeMatrix(skb->data, rlen, v110buf, size);
503 /* now distribute 2 or 4 bits each to the output stream! */
504 rbuf = skb_put(nskb, size);
505 olen = 0;
506 sval1 = 8 - v->nbits;
507 sval2 = v->key << sval1;
508 for (i = 0; i < mlen; i++) {
509 v110buf[i] = FlipBits(v110buf[i], v->nbits);
510 for (j = 0; j < v->nbytes; j++) {
511 if (size--)
512 *rbuf++ = ~v->key | (((v110buf[i] << (j * v->nbits)) & sval2) >> sval1);
513 else {
514 printk(KERN_WARNING "isdn_v110_encode: buffers full!\n");
515 goto buffer_full;
516 }
517 olen++;
518 }
519 }
520buffer_full:
521 skb_trim(nskb, olen);
522 *((int *)skb_push(nskb, sizeof(int))) = rlen;
523 return nskb;
524}
525
526int
527isdn_v110_stat_callback(int idx, isdn_ctrl *c)
528{
529 isdn_v110_stream *v = NULL;
530 int i;
531 int ret = 0;
532
533 if (idx < 0)
534 return 0;
535 switch (c->command) {
536 case ISDN_STAT_BSENT:
537 /* Keep the send-queue of the driver filled
538 * with frames:
539 * If number of outstanding frames < 3,
540 * send down an Idle-Frame (or an Sync-Frame, if
541 * v->SyncInit != 0).
542 */
543 if (!(v = dev->v110[idx]))
544 return 0;
545 atomic_inc(&dev->v110use[idx]);
546 for (i = 0; i * v->framelen < c->parm.length; i++) {
547 if (v->skbidle > 0) {
548 v->skbidle--;
549 ret = 1;
550 } else {
551 if (v->skbuser > 0)
552 v->skbuser--;
553 ret = 0;
554 }
555 }
556 for (i = v->skbuser + v->skbidle; i < 2; i++) {
557 struct sk_buff *skb;
558 if (v->SyncInit > 0)
559 skb = isdn_v110_sync(v);
560 else
561 skb = isdn_v110_idle(v);
562 if (skb) {
563 if (dev->drv[c->driver]->interface->writebuf_skb(c->driver, c->arg, 1, skb) <= 0) {
564 dev_kfree_skb(skb);
565 break;
566 } else {
567 if (v->SyncInit)
568 v->SyncInit--;
569 v->skbidle++;
570 }
571 } else
572 break;
573 }
574 atomic_dec(&dev->v110use[idx]);
575 return ret;
576 case ISDN_STAT_DHUP:
577 case ISDN_STAT_BHUP:
578 while (1) {
579 atomic_inc(&dev->v110use[idx]);
580 if (atomic_dec_and_test(&dev->v110use[idx])) {
581 isdn_v110_close(dev->v110[idx]);
582 dev->v110[idx] = NULL;
583 break;
584 }
585 mdelay(1);
586 }
587 break;
588 case ISDN_STAT_BCONN:
589 if (dev->v110emu[idx] && (dev->v110[idx] == NULL)) {
590 int hdrlen = dev->drv[c->driver]->interface->hl_hdrlen;
591 int maxsize = dev->drv[c->driver]->interface->maxbufsize;
592 atomic_inc(&dev->v110use[idx]);
593 switch (dev->v110emu[idx]) {
594 case ISDN_PROTO_L2_V11096:
595 dev->v110[idx] = isdn_v110_open(V110_9600, hdrlen, maxsize);
596 break;
597 case ISDN_PROTO_L2_V11019:
598 dev->v110[idx] = isdn_v110_open(V110_19200, hdrlen, maxsize);
599 break;
600 case ISDN_PROTO_L2_V11038:
601 dev->v110[idx] = isdn_v110_open(V110_38400, hdrlen, maxsize);
602 break;
603 default:;
604 }
605 if ((v = dev->v110[idx])) {
606 while (v->SyncInit) {
607 struct sk_buff *skb = isdn_v110_sync(v);
608 if (dev->drv[c->driver]->interface->writebuf_skb(c->driver, c->arg, 1, skb) <= 0) {
609 dev_kfree_skb(skb);
610 /* Unable to send, try later */
611 break;
612 }
613 v->SyncInit--;
614 v->skbidle++;
615 }
616 } else
617 printk(KERN_WARNING "isdn_v110: Couldn't open stream for chan %d\n", idx);
618 atomic_dec(&dev->v110use[idx]);
619 }
620 break;
621 default:
622 return 0;
623 }
624 return 0;
625}
diff --git a/drivers/isdn/i4l/isdn_v110.h b/drivers/isdn/i4l/isdn_v110.h
deleted file mode 100644
index de774ab598c9..000000000000
--- a/drivers/isdn/i4l/isdn_v110.h
+++ /dev/null
@@ -1,29 +0,0 @@
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
deleted file mode 100644
index 48bfbcb4a09d..000000000000
--- a/drivers/isdn/i4l/isdn_x25iface.c
+++ /dev/null
@@ -1,332 +0,0 @@
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 which 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/slab.h>
24#include <linux/wanrouter.h>
25#include <net/x25device.h>
26#include "isdn_x25iface.h"
27
28/* for debugging messages not to cause an oops when device pointer is NULL*/
29#define MY_DEVNAME(dev) ((dev) ? (dev)->name : "DEVICE UNSPECIFIED")
30
31
32typedef struct isdn_x25iface_proto_data {
33 int magic;
34 enum wan_states state;
35 /* Private stuff, not to be accessed via proto_data. We provide the
36 other storage for the concap_proto instance here as well,
37 enabling us to allocate both with just one kmalloc(): */
38 struct concap_proto priv;
39} ix25_pdata_t;
40
41
42
43/* is now in header file (extern): struct concap_proto * isdn_x25iface_proto_new(void); */
44static void isdn_x25iface_proto_del(struct concap_proto *);
45static int isdn_x25iface_proto_close(struct concap_proto *);
46static int isdn_x25iface_proto_restart(struct concap_proto *,
47 struct net_device *,
48 struct concap_device_ops *);
49static int isdn_x25iface_xmit(struct concap_proto *, struct sk_buff *);
50static int isdn_x25iface_receive(struct concap_proto *, struct sk_buff *);
51static int isdn_x25iface_connect_ind(struct concap_proto *);
52static int isdn_x25iface_disconn_ind(struct concap_proto *);
53
54
55static struct concap_proto_ops ix25_pops = {
56 .proto_new = &isdn_x25iface_proto_new,
57 .proto_del = &isdn_x25iface_proto_del,
58 .restart = &isdn_x25iface_proto_restart,
59 .close = &isdn_x25iface_proto_close,
60 .encap_and_xmit = &isdn_x25iface_xmit,
61 .data_ind = &isdn_x25iface_receive,
62 .connect_ind = &isdn_x25iface_connect_ind,
63 .disconn_ind = &isdn_x25iface_disconn_ind
64};
65
66/* error message helper function */
67static void illegal_state_warn(unsigned state, unsigned char firstbyte)
68{
69 printk(KERN_WARNING "isdn_x25iface: firstbyte %x illegal in"
70 "current state %d\n", firstbyte, state);
71}
72
73/* check protocol data field for consistency */
74static int pdata_is_bad(ix25_pdata_t *pda) {
75
76 if (pda && pda->magic == ISDN_X25IFACE_MAGIC) return 0;
77 printk(KERN_WARNING
78 "isdn_x25iface_xxx: illegal pointer to proto data\n");
79 return 1;
80}
81
82/* create a new x25 interface protocol instance
83 */
84struct concap_proto *isdn_x25iface_proto_new(void)
85{
86 ix25_pdata_t *tmp = kmalloc(sizeof(ix25_pdata_t), GFP_KERNEL);
87 IX25DEBUG("isdn_x25iface_proto_new\n");
88 if (tmp) {
89 tmp->magic = ISDN_X25IFACE_MAGIC;
90 tmp->state = WAN_UNCONFIGURED;
91 /* private data space used to hold the concap_proto data.
92 Only to be accessed via the returned pointer */
93 spin_lock_init(&tmp->priv.lock);
94 tmp->priv.dops = NULL;
95 tmp->priv.net_dev = NULL;
96 tmp->priv.pops = &ix25_pops;
97 tmp->priv.flags = 0;
98 tmp->priv.proto_data = tmp;
99 return (&(tmp->priv));
100 }
101 return NULL;
102};
103
104/* close the x25iface encapsulation protocol
105 */
106static int isdn_x25iface_proto_close(struct concap_proto *cprot) {
107
108 ix25_pdata_t *tmp;
109 int ret = 0;
110 ulong flags;
111
112 if (!cprot) {
113 printk(KERN_ERR "isdn_x25iface_proto_close: "
114 "invalid concap_proto pointer\n");
115 return -1;
116 }
117 IX25DEBUG("isdn_x25iface_proto_close %s \n", MY_DEVNAME(cprot->net_dev));
118 spin_lock_irqsave(&cprot->lock, flags);
119 cprot->dops = NULL;
120 cprot->net_dev = NULL;
121 tmp = cprot->proto_data;
122 if (pdata_is_bad(tmp)) {
123 ret = -1;
124 } else {
125 tmp->state = WAN_UNCONFIGURED;
126 }
127 spin_unlock_irqrestore(&cprot->lock, flags);
128 return ret;
129}
130
131/* Delete the x25iface encapsulation protocol instance
132 */
133static void isdn_x25iface_proto_del(struct concap_proto *cprot) {
134
135 ix25_pdata_t *tmp;
136
137 IX25DEBUG("isdn_x25iface_proto_del \n");
138 if (!cprot) {
139 printk(KERN_ERR "isdn_x25iface_proto_del: "
140 "concap_proto pointer is NULL\n");
141 return;
142 }
143 tmp = cprot->proto_data;
144 if (tmp == NULL) {
145 printk(KERN_ERR "isdn_x25iface_proto_del: inconsistent "
146 "proto_data pointer (maybe already deleted?)\n");
147 return;
148 }
149 /* close if the protocol is still open */
150 if (cprot->dops) isdn_x25iface_proto_close(cprot);
151 /* freeing the storage should be sufficient now. But some additional
152 settings might help to catch wild pointer bugs */
153 tmp->magic = 0;
154 cprot->proto_data = NULL;
155
156 kfree(tmp);
157 return;
158}
159
160/* (re-)initialize the data structures for x25iface encapsulation
161 */
162static int isdn_x25iface_proto_restart(struct concap_proto *cprot,
163 struct net_device *ndev,
164 struct concap_device_ops *dops)
165{
166 ix25_pdata_t *pda = cprot->proto_data;
167 ulong flags;
168
169 IX25DEBUG("isdn_x25iface_proto_restart %s \n", MY_DEVNAME(ndev));
170
171 if (pdata_is_bad(pda)) return -1;
172
173 if (!(dops && dops->data_req && dops->connect_req
174 && dops->disconn_req)) {
175 printk(KERN_WARNING "isdn_x25iface_restart: required dops"
176 " missing\n");
177 isdn_x25iface_proto_close(cprot);
178 return -1;
179 }
180 spin_lock_irqsave(&cprot->lock, flags);
181 cprot->net_dev = ndev;
182 cprot->pops = &ix25_pops;
183 cprot->dops = dops;
184 pda->state = WAN_DISCONNECTED;
185 spin_unlock_irqrestore(&cprot->lock, flags);
186 return 0;
187}
188
189/* deliver a dl_data frame received from i4l HL driver to the network layer
190 */
191static int isdn_x25iface_receive(struct concap_proto *cprot, struct sk_buff *skb)
192{
193 IX25DEBUG("isdn_x25iface_receive %s \n", MY_DEVNAME(cprot->net_dev));
194 if (((ix25_pdata_t *)(cprot->proto_data))
195 ->state == WAN_CONNECTED) {
196 if (skb_push(skb, 1)) {
197 skb->data[0] = X25_IFACE_DATA;
198 skb->protocol = x25_type_trans(skb, cprot->net_dev);
199 netif_rx(skb);
200 return 0;
201 }
202 }
203 printk(KERN_WARNING "isdn_x25iface_receive %s: not connected, skb dropped\n", MY_DEVNAME(cprot->net_dev));
204 dev_kfree_skb(skb);
205 return -1;
206}
207
208/* a connection set up is indicated by lower layer
209 */
210static int isdn_x25iface_connect_ind(struct concap_proto *cprot)
211{
212 struct sk_buff *skb;
213 enum wan_states *state_p
214 = &(((ix25_pdata_t *)(cprot->proto_data))->state);
215 IX25DEBUG("isdn_x25iface_connect_ind %s \n"
216 , MY_DEVNAME(cprot->net_dev));
217 if (*state_p == WAN_UNCONFIGURED) {
218 printk(KERN_WARNING
219 "isdn_x25iface_connect_ind while unconfigured %s\n"
220 , MY_DEVNAME(cprot->net_dev));
221 return -1;
222 }
223 *state_p = WAN_CONNECTED;
224
225 skb = dev_alloc_skb(1);
226 if (skb) {
227 skb_put_u8(skb, X25_IFACE_CONNECT);
228 skb->protocol = x25_type_trans(skb, cprot->net_dev);
229 netif_rx(skb);
230 return 0;
231 } else {
232 printk(KERN_WARNING "isdn_x25iface_connect_ind: "
233 " out of memory -- disconnecting\n");
234 cprot->dops->disconn_req(cprot);
235 return -1;
236 }
237}
238
239/* a disconnect is indicated by lower layer
240 */
241static int isdn_x25iface_disconn_ind(struct concap_proto *cprot)
242{
243 struct sk_buff *skb;
244 enum wan_states *state_p
245 = &(((ix25_pdata_t *)(cprot->proto_data))->state);
246 IX25DEBUG("isdn_x25iface_disconn_ind %s \n", MY_DEVNAME(cprot->net_dev));
247 if (*state_p == WAN_UNCONFIGURED) {
248 printk(KERN_WARNING
249 "isdn_x25iface_disconn_ind while unconfigured\n");
250 return -1;
251 }
252 if (!cprot->net_dev) return -1;
253 *state_p = WAN_DISCONNECTED;
254 skb = dev_alloc_skb(1);
255 if (skb) {
256 skb_put_u8(skb, X25_IFACE_DISCONNECT);
257 skb->protocol = x25_type_trans(skb, cprot->net_dev);
258 netif_rx(skb);
259 return 0;
260 } else {
261 printk(KERN_WARNING "isdn_x25iface_disconn_ind:"
262 " out of memory\n");
263 return -1;
264 }
265}
266
267/* process a frame handed over to us from linux network layer. First byte
268 semantics as defined in Documentation/networking/x25-iface.txt
269*/
270static int isdn_x25iface_xmit(struct concap_proto *cprot, struct sk_buff *skb)
271{
272 unsigned char firstbyte = skb->data[0];
273 enum wan_states *state = &((ix25_pdata_t *)cprot->proto_data)->state;
274 int ret = 0;
275 IX25DEBUG("isdn_x25iface_xmit: %s first=%x state=%d\n",
276 MY_DEVNAME(cprot->net_dev), firstbyte, *state);
277 switch (firstbyte) {
278 case X25_IFACE_DATA:
279 if (*state == WAN_CONNECTED) {
280 skb_pull(skb, 1);
281 netif_trans_update(cprot->net_dev);
282 ret = (cprot->dops->data_req(cprot, skb));
283 /* prepare for future retransmissions */
284 if (ret) skb_push(skb, 1);
285 return ret;
286 }
287 illegal_state_warn(*state, firstbyte);
288 break;
289 case X25_IFACE_CONNECT:
290 if (*state == WAN_DISCONNECTED) {
291 *state = WAN_CONNECTING;
292 ret = cprot->dops->connect_req(cprot);
293 if (ret) {
294 /* reset state and notify upper layer about
295 * immidiatly failed attempts */
296 isdn_x25iface_disconn_ind(cprot);
297 }
298 } else {
299 illegal_state_warn(*state, firstbyte);
300 }
301 break;
302 case X25_IFACE_DISCONNECT:
303 switch (*state) {
304 case WAN_DISCONNECTED:
305 /* Should not happen. However, give upper layer a
306 chance to recover from inconstistency but don't
307 trust the lower layer sending the disconn_confirm
308 when already disconnected */
309 printk(KERN_WARNING "isdn_x25iface_xmit: disconnect "
310 " requested while disconnected\n");
311 isdn_x25iface_disconn_ind(cprot);
312 break; /* prevent infinite loops */
313 case WAN_CONNECTING:
314 case WAN_CONNECTED:
315 *state = WAN_DISCONNECTED;
316 cprot->dops->disconn_req(cprot);
317 break;
318 default:
319 illegal_state_warn(*state, firstbyte);
320 }
321 break;
322 case X25_IFACE_PARAMS:
323 printk(KERN_WARNING "isdn_x25iface_xmit: setting of lapb"
324 " options not yet supported\n");
325 break;
326 default:
327 printk(KERN_WARNING "isdn_x25iface_xmit: frame with illegal"
328 " first byte %x ignored:\n", firstbyte);
329 }
330 dev_kfree_skb(skb);
331 return 0;
332}
diff --git a/drivers/isdn/i4l/isdn_x25iface.h b/drivers/isdn/i4l/isdn_x25iface.h
deleted file mode 100644
index ca08e082cf7c..000000000000
--- a/drivers/isdn/i4l/isdn_x25iface.h
+++ /dev/null
@@ -1,30 +0,0 @@
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/isdn.h>
23#include <linux/concap.h>
24
25extern struct concap_proto_ops *isdn_x25iface_concap_proto_ops_pt;
26extern struct concap_proto *isdn_x25iface_proto_new(void);
27
28
29
30#endif
diff --git a/drivers/isdn/isdnloop/Makefile b/drivers/isdn/isdnloop/Makefile
deleted file mode 100644
index 5ff4c0e09768..000000000000
--- a/drivers/isdn/isdnloop/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
1# SPDX-License-Identifier: GPL-2.0-only
2# Makefile for the isdnloop ISDN device driver
3
4# Each configuration option enables a list of files.
5
6obj-$(CONFIG_ISDN_DRV_LOOP) += isdnloop.o
diff --git a/drivers/isdn/isdnloop/isdnloop.c b/drivers/isdn/isdnloop/isdnloop.c
deleted file mode 100644
index 755c6bbc9553..000000000000
--- a/drivers/isdn/isdnloop/isdnloop.c
+++ /dev/null
@@ -1,1528 +0,0 @@
1/* $Id: isdnloop.c,v 1.11.6.7 2001/11/11 19:54:31 kai Exp $
2 *
3 * ISDN low-level module implementing a dummy loop driver.
4 *
5 * Copyright 1997 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#include <linux/module.h>
13#include <linux/interrupt.h>
14#include <linux/slab.h>
15#include <linux/init.h>
16#include <linux/sched.h>
17#include "isdnloop.h"
18
19static char *isdnloop_id = "loop0";
20
21MODULE_DESCRIPTION("ISDN4Linux: Pseudo Driver that simulates an ISDN card");
22MODULE_AUTHOR("Fritz Elfert");
23MODULE_LICENSE("GPL");
24module_param(isdnloop_id, charp, 0);
25MODULE_PARM_DESC(isdnloop_id, "ID-String of first card");
26
27static int isdnloop_addcard(char *);
28
29/*
30 * Free queue completely.
31 *
32 * Parameter:
33 * card = pointer to card struct
34 * channel = channel number
35 */
36static void
37isdnloop_free_queue(isdnloop_card *card, int channel)
38{
39 struct sk_buff_head *queue = &card->bqueue[channel];
40
41 skb_queue_purge(queue);
42 card->sndcount[channel] = 0;
43}
44
45/*
46 * Send B-Channel data to another virtual card.
47 * This routine is called via timer-callback from isdnloop_pollbchan().
48 *
49 * Parameter:
50 * card = pointer to card struct.
51 * ch = channel number (0-based)
52 */
53static void
54isdnloop_bchan_send(isdnloop_card *card, int ch)
55{
56 isdnloop_card *rcard = card->rcard[ch];
57 int rch = card->rch[ch], len, ack;
58 struct sk_buff *skb;
59 isdn_ctrl cmd;
60
61 while (card->sndcount[ch]) {
62 skb = skb_dequeue(&card->bqueue[ch]);
63 if (skb) {
64 len = skb->len;
65 card->sndcount[ch] -= len;
66 ack = *(skb->head); /* used as scratch area */
67 cmd.driver = card->myid;
68 cmd.arg = ch;
69 if (rcard) {
70 rcard->interface.rcvcallb_skb(rcard->myid, rch, skb);
71 } else {
72 printk(KERN_WARNING "isdnloop: no rcard, skb dropped\n");
73 dev_kfree_skb(skb);
74
75 }
76 cmd.command = ISDN_STAT_BSENT;
77 cmd.parm.length = len;
78 card->interface.statcallb(&cmd);
79 } else
80 card->sndcount[ch] = 0;
81 }
82}
83
84/*
85 * Send/Receive Data to/from the B-Channel.
86 * This routine is called via timer-callback.
87 * It schedules itself while any B-Channel is open.
88 *
89 * Parameter:
90 * data = pointer to card struct, set by kernel timer.data
91 */
92static void
93isdnloop_pollbchan(struct timer_list *t)
94{
95 isdnloop_card *card = from_timer(card, t, rb_timer);
96 unsigned long flags;
97
98 if (card->flags & ISDNLOOP_FLAGS_B1ACTIVE)
99 isdnloop_bchan_send(card, 0);
100 if (card->flags & ISDNLOOP_FLAGS_B2ACTIVE)
101 isdnloop_bchan_send(card, 1);
102 if (card->flags & (ISDNLOOP_FLAGS_B1ACTIVE | ISDNLOOP_FLAGS_B2ACTIVE)) {
103 /* schedule b-channel polling again */
104 spin_lock_irqsave(&card->isdnloop_lock, flags);
105 card->rb_timer.expires = jiffies + ISDNLOOP_TIMER_BCREAD;
106 add_timer(&card->rb_timer);
107 card->flags |= ISDNLOOP_FLAGS_RBTIMER;
108 spin_unlock_irqrestore(&card->isdnloop_lock, flags);
109 } else
110 card->flags &= ~ISDNLOOP_FLAGS_RBTIMER;
111}
112
113/*
114 * Parse ICN-type setup string and fill fields of setup-struct
115 * with parsed data.
116 *
117 * Parameter:
118 * setup = setup string, format: [caller-id],si1,si2,[called-id]
119 * cmd = pointer to struct to be filled.
120 */
121static void
122isdnloop_parse_setup(char *setup, isdn_ctrl *cmd)
123{
124 char *t = setup;
125 char *s = strchr(t, ',');
126
127 *s++ = '\0';
128 strlcpy(cmd->parm.setup.phone, t, sizeof(cmd->parm.setup.phone));
129 s = strchr(t = s, ',');
130 *s++ = '\0';
131 if (!strlen(t))
132 cmd->parm.setup.si1 = 0;
133 else
134 cmd->parm.setup.si1 = simple_strtoul(t, NULL, 10);
135 s = strchr(t = s, ',');
136 *s++ = '\0';
137 if (!strlen(t))
138 cmd->parm.setup.si2 = 0;
139 else
140 cmd->parm.setup.si2 =
141 simple_strtoul(t, NULL, 10);
142 strlcpy(cmd->parm.setup.eazmsn, s, sizeof(cmd->parm.setup.eazmsn));
143 cmd->parm.setup.plan = 0;
144 cmd->parm.setup.screen = 0;
145}
146
147typedef struct isdnloop_stat {
148 char *statstr;
149 int command;
150 int action;
151} isdnloop_stat;
152/* *INDENT-OFF* */
153static isdnloop_stat isdnloop_stat_table[] = {
154 {"BCON_", ISDN_STAT_BCONN, 1}, /* B-Channel connected */
155 {"BDIS_", ISDN_STAT_BHUP, 2}, /* B-Channel disconnected */
156 {"DCON_", ISDN_STAT_DCONN, 0}, /* D-Channel connected */
157 {"DDIS_", ISDN_STAT_DHUP, 0}, /* D-Channel disconnected */
158 {"DCAL_I", ISDN_STAT_ICALL, 3}, /* Incoming call dialup-line */
159 {"DSCA_I", ISDN_STAT_ICALL, 3}, /* Incoming call 1TR6-SPV */
160 {"FCALL", ISDN_STAT_ICALL, 4}, /* Leased line connection up */
161 {"CIF", ISDN_STAT_CINF, 5}, /* Charge-info, 1TR6-type */
162 {"AOC", ISDN_STAT_CINF, 6}, /* Charge-info, DSS1-type */
163 {"CAU", ISDN_STAT_CAUSE, 7}, /* Cause code */
164 {"TEI OK", ISDN_STAT_RUN, 0}, /* Card connected to wallplug */
165 {"E_L1: ACT FAIL", ISDN_STAT_BHUP, 8}, /* Layer-1 activation failed */
166 {"E_L2: DATA LIN", ISDN_STAT_BHUP, 8}, /* Layer-2 data link lost */
167 {"E_L1: ACTIVATION FAILED",
168 ISDN_STAT_BHUP, 8}, /* Layer-1 activation failed */
169 {NULL, 0, -1}
170};
171/* *INDENT-ON* */
172
173
174/*
175 * Parse Status message-strings from virtual card.
176 * Depending on status, call statcallb for sending messages to upper
177 * levels. Also set/reset B-Channel active-flags.
178 *
179 * Parameter:
180 * status = status string to parse.
181 * channel = channel where message comes from.
182 * card = card where message comes from.
183 */
184static void
185isdnloop_parse_status(u_char *status, int channel, isdnloop_card *card)
186{
187 isdnloop_stat *s = isdnloop_stat_table;
188 int action = -1;
189 isdn_ctrl cmd;
190
191 while (s->statstr) {
192 if (!strncmp(status, s->statstr, strlen(s->statstr))) {
193 cmd.command = s->command;
194 action = s->action;
195 break;
196 }
197 s++;
198 }
199 if (action == -1)
200 return;
201 cmd.driver = card->myid;
202 cmd.arg = channel;
203 switch (action) {
204 case 1:
205 /* BCON_x */
206 card->flags |= (channel) ?
207 ISDNLOOP_FLAGS_B2ACTIVE : ISDNLOOP_FLAGS_B1ACTIVE;
208 break;
209 case 2:
210 /* BDIS_x */
211 card->flags &= ~((channel) ?
212 ISDNLOOP_FLAGS_B2ACTIVE : ISDNLOOP_FLAGS_B1ACTIVE);
213 isdnloop_free_queue(card, channel);
214 break;
215 case 3:
216 /* DCAL_I and DSCA_I */
217 isdnloop_parse_setup(status + 6, &cmd);
218 break;
219 case 4:
220 /* FCALL */
221 sprintf(cmd.parm.setup.phone, "LEASED%d", card->myid);
222 sprintf(cmd.parm.setup.eazmsn, "%d", channel + 1);
223 cmd.parm.setup.si1 = 7;
224 cmd.parm.setup.si2 = 0;
225 cmd.parm.setup.plan = 0;
226 cmd.parm.setup.screen = 0;
227 break;
228 case 5:
229 /* CIF */
230 strlcpy(cmd.parm.num, status + 3, sizeof(cmd.parm.num));
231 break;
232 case 6:
233 /* AOC */
234 snprintf(cmd.parm.num, sizeof(cmd.parm.num), "%d",
235 (int) simple_strtoul(status + 7, NULL, 16));
236 break;
237 case 7:
238 /* CAU */
239 status += 3;
240 if (strlen(status) == 4)
241 snprintf(cmd.parm.num, sizeof(cmd.parm.num), "%s%c%c",
242 status + 2, *status, *(status + 1));
243 else
244 strlcpy(cmd.parm.num, status + 1, sizeof(cmd.parm.num));
245 break;
246 case 8:
247 /* Misc Errors on L1 and L2 */
248 card->flags &= ~ISDNLOOP_FLAGS_B1ACTIVE;
249 isdnloop_free_queue(card, 0);
250 cmd.arg = 0;
251 cmd.driver = card->myid;
252 card->interface.statcallb(&cmd);
253 cmd.command = ISDN_STAT_DHUP;
254 cmd.arg = 0;
255 cmd.driver = card->myid;
256 card->interface.statcallb(&cmd);
257 cmd.command = ISDN_STAT_BHUP;
258 card->flags &= ~ISDNLOOP_FLAGS_B2ACTIVE;
259 isdnloop_free_queue(card, 1);
260 cmd.arg = 1;
261 cmd.driver = card->myid;
262 card->interface.statcallb(&cmd);
263 cmd.command = ISDN_STAT_DHUP;
264 cmd.arg = 1;
265 cmd.driver = card->myid;
266 break;
267 }
268 card->interface.statcallb(&cmd);
269}
270
271/*
272 * Store a cwcharacter into ringbuffer for reading from /dev/isdnctrl
273 *
274 * Parameter:
275 * card = pointer to card struct.
276 * c = char to store.
277 */
278static void
279isdnloop_putmsg(isdnloop_card *card, unsigned char c)
280{
281 ulong flags;
282
283 spin_lock_irqsave(&card->isdnloop_lock, flags);
284 *card->msg_buf_write++ = (c == 0xff) ? '\n' : c;
285 if (card->msg_buf_write == card->msg_buf_read) {
286 if (++card->msg_buf_read > card->msg_buf_end)
287 card->msg_buf_read = card->msg_buf;
288 }
289 if (card->msg_buf_write > card->msg_buf_end)
290 card->msg_buf_write = card->msg_buf;
291 spin_unlock_irqrestore(&card->isdnloop_lock, flags);
292}
293
294/*
295 * Poll a virtual cards message queue.
296 * If there are new status-replies from the card, copy them to
297 * ringbuffer for reading on /dev/isdnctrl and call
298 * isdnloop_parse_status() for processing them. Watch for special
299 * Firmware bootmessage and parse it, to get the D-Channel protocol.
300 * If there are B-Channels open, initiate a timer-callback to
301 * isdnloop_pollbchan().
302 * This routine is called periodically via timer interrupt.
303 *
304 * Parameter:
305 * data = pointer to card struct
306 */
307static void
308isdnloop_polldchan(struct timer_list *t)
309{
310 isdnloop_card *card = from_timer(card, t, st_timer);
311 struct sk_buff *skb;
312 int avail;
313 int left;
314 u_char c;
315 int ch;
316 unsigned long flags;
317 u_char *p;
318 isdn_ctrl cmd;
319
320 skb = skb_dequeue(&card->dqueue);
321 if (skb)
322 avail = skb->len;
323 else
324 avail = 0;
325 for (left = avail; left > 0; left--) {
326 c = *skb->data;
327 skb_pull(skb, 1);
328 isdnloop_putmsg(card, c);
329 card->imsg[card->iptr] = c;
330 if (card->iptr < 59)
331 card->iptr++;
332 if (!skb->len) {
333 avail++;
334 isdnloop_putmsg(card, '\n');
335 card->imsg[card->iptr] = 0;
336 card->iptr = 0;
337 if (card->imsg[0] == '0' && card->imsg[1] >= '0' &&
338 card->imsg[1] <= '2' && card->imsg[2] == ';') {
339 ch = (card->imsg[1] - '0') - 1;
340 p = &card->imsg[3];
341 isdnloop_parse_status(p, ch, card);
342 } else {
343 p = card->imsg;
344 if (!strncmp(p, "DRV1.", 5)) {
345 printk(KERN_INFO "isdnloop: (%s) %s\n", CID, p);
346 if (!strncmp(p + 7, "TC", 2)) {
347 card->ptype = ISDN_PTYPE_1TR6;
348 card->interface.features |= ISDN_FEATURE_P_1TR6;
349 printk(KERN_INFO
350 "isdnloop: (%s) 1TR6-Protocol loaded and running\n", CID);
351 }
352 if (!strncmp(p + 7, "EC", 2)) {
353 card->ptype = ISDN_PTYPE_EURO;
354 card->interface.features |= ISDN_FEATURE_P_EURO;
355 printk(KERN_INFO
356 "isdnloop: (%s) Euro-Protocol loaded and running\n", CID);
357 }
358 continue;
359
360 }
361 }
362 }
363 }
364 if (avail) {
365 cmd.command = ISDN_STAT_STAVAIL;
366 cmd.driver = card->myid;
367 cmd.arg = avail;
368 card->interface.statcallb(&cmd);
369 }
370 if (card->flags & (ISDNLOOP_FLAGS_B1ACTIVE | ISDNLOOP_FLAGS_B2ACTIVE))
371 if (!(card->flags & ISDNLOOP_FLAGS_RBTIMER)) {
372 /* schedule b-channel polling */
373 card->flags |= ISDNLOOP_FLAGS_RBTIMER;
374 spin_lock_irqsave(&card->isdnloop_lock, flags);
375 del_timer(&card->rb_timer);
376 card->rb_timer.expires = jiffies + ISDNLOOP_TIMER_BCREAD;
377 add_timer(&card->rb_timer);
378 spin_unlock_irqrestore(&card->isdnloop_lock, flags);
379 }
380 /* schedule again */
381 spin_lock_irqsave(&card->isdnloop_lock, flags);
382 card->st_timer.expires = jiffies + ISDNLOOP_TIMER_DCREAD;
383 add_timer(&card->st_timer);
384 spin_unlock_irqrestore(&card->isdnloop_lock, flags);
385}
386
387/*
388 * Append a packet to the transmit buffer-queue.
389 *
390 * Parameter:
391 * channel = Number of B-channel
392 * skb = packet to send.
393 * card = pointer to card-struct
394 * Return:
395 * Number of bytes transferred, -E??? on error
396 */
397static int
398isdnloop_sendbuf(int channel, struct sk_buff *skb, isdnloop_card *card)
399{
400 int len = skb->len;
401 unsigned long flags;
402 struct sk_buff *nskb;
403
404 if (len > 4000) {
405 printk(KERN_WARNING
406 "isdnloop: Send packet too large\n");
407 return -EINVAL;
408 }
409 if (len) {
410 if (!(card->flags & (channel ? ISDNLOOP_FLAGS_B2ACTIVE : ISDNLOOP_FLAGS_B1ACTIVE)))
411 return 0;
412 if (card->sndcount[channel] > ISDNLOOP_MAX_SQUEUE)
413 return 0;
414 spin_lock_irqsave(&card->isdnloop_lock, flags);
415 nskb = dev_alloc_skb(skb->len);
416 if (nskb) {
417 skb_copy_from_linear_data(skb,
418 skb_put(nskb, len), len);
419 skb_queue_tail(&card->bqueue[channel], nskb);
420 dev_kfree_skb(skb);
421 } else
422 len = 0;
423 card->sndcount[channel] += len;
424 spin_unlock_irqrestore(&card->isdnloop_lock, flags);
425 }
426 return len;
427}
428
429/*
430 * Read the messages from the card's ringbuffer
431 *
432 * Parameter:
433 * buf = pointer to buffer.
434 * len = number of bytes to read.
435 * user = flag, 1: called from userlevel 0: called from kernel.
436 * card = pointer to card struct.
437 * Return:
438 * number of bytes actually transferred.
439 */
440static int
441isdnloop_readstatus(u_char __user *buf, int len, isdnloop_card *card)
442{
443 int count;
444 u_char __user *p;
445
446 for (p = buf, count = 0; count < len; p++, count++) {
447 if (card->msg_buf_read == card->msg_buf_write)
448 return count;
449 if (put_user(*card->msg_buf_read++, p))
450 return -EFAULT;
451 if (card->msg_buf_read > card->msg_buf_end)
452 card->msg_buf_read = card->msg_buf;
453 }
454 return count;
455}
456
457/*
458 * Simulate a card's response by appending it to the cards
459 * message queue.
460 *
461 * Parameter:
462 * card = pointer to card struct.
463 * s = pointer to message-string.
464 * ch = channel: 0 = generic messages, 1 and 2 = D-channel messages.
465 * Return:
466 * 0 on success, 1 on memory squeeze.
467 */
468static int
469isdnloop_fake(isdnloop_card *card, char *s, int ch)
470{
471 struct sk_buff *skb;
472 int len = strlen(s) + ((ch >= 0) ? 3 : 0);
473 skb = dev_alloc_skb(len);
474 if (!skb) {
475 printk(KERN_WARNING "isdnloop: Out of memory in isdnloop_fake\n");
476 return 1;
477 }
478 if (ch >= 0)
479 sprintf(skb_put(skb, 3), "%02d;", ch);
480 skb_put_data(skb, s, strlen(s));
481 skb_queue_tail(&card->dqueue, skb);
482 return 0;
483}
484/* *INDENT-OFF* */
485static isdnloop_stat isdnloop_cmd_table[] = {
486 {"BCON_R", 0, 1}, /* B-Channel connect */
487 {"BCON_I", 0, 17}, /* B-Channel connect ind */
488 {"BDIS_R", 0, 2}, /* B-Channel disconnect */
489 {"DDIS_R", 0, 3}, /* D-Channel disconnect */
490 {"DCON_R", 0, 16}, /* D-Channel connect */
491 {"DSCA_R", 0, 4}, /* Dial 1TR6-SPV */
492 {"DCAL_R", 0, 5}, /* Dial */
493 {"EAZC", 0, 6}, /* Clear EAZ listener */
494 {"EAZ", 0, 7}, /* Set EAZ listener */
495 {"SEEAZ", 0, 8}, /* Get EAZ listener */
496 {"MSN", 0, 9}, /* Set/Clear MSN listener */
497 {"MSALL", 0, 10}, /* Set multi MSN listeners */
498 {"SETSIL", 0, 11}, /* Set SI list */
499 {"SEESIL", 0, 12}, /* Get SI list */
500 {"SILC", 0, 13}, /* Clear SI list */
501 {"LOCK", 0, -1}, /* LOCK channel */
502 {"UNLOCK", 0, -1}, /* UNLOCK channel */
503 {"FV2ON", 1, 14}, /* Leased mode on */
504 {"FV2OFF", 1, 15}, /* Leased mode off */
505 {NULL, 0, -1}
506};
507/* *INDENT-ON* */
508
509
510/*
511 * Simulate an error-response from a card.
512 *
513 * Parameter:
514 * card = pointer to card struct.
515 */
516static void
517isdnloop_fake_err(isdnloop_card *card)
518{
519 char buf[64];
520
521 snprintf(buf, sizeof(buf), "E%s", card->omsg);
522 isdnloop_fake(card, buf, -1);
523 isdnloop_fake(card, "NAK", -1);
524}
525
526static u_char ctable_eu[] = {0x00, 0x11, 0x01, 0x12};
527static u_char ctable_1t[] = {0x00, 0x3b, 0x01, 0x3a};
528
529/*
530 * Assemble a simplified cause message depending on the
531 * D-channel protocol used.
532 *
533 * Parameter:
534 * card = pointer to card struct.
535 * loc = location: 0 = local, 1 = remote.
536 * cau = cause: 1 = busy, 2 = nonexistent callerid, 3 = no user responding.
537 * Return:
538 * Pointer to buffer containing the assembled message.
539 */
540static char *
541isdnloop_unicause(isdnloop_card *card, int loc, int cau)
542{
543 static char buf[6];
544
545 switch (card->ptype) {
546 case ISDN_PTYPE_EURO:
547 sprintf(buf, "E%02X%02X", (loc) ? 4 : 2, ctable_eu[cau]);
548 break;
549 case ISDN_PTYPE_1TR6:
550 sprintf(buf, "%02X44", ctable_1t[cau]);
551 break;
552 default:
553 return "0000";
554 }
555 return buf;
556}
557
558/*
559 * Release a virtual connection. Called from timer interrupt, when
560 * called party did not respond.
561 *
562 * Parameter:
563 * card = pointer to card struct.
564 * ch = channel (0-based)
565 */
566static void
567isdnloop_atimeout(isdnloop_card *card, int ch)
568{
569 unsigned long flags;
570 char buf[60];
571
572 spin_lock_irqsave(&card->isdnloop_lock, flags);
573 if (card->rcard[ch]) {
574 isdnloop_fake(card->rcard[ch], "DDIS_I", card->rch[ch] + 1);
575 card->rcard[ch]->rcard[card->rch[ch]] = NULL;
576 card->rcard[ch] = NULL;
577 }
578 isdnloop_fake(card, "DDIS_I", ch + 1);
579 /* No user responding */
580 sprintf(buf, "CAU%s", isdnloop_unicause(card, 1, 3));
581 isdnloop_fake(card, buf, ch + 1);
582 spin_unlock_irqrestore(&card->isdnloop_lock, flags);
583}
584
585/*
586 * Wrapper for isdnloop_atimeout().
587 */
588static void
589isdnloop_atimeout0(struct timer_list *t)
590{
591 isdnloop_card *card = from_timer(card, t, c_timer[0]);
592
593 isdnloop_atimeout(card, 0);
594}
595
596/*
597 * Wrapper for isdnloop_atimeout().
598 */
599static void
600isdnloop_atimeout1(struct timer_list *t)
601{
602 isdnloop_card *card = from_timer(card, t, c_timer[1]);
603
604 isdnloop_atimeout(card, 1);
605}
606
607/*
608 * Install a watchdog for a user, not responding.
609 *
610 * Parameter:
611 * card = pointer to card struct.
612 * ch = channel to watch for.
613 */
614static void
615isdnloop_start_ctimer(isdnloop_card *card, int ch)
616{
617 unsigned long flags;
618
619 spin_lock_irqsave(&card->isdnloop_lock, flags);
620 timer_setup(&card->c_timer[ch], ch ? isdnloop_atimeout1
621 : isdnloop_atimeout0, 0);
622 card->c_timer[ch].expires = jiffies + ISDNLOOP_TIMER_ALERTWAIT;
623 add_timer(&card->c_timer[ch]);
624 spin_unlock_irqrestore(&card->isdnloop_lock, flags);
625}
626
627/*
628 * Kill a pending channel watchdog.
629 *
630 * Parameter:
631 * card = pointer to card struct.
632 * ch = channel (0-based).
633 */
634static void
635isdnloop_kill_ctimer(isdnloop_card *card, int ch)
636{
637 unsigned long flags;
638
639 spin_lock_irqsave(&card->isdnloop_lock, flags);
640 del_timer(&card->c_timer[ch]);
641 spin_unlock_irqrestore(&card->isdnloop_lock, flags);
642}
643
644static u_char si2bit[] = {0, 1, 0, 0, 0, 2, 0, 4, 0, 0};
645static u_char bit2si[] = {1, 5, 7};
646
647/*
648 * Try finding a listener for an outgoing call.
649 *
650 * Parameter:
651 * card = pointer to calling card.
652 * p = pointer to ICN-type setup-string.
653 * lch = channel of calling card.
654 * cmd = pointer to struct to be filled when parsing setup.
655 * Return:
656 * 0 = found match, alerting should happen.
657 * 1 = found matching number but it is busy.
658 * 2 = no matching listener.
659 * 3 = found matching number but SI does not match.
660 */
661static int
662isdnloop_try_call(isdnloop_card *card, char *p, int lch, isdn_ctrl *cmd)
663{
664 isdnloop_card *cc = cards;
665 unsigned long flags;
666 int ch;
667 int num_match;
668 int i;
669 char *e;
670 char nbuf[32];
671
672 isdnloop_parse_setup(p, cmd);
673 while (cc) {
674 for (ch = 0; ch < 2; ch++) {
675 /* Exclude ourself */
676 if ((cc == card) && (ch == lch))
677 continue;
678 num_match = 0;
679 switch (cc->ptype) {
680 case ISDN_PTYPE_EURO:
681 for (i = 0; i < 3; i++)
682 if (!(strcmp(cc->s0num[i], cmd->parm.setup.phone)))
683 num_match = 1;
684 break;
685 case ISDN_PTYPE_1TR6:
686 e = cc->eazlist[ch];
687 while (*e) {
688 sprintf(nbuf, "%s%c", cc->s0num[0], *e);
689 if (!(strcmp(nbuf, cmd->parm.setup.phone)))
690 num_match = 1;
691 e++;
692 }
693 }
694 if (num_match) {
695 spin_lock_irqsave(&card->isdnloop_lock, flags);
696 /* channel idle? */
697 if (!(cc->rcard[ch])) {
698 /* Check SI */
699 if (!(si2bit[cmd->parm.setup.si1] & cc->sil[ch])) {
700 spin_unlock_irqrestore(&card->isdnloop_lock, flags);
701 return 3;
702 }
703 /* ch is idle, si and number matches */
704 cc->rcard[ch] = card;
705 cc->rch[ch] = lch;
706 card->rcard[lch] = cc;
707 card->rch[lch] = ch;
708 spin_unlock_irqrestore(&card->isdnloop_lock, flags);
709 return 0;
710 } else {
711 spin_unlock_irqrestore(&card->isdnloop_lock, flags);
712 /* num matches, but busy */
713 if (ch == 1)
714 return 1;
715 }
716 }
717 }
718 cc = cc->next;
719 }
720 return 2;
721}
722
723/*
724 * Depending on D-channel protocol and caller/called, modify
725 * phone number.
726 *
727 * Parameter:
728 * card = pointer to card struct.
729 * phone = pointer phone number.
730 * caller = flag: 1 = caller, 0 = called.
731 * Return:
732 * pointer to new phone number.
733 */
734static char *
735isdnloop_vstphone(isdnloop_card *card, char *phone, int caller)
736{
737 int i;
738 static char nphone[30];
739
740 if (!card) {
741 printk("BUG!!!\n");
742 return "";
743 }
744 switch (card->ptype) {
745 case ISDN_PTYPE_EURO:
746 if (caller) {
747 for (i = 0; i < 2; i++)
748 if (!(strcmp(card->s0num[i], phone)))
749 return phone;
750 return card->s0num[0];
751 }
752 return phone;
753 break;
754 case ISDN_PTYPE_1TR6:
755 if (caller) {
756 sprintf(nphone, "%s%c", card->s0num[0], phone[0]);
757 return nphone;
758 } else
759 return &phone[strlen(phone) - 1];
760 break;
761 }
762 return "";
763}
764
765/*
766 * Parse an ICN-type command string sent to the 'card'.
767 * Perform misc. actions depending on the command.
768 *
769 * Parameter:
770 * card = pointer to card struct.
771 */
772static void
773isdnloop_parse_cmd(isdnloop_card *card)
774{
775 char *p = card->omsg;
776 isdn_ctrl cmd;
777 char buf[60];
778 isdnloop_stat *s = isdnloop_cmd_table;
779 int action = -1;
780 int i;
781 int ch;
782
783 if ((card->omsg[0] != '0') && (card->omsg[2] != ';')) {
784 isdnloop_fake_err(card);
785 return;
786 }
787 ch = card->omsg[1] - '0';
788 if ((ch < 0) || (ch > 2)) {
789 isdnloop_fake_err(card);
790 return;
791 }
792 p += 3;
793 while (s->statstr) {
794 if (!strncmp(p, s->statstr, strlen(s->statstr))) {
795 action = s->action;
796 if (s->command && (ch != 0)) {
797 isdnloop_fake_err(card);
798 return;
799 }
800 break;
801 }
802 s++;
803 }
804 if (action == -1)
805 return;
806 switch (action) {
807 case 1:
808 /* 0x;BCON_R */
809 if (card->rcard[ch - 1]) {
810 isdnloop_fake(card->rcard[ch - 1], "BCON_I",
811 card->rch[ch - 1] + 1);
812 isdnloop_fake(card, "BCON_C", ch);
813 }
814 break;
815 case 17:
816 /* 0x;BCON_I */
817 if (card->rcard[ch - 1]) {
818 isdnloop_fake(card->rcard[ch - 1], "BCON_C",
819 card->rch[ch - 1] + 1);
820 }
821 break;
822 case 2:
823 /* 0x;BDIS_R */
824 isdnloop_fake(card, "BDIS_C", ch);
825 if (card->rcard[ch - 1]) {
826 isdnloop_fake(card->rcard[ch - 1], "BDIS_I",
827 card->rch[ch - 1] + 1);
828 }
829 break;
830 case 16:
831 /* 0x;DCON_R */
832 isdnloop_kill_ctimer(card, ch - 1);
833 if (card->rcard[ch - 1]) {
834 isdnloop_kill_ctimer(card->rcard[ch - 1], card->rch[ch - 1]);
835 isdnloop_fake(card->rcard[ch - 1], "DCON_C",
836 card->rch[ch - 1] + 1);
837 isdnloop_fake(card, "DCON_C", ch);
838 }
839 break;
840 case 3:
841 /* 0x;DDIS_R */
842 isdnloop_kill_ctimer(card, ch - 1);
843 if (card->rcard[ch - 1]) {
844 isdnloop_kill_ctimer(card->rcard[ch - 1], card->rch[ch - 1]);
845 isdnloop_fake(card->rcard[ch - 1], "DDIS_I",
846 card->rch[ch - 1] + 1);
847 card->rcard[ch - 1] = NULL;
848 }
849 isdnloop_fake(card, "DDIS_C", ch);
850 break;
851 case 4:
852 /* 0x;DSCA_Rdd,yy,zz,oo */
853 if (card->ptype != ISDN_PTYPE_1TR6) {
854 isdnloop_fake_err(card);
855 return;
856 }
857 /* Fall through */
858 case 5:
859 /* 0x;DCAL_Rdd,yy,zz,oo */
860 p += 6;
861 switch (isdnloop_try_call(card, p, ch - 1, &cmd)) {
862 case 0:
863 /* Alerting */
864 sprintf(buf, "D%s_I%s,%02d,%02d,%s",
865 (action == 4) ? "SCA" : "CAL",
866 isdnloop_vstphone(card, cmd.parm.setup.eazmsn, 1),
867 cmd.parm.setup.si1,
868 cmd.parm.setup.si2,
869 isdnloop_vstphone(card->rcard[ch - 1],
870 cmd.parm.setup.phone, 0));
871 isdnloop_fake(card->rcard[ch - 1], buf, card->rch[ch - 1] + 1);
872 /* Fall through */
873 case 3:
874 /* si1 does not match, don't alert but start timer */
875 isdnloop_start_ctimer(card, ch - 1);
876 break;
877 case 1:
878 /* Remote busy */
879 isdnloop_fake(card, "DDIS_I", ch);
880 sprintf(buf, "CAU%s", isdnloop_unicause(card, 1, 1));
881 isdnloop_fake(card, buf, ch);
882 break;
883 case 2:
884 /* No such user */
885 isdnloop_fake(card, "DDIS_I", ch);
886 sprintf(buf, "CAU%s", isdnloop_unicause(card, 1, 2));
887 isdnloop_fake(card, buf, ch);
888 break;
889 }
890 break;
891 case 6:
892 /* 0x;EAZC */
893 card->eazlist[ch - 1][0] = '\0';
894 break;
895 case 7:
896 /* 0x;EAZ */
897 p += 3;
898 if (strlen(p) >= sizeof(card->eazlist[0]))
899 break;
900 strcpy(card->eazlist[ch - 1], p);
901 break;
902 case 8:
903 /* 0x;SEEAZ */
904 sprintf(buf, "EAZ-LIST: %s", card->eazlist[ch - 1]);
905 isdnloop_fake(card, buf, ch + 1);
906 break;
907 case 9:
908 /* 0x;MSN */
909 break;
910 case 10:
911 /* 0x;MSNALL */
912 break;
913 case 11:
914 /* 0x;SETSIL */
915 p += 6;
916 i = 0;
917 while (strchr("0157", *p)) {
918 if (i)
919 card->sil[ch - 1] |= si2bit[*p - '0'];
920 i = (*p++ == '0');
921 }
922 if (*p)
923 isdnloop_fake_err(card);
924 break;
925 case 12:
926 /* 0x;SEESIL */
927 sprintf(buf, "SIN-LIST: ");
928 p = buf + 10;
929 for (i = 0; i < 3; i++)
930 if (card->sil[ch - 1] & (1 << i))
931 p += sprintf(p, "%02d", bit2si[i]);
932 isdnloop_fake(card, buf, ch + 1);
933 break;
934 case 13:
935 /* 0x;SILC */
936 card->sil[ch - 1] = 0;
937 break;
938 case 14:
939 /* 00;FV2ON */
940 break;
941 case 15:
942 /* 00;FV2OFF */
943 break;
944 }
945}
946
947/*
948 * Put command-strings into the of the 'card'. In reality, execute them
949 * right in place by calling isdnloop_parse_cmd(). Also copy every
950 * command to the read message ringbuffer, preceding it with a '>'.
951 * These mesagges can be read at /dev/isdnctrl.
952 *
953 * Parameter:
954 * buf = pointer to command buffer.
955 * len = length of buffer data.
956 * user = flag: 1 = called form userlevel, 0 called from kernel.
957 * card = pointer to card struct.
958 * Return:
959 * number of bytes transferred (currently always equals len).
960 */
961static int
962isdnloop_writecmd(const u_char *buf, int len, int user, isdnloop_card *card)
963{
964 int xcount = 0;
965 int ocount = 1;
966 isdn_ctrl cmd;
967
968 while (len) {
969 int count = len;
970 u_char *p;
971 u_char msg[0x100];
972
973 if (count > 255)
974 count = 255;
975 if (user) {
976 if (copy_from_user(msg, buf, count))
977 return -EFAULT;
978 } else
979 memcpy(msg, buf, count);
980 isdnloop_putmsg(card, '>');
981 for (p = msg; count > 0; count--, p++) {
982 len--;
983 xcount++;
984 isdnloop_putmsg(card, *p);
985 card->omsg[card->optr] = *p;
986 if (*p == '\n') {
987 card->omsg[card->optr] = '\0';
988 card->optr = 0;
989 isdnloop_parse_cmd(card);
990 if (len) {
991 isdnloop_putmsg(card, '>');
992 ocount++;
993 }
994 } else {
995 if (card->optr < 59)
996 card->optr++;
997 }
998 ocount++;
999 }
1000 }
1001 cmd.command = ISDN_STAT_STAVAIL;
1002 cmd.driver = card->myid;
1003 cmd.arg = ocount;
1004 card->interface.statcallb(&cmd);
1005 return xcount;
1006}
1007
1008/*
1009 * Delete card's pending timers, send STOP to linklevel
1010 */
1011static void
1012isdnloop_stopcard(isdnloop_card *card)
1013{
1014 unsigned long flags;
1015 isdn_ctrl cmd;
1016
1017 spin_lock_irqsave(&card->isdnloop_lock, flags);
1018 if (card->flags & ISDNLOOP_FLAGS_RUNNING) {
1019 card->flags &= ~ISDNLOOP_FLAGS_RUNNING;
1020 del_timer(&card->st_timer);
1021 del_timer(&card->rb_timer);
1022 del_timer(&card->c_timer[0]);
1023 del_timer(&card->c_timer[1]);
1024 cmd.command = ISDN_STAT_STOP;
1025 cmd.driver = card->myid;
1026 card->interface.statcallb(&cmd);
1027 }
1028 spin_unlock_irqrestore(&card->isdnloop_lock, flags);
1029}
1030
1031/*
1032 * Stop all cards before unload.
1033 */
1034static void
1035isdnloop_stopallcards(void)
1036{
1037 isdnloop_card *p = cards;
1038
1039 while (p) {
1040 isdnloop_stopcard(p);
1041 p = p->next;
1042 }
1043}
1044
1045/*
1046 * Start a 'card'. Simulate card's boot message and set the phone
1047 * number(s) of the virtual 'S0-Interface'. Install D-channel
1048 * poll timer.
1049 *
1050 * Parameter:
1051 * card = pointer to card struct.
1052 * sdefp = pointer to struct holding ioctl parameters.
1053 * Return:
1054 * 0 on success, -E??? otherwise.
1055 */
1056static int
1057isdnloop_start(isdnloop_card *card, isdnloop_sdef *sdefp)
1058{
1059 unsigned long flags;
1060 isdnloop_sdef sdef;
1061 int i;
1062
1063 if (card->flags & ISDNLOOP_FLAGS_RUNNING)
1064 return -EBUSY;
1065 if (copy_from_user((char *) &sdef, (char *) sdefp, sizeof(sdef)))
1066 return -EFAULT;
1067
1068 for (i = 0; i < 3; i++) {
1069 if (!memchr(sdef.num[i], 0, sizeof(sdef.num[i])))
1070 return -EINVAL;
1071 }
1072
1073 spin_lock_irqsave(&card->isdnloop_lock, flags);
1074 switch (sdef.ptype) {
1075 case ISDN_PTYPE_EURO:
1076 if (isdnloop_fake(card, "DRV1.23EC-Q.931-CAPI-CNS-BASIS-20.02.96",
1077 -1)) {
1078 spin_unlock_irqrestore(&card->isdnloop_lock, flags);
1079 return -ENOMEM;
1080 }
1081 card->sil[0] = card->sil[1] = 4;
1082 if (isdnloop_fake(card, "TEI OK", 0)) {
1083 spin_unlock_irqrestore(&card->isdnloop_lock, flags);
1084 return -ENOMEM;
1085 }
1086 for (i = 0; i < 3; i++) {
1087 strlcpy(card->s0num[i], sdef.num[i],
1088 sizeof(card->s0num[0]));
1089 }
1090 break;
1091 case ISDN_PTYPE_1TR6:
1092 if (isdnloop_fake(card, "DRV1.04TC-1TR6-CAPI-CNS-BASIS-29.11.95",
1093 -1)) {
1094 spin_unlock_irqrestore(&card->isdnloop_lock, flags);
1095 return -ENOMEM;
1096 }
1097 card->sil[0] = card->sil[1] = 4;
1098 if (isdnloop_fake(card, "TEI OK", 0)) {
1099 spin_unlock_irqrestore(&card->isdnloop_lock, flags);
1100 return -ENOMEM;
1101 }
1102 strlcpy(card->s0num[0], sdef.num[0], sizeof(card->s0num[0]));
1103 card->s0num[1][0] = '\0';
1104 card->s0num[2][0] = '\0';
1105 break;
1106 default:
1107 spin_unlock_irqrestore(&card->isdnloop_lock, flags);
1108 printk(KERN_WARNING "isdnloop: Illegal D-channel protocol %d\n",
1109 sdef.ptype);
1110 return -EINVAL;
1111 }
1112 timer_setup(&card->rb_timer, isdnloop_pollbchan, 0);
1113 timer_setup(&card->st_timer, isdnloop_polldchan, 0);
1114 card->st_timer.expires = jiffies + ISDNLOOP_TIMER_DCREAD;
1115 add_timer(&card->st_timer);
1116 card->flags |= ISDNLOOP_FLAGS_RUNNING;
1117 spin_unlock_irqrestore(&card->isdnloop_lock, flags);
1118 return 0;
1119}
1120
1121/*
1122 * Main handler for commands sent by linklevel.
1123 */
1124static int
1125isdnloop_command(isdn_ctrl *c, isdnloop_card *card)
1126{
1127 ulong a;
1128 int i;
1129 char cbuf[80];
1130 isdn_ctrl cmd;
1131 isdnloop_cdef cdef;
1132
1133 switch (c->command) {
1134 case ISDN_CMD_IOCTL:
1135 memcpy(&a, c->parm.num, sizeof(ulong));
1136 switch (c->arg) {
1137 case ISDNLOOP_IOCTL_DEBUGVAR:
1138 return (ulong) card;
1139 case ISDNLOOP_IOCTL_STARTUP:
1140 return isdnloop_start(card, (isdnloop_sdef *) a);
1141 break;
1142 case ISDNLOOP_IOCTL_ADDCARD:
1143 if (copy_from_user((char *)&cdef,
1144 (char *)a,
1145 sizeof(cdef)))
1146 return -EFAULT;
1147 return isdnloop_addcard(cdef.id1);
1148 break;
1149 case ISDNLOOP_IOCTL_LEASEDCFG:
1150 if (a) {
1151 if (!card->leased) {
1152 card->leased = 1;
1153 while (card->ptype == ISDN_PTYPE_UNKNOWN)
1154 schedule_timeout_interruptible(10);
1155 schedule_timeout_interruptible(10);
1156 sprintf(cbuf, "00;FV2ON\n01;EAZ1\n02;EAZ2\n");
1157 i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card);
1158 printk(KERN_INFO
1159 "isdnloop: (%s) Leased-line mode enabled\n",
1160 CID);
1161 cmd.command = ISDN_STAT_RUN;
1162 cmd.driver = card->myid;
1163 cmd.arg = 0;
1164 card->interface.statcallb(&cmd);
1165 }
1166 } else {
1167 if (card->leased) {
1168 card->leased = 0;
1169 sprintf(cbuf, "00;FV2OFF\n");
1170 i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card);
1171 printk(KERN_INFO
1172 "isdnloop: (%s) Leased-line mode disabled\n",
1173 CID);
1174 cmd.command = ISDN_STAT_RUN;
1175 cmd.driver = card->myid;
1176 cmd.arg = 0;
1177 card->interface.statcallb(&cmd);
1178 }
1179 }
1180 return 0;
1181 default:
1182 return -EINVAL;
1183 }
1184 break;
1185 case ISDN_CMD_DIAL:
1186 if (!(card->flags & ISDNLOOP_FLAGS_RUNNING))
1187 return -ENODEV;
1188 if (card->leased)
1189 break;
1190 if ((c->arg & 255) < ISDNLOOP_BCH) {
1191 char *p;
1192 char dcode[4];
1193
1194 a = c->arg;
1195 p = c->parm.setup.phone;
1196 if (*p == 's' || *p == 'S') {
1197 /* Dial for SPV */
1198 p++;
1199 strcpy(dcode, "SCA");
1200 } else
1201 /* Normal Dial */
1202 strcpy(dcode, "CAL");
1203 snprintf(cbuf, sizeof(cbuf),
1204 "%02d;D%s_R%s,%02d,%02d,%s\n", (int) (a + 1),
1205 dcode, p, c->parm.setup.si1,
1206 c->parm.setup.si2, c->parm.setup.eazmsn);
1207 i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card);
1208 }
1209 break;
1210 case ISDN_CMD_ACCEPTD:
1211 if (!(card->flags & ISDNLOOP_FLAGS_RUNNING))
1212 return -ENODEV;
1213 if (c->arg < ISDNLOOP_BCH) {
1214 a = c->arg + 1;
1215 cbuf[0] = 0;
1216 switch (card->l2_proto[a - 1]) {
1217 case ISDN_PROTO_L2_X75I:
1218 sprintf(cbuf, "%02d;BX75\n", (int) a);
1219 break;
1220#ifdef CONFIG_ISDN_X25
1221 case ISDN_PROTO_L2_X25DTE:
1222 sprintf(cbuf, "%02d;BX2T\n", (int) a);
1223 break;
1224 case ISDN_PROTO_L2_X25DCE:
1225 sprintf(cbuf, "%02d;BX2C\n", (int) a);
1226 break;
1227#endif
1228 case ISDN_PROTO_L2_HDLC:
1229 sprintf(cbuf, "%02d;BTRA\n", (int) a);
1230 break;
1231 }
1232 if (strlen(cbuf))
1233 i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card);
1234 sprintf(cbuf, "%02d;DCON_R\n", (int) a);
1235 i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card);
1236 }
1237 break;
1238 case ISDN_CMD_ACCEPTB:
1239 if (!(card->flags & ISDNLOOP_FLAGS_RUNNING))
1240 return -ENODEV;
1241 if (c->arg < ISDNLOOP_BCH) {
1242 a = c->arg + 1;
1243 switch (card->l2_proto[a - 1]) {
1244 case ISDN_PROTO_L2_X75I:
1245 sprintf(cbuf, "%02d;BCON_R,BX75\n", (int) a);
1246 break;
1247#ifdef CONFIG_ISDN_X25
1248 case ISDN_PROTO_L2_X25DTE:
1249 sprintf(cbuf, "%02d;BCON_R,BX2T\n", (int) a);
1250 break;
1251 case ISDN_PROTO_L2_X25DCE:
1252 sprintf(cbuf, "%02d;BCON_R,BX2C\n", (int) a);
1253 break;
1254#endif
1255 case ISDN_PROTO_L2_HDLC:
1256 sprintf(cbuf, "%02d;BCON_R,BTRA\n", (int) a);
1257 break;
1258 default:
1259 sprintf(cbuf, "%02d;BCON_R\n", (int) a);
1260 }
1261 printk(KERN_DEBUG "isdnloop writecmd '%s'\n", cbuf);
1262 i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card);
1263 break;
1264 case ISDN_CMD_HANGUP:
1265 if (!(card->flags & ISDNLOOP_FLAGS_RUNNING))
1266 return -ENODEV;
1267 if (c->arg < ISDNLOOP_BCH) {
1268 a = c->arg + 1;
1269 sprintf(cbuf, "%02d;BDIS_R\n%02d;DDIS_R\n", (int) a, (int) a);
1270 i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card);
1271 }
1272 break;
1273 case ISDN_CMD_SETEAZ:
1274 if (!(card->flags & ISDNLOOP_FLAGS_RUNNING))
1275 return -ENODEV;
1276 if (card->leased)
1277 break;
1278 if (c->arg < ISDNLOOP_BCH) {
1279 a = c->arg + 1;
1280 if (card->ptype == ISDN_PTYPE_EURO) {
1281 sprintf(cbuf, "%02d;MS%s%s\n", (int) a,
1282 c->parm.num[0] ? "N" : "ALL", c->parm.num);
1283 } else
1284 sprintf(cbuf, "%02d;EAZ%s\n", (int) a,
1285 c->parm.num[0] ? c->parm.num : (u_char *) "0123456789");
1286 i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card);
1287 }
1288 break;
1289 case ISDN_CMD_CLREAZ:
1290 if (!(card->flags & ISDNLOOP_FLAGS_RUNNING))
1291 return -ENODEV;
1292 if (card->leased)
1293 break;
1294 if (c->arg < ISDNLOOP_BCH) {
1295 a = c->arg + 1;
1296 if (card->ptype == ISDN_PTYPE_EURO)
1297 sprintf(cbuf, "%02d;MSNC\n", (int) a);
1298 else
1299 sprintf(cbuf, "%02d;EAZC\n", (int) a);
1300 i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card);
1301 }
1302 break;
1303 case ISDN_CMD_SETL2:
1304 if (!(card->flags & ISDNLOOP_FLAGS_RUNNING))
1305 return -ENODEV;
1306 if ((c->arg & 255) < ISDNLOOP_BCH) {
1307 a = c->arg;
1308 switch (a >> 8) {
1309 case ISDN_PROTO_L2_X75I:
1310 sprintf(cbuf, "%02d;BX75\n", (int) (a & 255) + 1);
1311 break;
1312#ifdef CONFIG_ISDN_X25
1313 case ISDN_PROTO_L2_X25DTE:
1314 sprintf(cbuf, "%02d;BX2T\n", (int) (a & 255) + 1);
1315 break;
1316 case ISDN_PROTO_L2_X25DCE:
1317 sprintf(cbuf, "%02d;BX2C\n", (int) (a & 255) + 1);
1318 break;
1319#endif
1320 case ISDN_PROTO_L2_HDLC:
1321 sprintf(cbuf, "%02d;BTRA\n", (int) (a & 255) + 1);
1322 break;
1323 case ISDN_PROTO_L2_TRANS:
1324 sprintf(cbuf, "%02d;BTRA\n", (int) (a & 255) + 1);
1325 break;
1326 default:
1327 return -EINVAL;
1328 }
1329 i = isdnloop_writecmd(cbuf, strlen(cbuf), 0, card);
1330 card->l2_proto[a & 255] = (a >> 8);
1331 }
1332 break;
1333 case ISDN_CMD_SETL3:
1334 if (!(card->flags & ISDNLOOP_FLAGS_RUNNING))
1335 return -ENODEV;
1336 return 0;
1337 default:
1338 return -EINVAL;
1339 }
1340 }
1341 return 0;
1342}
1343
1344/*
1345 * Find card with given driverId
1346 */
1347static inline isdnloop_card *
1348isdnloop_findcard(int driverid)
1349{
1350 isdnloop_card *p = cards;
1351
1352 while (p) {
1353 if (p->myid == driverid)
1354 return p;
1355 p = p->next;
1356 }
1357 return (isdnloop_card *) 0;
1358}
1359
1360/*
1361 * Wrapper functions for interface to linklevel
1362 */
1363static int
1364if_command(isdn_ctrl *c)
1365{
1366 isdnloop_card *card = isdnloop_findcard(c->driver);
1367
1368 if (card)
1369 return isdnloop_command(c, card);
1370 printk(KERN_ERR
1371 "isdnloop: if_command called with invalid driverId!\n");
1372 return -ENODEV;
1373}
1374
1375static int
1376if_writecmd(const u_char __user *buf, int len, int id, int channel)
1377{
1378 isdnloop_card *card = isdnloop_findcard(id);
1379
1380 if (card) {
1381 if (!(card->flags & ISDNLOOP_FLAGS_RUNNING))
1382 return -ENODEV;
1383 return isdnloop_writecmd(buf, len, 1, card);
1384 }
1385 printk(KERN_ERR
1386 "isdnloop: if_writecmd called with invalid driverId!\n");
1387 return -ENODEV;
1388}
1389
1390static int
1391if_readstatus(u_char __user *buf, int len, int id, int channel)
1392{
1393 isdnloop_card *card = isdnloop_findcard(id);
1394
1395 if (card) {
1396 if (!(card->flags & ISDNLOOP_FLAGS_RUNNING))
1397 return -ENODEV;
1398 return isdnloop_readstatus(buf, len, card);
1399 }
1400 printk(KERN_ERR
1401 "isdnloop: if_readstatus called with invalid driverId!\n");
1402 return -ENODEV;
1403}
1404
1405static int
1406if_sendbuf(int id, int channel, int ack, struct sk_buff *skb)
1407{
1408 isdnloop_card *card = isdnloop_findcard(id);
1409
1410 if (card) {
1411 if (!(card->flags & ISDNLOOP_FLAGS_RUNNING))
1412 return -ENODEV;
1413 /* ack request stored in skb scratch area */
1414 *(skb->head) = ack;
1415 return isdnloop_sendbuf(channel, skb, card);
1416 }
1417 printk(KERN_ERR
1418 "isdnloop: if_sendbuf called with invalid driverId!\n");
1419 return -ENODEV;
1420}
1421
1422/*
1423 * Allocate a new card-struct, initialize it
1424 * link it into cards-list and register it at linklevel.
1425 */
1426static isdnloop_card *
1427isdnloop_initcard(char *id)
1428{
1429 isdnloop_card *card;
1430 int i;
1431 card = kzalloc(sizeof(isdnloop_card), GFP_KERNEL);
1432 if (!card) {
1433 printk(KERN_WARNING
1434 "isdnloop: (%s) Could not allocate card-struct.\n", id);
1435 return (isdnloop_card *) 0;
1436 }
1437 card->interface.owner = THIS_MODULE;
1438 card->interface.channels = ISDNLOOP_BCH;
1439 card->interface.hl_hdrlen = 1; /* scratch area for storing ack flag*/
1440 card->interface.maxbufsize = 4000;
1441 card->interface.command = if_command;
1442 card->interface.writebuf_skb = if_sendbuf;
1443 card->interface.writecmd = if_writecmd;
1444 card->interface.readstat = if_readstatus;
1445 card->interface.features = ISDN_FEATURE_L2_X75I |
1446#ifdef CONFIG_ISDN_X25
1447 ISDN_FEATURE_L2_X25DTE |
1448 ISDN_FEATURE_L2_X25DCE |
1449#endif
1450 ISDN_FEATURE_L2_HDLC |
1451 ISDN_FEATURE_L3_TRANS |
1452 ISDN_FEATURE_P_UNKNOWN;
1453 card->ptype = ISDN_PTYPE_UNKNOWN;
1454 strlcpy(card->interface.id, id, sizeof(card->interface.id));
1455 card->msg_buf_write = card->msg_buf;
1456 card->msg_buf_read = card->msg_buf;
1457 card->msg_buf_end = &card->msg_buf[sizeof(card->msg_buf) - 1];
1458 for (i = 0; i < ISDNLOOP_BCH; i++) {
1459 card->l2_proto[i] = ISDN_PROTO_L2_X75I;
1460 skb_queue_head_init(&card->bqueue[i]);
1461 }
1462 skb_queue_head_init(&card->dqueue);
1463 spin_lock_init(&card->isdnloop_lock);
1464 card->next = cards;
1465 cards = card;
1466 if (!register_isdn(&card->interface)) {
1467 cards = cards->next;
1468 printk(KERN_WARNING
1469 "isdnloop: Unable to register %s\n", id);
1470 kfree(card);
1471 return (isdnloop_card *) 0;
1472 }
1473 card->myid = card->interface.channels;
1474 return card;
1475}
1476
1477static int
1478isdnloop_addcard(char *id1)
1479{
1480 isdnloop_card *card;
1481 card = isdnloop_initcard(id1);
1482 if (!card) {
1483 return -EIO;
1484 }
1485 printk(KERN_INFO
1486 "isdnloop: (%s) virtual card added\n",
1487 card->interface.id);
1488 return 0;
1489}
1490
1491static int __init
1492isdnloop_init(void)
1493{
1494 if (isdnloop_id)
1495 return isdnloop_addcard(isdnloop_id);
1496
1497 return 0;
1498}
1499
1500static void __exit
1501isdnloop_exit(void)
1502{
1503 isdn_ctrl cmd;
1504 isdnloop_card *card = cards;
1505 isdnloop_card *last;
1506 int i;
1507
1508 isdnloop_stopallcards();
1509 while (card) {
1510 cmd.command = ISDN_STAT_UNLOAD;
1511 cmd.driver = card->myid;
1512 card->interface.statcallb(&cmd);
1513 for (i = 0; i < ISDNLOOP_BCH; i++)
1514 isdnloop_free_queue(card, i);
1515 card = card->next;
1516 }
1517 card = cards;
1518 while (card) {
1519 last = card;
1520 skb_queue_purge(&card->dqueue);
1521 card = card->next;
1522 kfree(last);
1523 }
1524 printk(KERN_NOTICE "isdnloop-ISDN-driver unloaded\n");
1525}
1526
1527module_init(isdnloop_init);
1528module_exit(isdnloop_exit);
diff --git a/drivers/isdn/isdnloop/isdnloop.h b/drivers/isdn/isdnloop/isdnloop.h
deleted file mode 100644
index e9e035552bb4..000000000000
--- a/drivers/isdn/isdnloop/isdnloop.h
+++ /dev/null
@@ -1,112 +0,0 @@
1/* $Id: isdnloop.h,v 1.5.6.3 2001/09/23 22:24:56 kai Exp $
2 *
3 * Loopback lowlevel module for testing of linklevel.
4 *
5 * Copyright 1997 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#ifndef isdnloop_h
13#define isdnloop_h
14
15#define ISDNLOOP_IOCTL_DEBUGVAR 0
16#define ISDNLOOP_IOCTL_ADDCARD 1
17#define ISDNLOOP_IOCTL_LEASEDCFG 2
18#define ISDNLOOP_IOCTL_STARTUP 3
19
20/* Struct for adding new cards */
21typedef struct isdnloop_cdef {
22 char id1[10];
23} isdnloop_cdef;
24
25/* Struct for configuring cards */
26typedef struct isdnloop_sdef {
27 int ptype;
28 char num[3][20];
29} isdnloop_sdef;
30
31#if defined(__KERNEL__) || defined(__DEBUGVAR__)
32
33#ifdef __KERNEL__
34/* Kernel includes */
35
36#include <linux/errno.h>
37#include <linux/fs.h>
38#include <linux/major.h>
39#include <asm/io.h>
40#include <linux/kernel.h>
41#include <linux/signal.h>
42#include <linux/slab.h>
43#include <linux/mm.h>
44#include <linux/mman.h>
45#include <linux/ioport.h>
46#include <linux/timer.h>
47#include <linux/wait.h>
48#include <linux/isdnif.h>
49
50#endif /* __KERNEL__ */
51
52#define ISDNLOOP_FLAGS_B1ACTIVE 1 /* B-Channel-1 is open */
53#define ISDNLOOP_FLAGS_B2ACTIVE 2 /* B-Channel-2 is open */
54#define ISDNLOOP_FLAGS_RUNNING 4 /* Cards driver activated */
55#define ISDNLOOP_FLAGS_RBTIMER 8 /* scheduling of B-Channel-poll */
56#define ISDNLOOP_TIMER_BCREAD 1 /* B-Channel poll-cycle */
57#define ISDNLOOP_TIMER_DCREAD (HZ/2) /* D-Channel poll-cycle */
58#define ISDNLOOP_TIMER_ALERTWAIT (10 * HZ) /* Alert timeout */
59#define ISDNLOOP_MAX_SQUEUE 65536 /* Max. outstanding send-data */
60#define ISDNLOOP_BCH 2 /* channels per card */
61
62/*
63 * Per card driver data
64 */
65typedef struct isdnloop_card {
66 struct isdnloop_card *next; /* Pointer to next device struct */
67 struct isdnloop_card
68 *rcard[ISDNLOOP_BCH]; /* Pointer to 'remote' card */
69 int rch[ISDNLOOP_BCH]; /* 'remote' channel */
70 int myid; /* Driver-Nr. assigned by linklevel */
71 int leased; /* Flag: This Adapter is connected */
72 /* to a leased line */
73 int sil[ISDNLOOP_BCH]; /* SI's to listen for */
74 char eazlist[ISDNLOOP_BCH][11];
75 /* EAZ's to listen for */
76 char s0num[3][20]; /* 1TR6 base-number or MSN's */
77 unsigned short flags; /* Statusflags */
78 int ptype; /* Protocol type (1TR6 or Euro) */
79 struct timer_list st_timer; /* Timer for Status-Polls */
80 struct timer_list rb_timer; /* Timer for B-Channel-Polls */
81 struct timer_list
82 c_timer[ISDNLOOP_BCH]; /* Timer for Alerting */
83 int l2_proto[ISDNLOOP_BCH]; /* Current layer-2-protocol */
84 isdn_if interface; /* Interface to upper layer */
85 int iptr; /* Index to imsg-buffer */
86 char imsg[60]; /* Internal buf for status-parsing */
87 int optr; /* Index to omsg-buffer */
88 char omsg[60]; /* Internal buf for cmd-parsing */
89 char msg_buf[2048]; /* Buffer for status-messages */
90 char *msg_buf_write; /* Writepointer for statusbuffer */
91 char *msg_buf_read; /* Readpointer for statusbuffer */
92 char *msg_buf_end; /* Pointer to end of statusbuffer */
93 int sndcount[ISDNLOOP_BCH]; /* Byte-counters for B-Ch.-send */
94 struct sk_buff_head
95 bqueue[ISDNLOOP_BCH]; /* B-Channel queues */
96 struct sk_buff_head dqueue; /* D-Channel queue */
97 spinlock_t isdnloop_lock;
98} isdnloop_card;
99
100/*
101 * Main driver data
102 */
103#ifdef __KERNEL__
104static isdnloop_card *cards = (isdnloop_card *) 0;
105#endif /* __KERNEL__ */
106
107/* Utility-Macros */
108
109#define CID (card->interface.id)
110
111#endif /* defined(__KERNEL__) || defined(__DEBUGVAR__) */
112#endif /* isdnloop_h */
diff --git a/include/linux/concap.h b/include/linux/concap.h
deleted file mode 100644
index 977acb3d1fb2..000000000000
--- a/include/linux/concap.h
+++ /dev/null
@@ -1,112 +0,0 @@
1/* $Id: concap.h,v 1.3.2.2 2004/01/12 23:08:35 keil Exp $
2 *
3 * Copyright 1997 by Henner Eisen <eis@baty.hanse.de>
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#ifndef _LINUX_CONCAP_H
10#define _LINUX_CONCAP_H
11
12#include <linux/skbuff.h>
13#include <linux/netdevice.h>
14
15/* Stuff to support encapsulation protocols genericly. The encapsulation
16 protocol is processed at the uppermost layer of the network interface.
17
18 Based on a ideas developed in a 'synchronous device' thread in the
19 linux-x25 mailing list contributed by Alan Cox, Thomasz Motylewski
20 and Jonathan Naylor.
21
22 For more documetation on this refer to Documentation/isdn/README.concap
23*/
24
25struct concap_proto_ops;
26struct concap_device_ops;
27
28/* this manages all data needed by the encapsulation protocol
29 */
30struct concap_proto{
31 struct net_device *net_dev; /* net device using our service */
32 struct concap_device_ops *dops; /* callbacks provided by device */
33 struct concap_proto_ops *pops; /* callbacks provided by us */
34 spinlock_t lock;
35 int flags;
36 void *proto_data; /* protocol specific private data, to
37 be accessed via *pops methods only*/
38 /*
39 :
40 whatever
41 :
42 */
43};
44
45/* Operations to be supported by the net device. Called by the encapsulation
46 * protocol entity. No receive method is offered because the encapsulation
47 * protocol directly calls netif_rx().
48 */
49struct concap_device_ops{
50
51 /* to request data is submitted by device*/
52 int (*data_req)(struct concap_proto *, struct sk_buff *);
53
54 /* Control methods must be set to NULL by devices which do not
55 support connection control.*/
56 /* to request a connection is set up */
57 int (*connect_req)(struct concap_proto *);
58
59 /* to request a connection is released */
60 int (*disconn_req)(struct concap_proto *);
61};
62
63/* Operations to be supported by the encapsulation protocol. Called by
64 * device driver.
65 */
66struct concap_proto_ops{
67
68 /* create a new encapsulation protocol instance of same type */
69 struct concap_proto * (*proto_new) (void);
70
71 /* delete encapsulation protocol instance and free all its resources.
72 cprot may no loger be referenced after calling this */
73 void (*proto_del)(struct concap_proto *cprot);
74
75 /* initialize the protocol's data. To be called at interface startup
76 or when the device driver resets the interface. All services of the
77 encapsulation protocol may be used after this*/
78 int (*restart)(struct concap_proto *cprot,
79 struct net_device *ndev,
80 struct concap_device_ops *dops);
81
82 /* inactivate an encapsulation protocol instance. The encapsulation
83 protocol may not call any *dops methods after this. */
84 int (*close)(struct concap_proto *cprot);
85
86 /* process a frame handed down to us by upper layer */
87 int (*encap_and_xmit)(struct concap_proto *cprot, struct sk_buff *skb);
88
89 /* to be called for each data entity received from lower layer*/
90 int (*data_ind)(struct concap_proto *cprot, struct sk_buff *skb);
91
92 /* to be called when a connection was set up/down.
93 Protocols that don't process these primitives might fill in
94 dummy methods here */
95 int (*connect_ind)(struct concap_proto *cprot);
96 int (*disconn_ind)(struct concap_proto *cprot);
97 /*
98 Some network device support functions, like net_header(), rebuild_header(),
99 and others, that depend solely on the encapsulation protocol, might
100 be provided here, too. The net device would just fill them in its
101 corresponding fields when it is opened.
102 */
103};
104
105/* dummy restart/close/connect/reset/disconn methods
106 */
107extern int concap_nop(struct concap_proto *cprot);
108
109/* dummy submit method
110 */
111extern int concap_drop_skb(struct concap_proto *cprot, struct sk_buff *skb);
112#endif
diff --git a/include/linux/isdn.h b/include/linux/isdn.h
deleted file mode 100644
index df97c8444f5d..000000000000
--- a/include/linux/isdn.h
+++ /dev/null
@@ -1,473 +0,0 @@
1/* $Id: isdn.h,v 1.125.2.3 2004/02/10 01:07:14 keil Exp $
2 *
3 * Main header for the Linux ISDN subsystem (linklevel).
4 *
5 * Copyright 1994,95,96 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#ifndef __ISDN_H__
14#define __ISDN_H__
15
16
17#include <linux/errno.h>
18#include <linux/fs.h>
19#include <linux/major.h>
20#include <asm/io.h>
21#include <linux/kernel.h>
22#include <linux/signal.h>
23#include <linux/slab.h>
24#include <linux/timer.h>
25#include <linux/wait.h>
26#include <linux/tty.h>
27#include <linux/tty_flip.h>
28#include <linux/serial_reg.h>
29#include <linux/fcntl.h>
30#include <linux/types.h>
31#include <linux/interrupt.h>
32#include <linux/ip.h>
33#include <linux/in.h>
34#include <linux/netdevice.h>
35#include <linux/etherdevice.h>
36#include <linux/skbuff.h>
37#include <linux/tcp.h>
38#include <linux/mutex.h>
39#include <uapi/linux/isdn.h>
40
41#define ISDN_TTY_MAJOR 43
42#define ISDN_TTYAUX_MAJOR 44
43#define ISDN_MAJOR 45
44
45/* The minor-devicenumbers for Channel 0 and 1 are used as arguments for
46 * physical Channel-Mapping, so they MUST NOT be changed without changing
47 * the correspondent code in isdn.c
48 */
49
50#define ISDN_MINOR_B 0
51#define ISDN_MINOR_BMAX (ISDN_MAX_CHANNELS-1)
52#define ISDN_MINOR_CTRL 64
53#define ISDN_MINOR_CTRLMAX (64 + (ISDN_MAX_CHANNELS-1))
54#define ISDN_MINOR_PPP 128
55#define ISDN_MINOR_PPPMAX (128 + (ISDN_MAX_CHANNELS-1))
56#define ISDN_MINOR_STATUS 255
57
58#ifdef CONFIG_ISDN_PPP
59
60#ifdef CONFIG_ISDN_PPP_VJ
61# include <net/slhc_vj.h>
62#endif
63
64#include <linux/ppp_defs.h>
65#include <linux/ppp-ioctl.h>
66
67#include <linux/isdn_ppp.h>
68#endif
69
70#ifdef CONFIG_ISDN_X25
71# include <linux/concap.h>
72#endif
73
74#include <linux/isdnif.h>
75
76#define ISDN_DRVIOCTL_MASK 0x7f /* Mask for Device-ioctl */
77
78/* Until now unused */
79#define ISDN_SERVICE_VOICE 1
80#define ISDN_SERVICE_AB 1<<1
81#define ISDN_SERVICE_X21 1<<2
82#define ISDN_SERVICE_G4 1<<3
83#define ISDN_SERVICE_BTX 1<<4
84#define ISDN_SERVICE_DFUE 1<<5
85#define ISDN_SERVICE_X25 1<<6
86#define ISDN_SERVICE_TTX 1<<7
87#define ISDN_SERVICE_MIXED 1<<8
88#define ISDN_SERVICE_FW 1<<9
89#define ISDN_SERVICE_GTEL 1<<10
90#define ISDN_SERVICE_BTXN 1<<11
91#define ISDN_SERVICE_BTEL 1<<12
92
93/* Macros checking plain usage */
94#define USG_NONE(x) ((x & ISDN_USAGE_MASK)==ISDN_USAGE_NONE)
95#define USG_RAW(x) ((x & ISDN_USAGE_MASK)==ISDN_USAGE_RAW)
96#define USG_MODEM(x) ((x & ISDN_USAGE_MASK)==ISDN_USAGE_MODEM)
97#define USG_VOICE(x) ((x & ISDN_USAGE_MASK)==ISDN_USAGE_VOICE)
98#define USG_NET(x) ((x & ISDN_USAGE_MASK)==ISDN_USAGE_NET)
99#define USG_FAX(x) ((x & ISDN_USAGE_MASK)==ISDN_USAGE_FAX)
100#define USG_OUTGOING(x) ((x & ISDN_USAGE_OUTGOING)==ISDN_USAGE_OUTGOING)
101#define USG_MODEMORVOICE(x) (((x & ISDN_USAGE_MASK)==ISDN_USAGE_MODEM) || \
102 ((x & ISDN_USAGE_MASK)==ISDN_USAGE_VOICE) )
103
104/* Timer-delays and scheduling-flags */
105#define ISDN_TIMER_RES 4 /* Main Timer-Resolution */
106#define ISDN_TIMER_02SEC (HZ/ISDN_TIMER_RES/5) /* Slow-Timer1 .2 sec */
107#define ISDN_TIMER_1SEC (HZ/ISDN_TIMER_RES) /* Slow-Timer2 1 sec */
108#define ISDN_TIMER_RINGING 5 /* tty RINGs = ISDN_TIMER_1SEC * this factor */
109#define ISDN_TIMER_KEEPINT 10 /* Cisco-Keepalive = ISDN_TIMER_1SEC * this factor */
110#define ISDN_TIMER_MODEMREAD 1
111#define ISDN_TIMER_MODEMPLUS 2
112#define ISDN_TIMER_MODEMRING 4
113#define ISDN_TIMER_MODEMXMIT 8
114#define ISDN_TIMER_NETDIAL 16
115#define ISDN_TIMER_NETHANGUP 32
116#define ISDN_TIMER_CARRIER 256 /* Wait for Carrier */
117#define ISDN_TIMER_FAST (ISDN_TIMER_MODEMREAD | ISDN_TIMER_MODEMPLUS | \
118 ISDN_TIMER_MODEMXMIT)
119#define ISDN_TIMER_SLOW (ISDN_TIMER_MODEMRING | ISDN_TIMER_NETHANGUP | \
120 ISDN_TIMER_NETDIAL | ISDN_TIMER_CARRIER)
121
122/* Timeout-Values for isdn_net_dial() */
123#define ISDN_TIMER_DTIMEOUT10 (10*HZ/(ISDN_TIMER_02SEC*(ISDN_TIMER_RES+1)))
124#define ISDN_TIMER_DTIMEOUT15 (15*HZ/(ISDN_TIMER_02SEC*(ISDN_TIMER_RES+1)))
125#define ISDN_TIMER_DTIMEOUT60 (60*HZ/(ISDN_TIMER_02SEC*(ISDN_TIMER_RES+1)))
126
127/* GLOBAL_FLAGS */
128#define ISDN_GLOBAL_STOPPED 1
129
130/*=================== Start of ip-over-ISDN stuff =========================*/
131
132/* Feature- and status-flags for a net-interface */
133#define ISDN_NET_CONNECTED 0x01 /* Bound to ISDN-Channel */
134#define ISDN_NET_SECURE 0x02 /* Accept calls from phonelist only */
135#define ISDN_NET_CALLBACK 0x04 /* activate callback */
136#define ISDN_NET_CBHUP 0x08 /* hangup before callback */
137#define ISDN_NET_CBOUT 0x10 /* remote machine does callback */
138
139#define ISDN_NET_MAGIC 0x49344C02 /* for paranoia-checking */
140
141/* Phone-list-element */
142typedef struct {
143 void *next;
144 char num[ISDN_MSNLEN];
145} isdn_net_phone;
146
147/*
148 Principles when extending structures for generic encapsulation protocol
149 ("concap") support:
150 - Stuff which is hardware specific (here i4l-specific) goes in
151 the netdev -> local structure (here: isdn_net_local)
152 - Stuff which is encapsulation protocol specific goes in the structure
153 which holds the linux device structure (here: isdn_net_device)
154*/
155
156/* Local interface-data */
157typedef struct isdn_net_local_s {
158 ulong magic;
159 struct net_device_stats stats; /* Ethernet Statistics */
160 int isdn_device; /* Index to isdn-device */
161 int isdn_channel; /* Index to isdn-channel */
162 int ppp_slot; /* PPPD device slot number */
163 int pre_device; /* Preselected isdn-device */
164 int pre_channel; /* Preselected isdn-channel */
165 int exclusive; /* If non-zero idx to reserved chan.*/
166 int flags; /* Connection-flags */
167 int dialretry; /* Counter for Dialout-retries */
168 int dialmax; /* Max. Number of Dial-retries */
169 int cbdelay; /* Delay before Callback starts */
170 int dtimer; /* Timeout-counter for dialing */
171 char msn[ISDN_MSNLEN]; /* MSNs/EAZs for this interface */
172 u_char cbhup; /* Flag: Reject Call before Callback*/
173 u_char dialstate; /* State for dialing */
174 u_char p_encap; /* Packet encapsulation */
175 /* 0 = Ethernet over ISDN */
176 /* 1 = RAW-IP */
177 /* 2 = IP with type field */
178 u_char l2_proto; /* Layer-2-protocol */
179 /* See ISDN_PROTO_L2..-constants in */
180 /* isdnif.h */
181 /* 0 = X75/LAPB with I-Frames */
182 /* 1 = X75/LAPB with UI-Frames */
183 /* 2 = X75/LAPB with BUI-Frames */
184 /* 3 = HDLC */
185 u_char l3_proto; /* Layer-3-protocol */
186 /* See ISDN_PROTO_L3..-constants in */
187 /* isdnif.h */
188 /* 0 = Transparent */
189 int huptimer; /* Timeout-counter for auto-hangup */
190 int charge; /* Counter for charging units */
191 ulong chargetime; /* Timer for Charging info */
192 int hupflags; /* Flags for charge-unit-hangup: */
193 /* bit0: chargeint is invalid */
194 /* bit1: Getting charge-interval */
195 /* bit2: Do charge-unit-hangup */
196 /* bit3: Do hangup even on incoming */
197 int outgoing; /* Flag: outgoing call */
198 int onhtime; /* Time to keep link up */
199 int chargeint; /* Interval between charge-infos */
200 int onum; /* Flag: at least 1 outgoing number */
201 int cps; /* current speed of this interface */
202 int transcount; /* byte-counter for cps-calculation */
203 int sqfull; /* Flag: netdev-queue overloaded */
204 ulong sqfull_stamp; /* Start-Time of overload */
205 ulong slavedelay; /* Dynamic bundling delaytime */
206 int triggercps; /* BogoCPS needed for trigger slave */
207 isdn_net_phone *phone[2]; /* List of remote-phonenumbers */
208 /* phone[0] = Incoming Numbers */
209 /* phone[1] = Outgoing Numbers */
210 isdn_net_phone *dial; /* Pointer to dialed number */
211 struct net_device *master; /* Ptr to Master device for slaves */
212 struct net_device *slave; /* Ptr to Slave device for masters */
213 struct isdn_net_local_s *next; /* Ptr to next link in bundle */
214 struct isdn_net_local_s *last; /* Ptr to last link in bundle */
215 struct isdn_net_dev_s *netdev; /* Ptr to netdev */
216 struct sk_buff_head super_tx_queue; /* List of supervisory frames to */
217 /* be transmitted asap */
218 atomic_t frame_cnt; /* number of frames currently */
219 /* queued in HL driver */
220 /* Ptr to orig. hard_header_cache */
221 spinlock_t xmit_lock; /* used to protect the xmit path of */
222 /* a particular channel (including */
223 /* the frame_cnt */
224
225 int pppbind; /* ippp device for bindings */
226 int dialtimeout; /* How long shall we try on dialing? (jiffies) */
227 int dialwait; /* How long shall we wait after failed attempt? (jiffies) */
228 ulong dialstarted; /* jiffies of first dialing-attempt */
229 ulong dialwait_timer; /* jiffies of earliest next dialing-attempt */
230 int huptimeout; /* How long will the connection be up? (seconds) */
231#ifdef CONFIG_ISDN_X25
232 struct concap_device_ops *dops; /* callbacks used by encapsulator */
233#endif
234 /* use an own struct for that in later versions */
235 ulong cisco_myseq; /* Local keepalive seq. for Cisco */
236 ulong cisco_mineseen; /* returned keepalive seq. from remote */
237 ulong cisco_yourseq; /* Remote keepalive seq. for Cisco */
238 int cisco_keepalive_period; /* keepalive period */
239 ulong cisco_last_slarp_in; /* jiffie of last keepalive packet we received */
240 char cisco_line_state; /* state of line according to keepalive packets */
241 char cisco_debserint; /* debugging flag of cisco hdlc with slarp */
242 struct timer_list cisco_timer;
243 struct work_struct tqueue;
244} isdn_net_local;
245
246/* the interface itself */
247typedef struct isdn_net_dev_s {
248 isdn_net_local *local;
249 isdn_net_local *queue; /* circular list of all bundled
250 channels, which are currently
251 online */
252 spinlock_t queue_lock; /* lock to protect queue */
253 void *next; /* Pointer to next isdn-interface */
254 struct net_device *dev; /* interface to upper levels */
255#ifdef CONFIG_ISDN_PPP
256 ippp_bundle * pb; /* pointer to the common bundle structure
257 * with the per-bundle data */
258#endif
259#ifdef CONFIG_ISDN_X25
260 struct concap_proto *cprot; /* connection oriented encapsulation protocol */
261#endif
262
263} isdn_net_dev;
264
265/*===================== End of ip-over-ISDN stuff ===========================*/
266
267/*======================= Start of ISDN-tty stuff ===========================*/
268
269#define ISDN_ASYNC_MAGIC 0x49344C01 /* for paranoia-checking */
270#define ISDN_SERIAL_XMIT_SIZE 1024 /* Default bufsize for write */
271#define ISDN_SERIAL_XMIT_MAX 4000 /* Maximum bufsize for write */
272
273#ifdef CONFIG_ISDN_AUDIO
274/* For using sk_buffs with audio we need some private variables
275 * within each sk_buff. For this purpose, we declare a struct here,
276 * and put it always at the private skb->cb data array. A few macros help
277 * accessing the variables.
278 */
279typedef struct _isdn_audio_data {
280 unsigned short dle_count;
281 unsigned char lock;
282} isdn_audio_data_t;
283
284#define ISDN_AUDIO_SKB_DLECOUNT(skb) (((isdn_audio_data_t *)&skb->cb[0])->dle_count)
285#define ISDN_AUDIO_SKB_LOCK(skb) (((isdn_audio_data_t *)&skb->cb[0])->lock)
286#endif
287
288/* Private data of AT-command-interpreter */
289typedef struct atemu {
290 u_char profile[ISDN_MODEM_NUMREG]; /* Modem-Regs. Profile 0 */
291 u_char mdmreg[ISDN_MODEM_NUMREG]; /* Modem-Registers */
292 char pmsn[ISDN_MSNLEN]; /* EAZ/MSNs Profile 0 */
293 char msn[ISDN_MSNLEN]; /* EAZ/MSN */
294 char plmsn[ISDN_LMSNLEN]; /* Listening MSNs Profile 0 */
295 char lmsn[ISDN_LMSNLEN]; /* Listening MSNs */
296 char cpn[ISDN_MSNLEN]; /* CalledPartyNumber on incoming call */
297 char connmsg[ISDN_CMSGLEN]; /* CONNECT-Msg from HL-Driver */
298#ifdef CONFIG_ISDN_AUDIO
299 u_char vpar[10]; /* Voice-parameters */
300 int lastDLE; /* Flag for voice-coding: DLE seen */
301#endif
302 int mdmcmdl; /* Length of Modem-Commandbuffer */
303 int pluscount; /* Counter for +++ sequence */
304 u_long lastplus; /* Timestamp of last + */
305 int carrierwait; /* Seconds of carrier waiting */
306 char mdmcmd[255]; /* Modem-Commandbuffer */
307 unsigned int charge; /* Charge units of current connection */
308} atemu;
309
310/* Private data (similar to async_struct in <linux/serial.h>) */
311typedef struct modem_info {
312 int magic;
313 struct tty_port port;
314 int x_char; /* xon/xoff character */
315 int mcr; /* Modem control register */
316 int msr; /* Modem status register */
317 int lsr; /* Line status register */
318 int line;
319 int online; /* 1 = B-Channel is up, drop data */
320 /* 2 = B-Channel is up, deliver d.*/
321 int dialing; /* Dial in progress or ATA */
322 int closing;
323 int rcvsched; /* Receive needs schedule */
324 int isdn_driver; /* Index to isdn-driver */
325 int isdn_channel; /* Index to isdn-channel */
326 int drv_index; /* Index to dev->usage */
327 int ncarrier; /* Flag: schedule NO CARRIER */
328 unsigned char last_cause[8]; /* Last cause message */
329 unsigned char last_num[ISDN_MSNLEN];
330 /* Last phone-number */
331 unsigned char last_l2; /* Last layer-2 protocol */
332 unsigned char last_si; /* Last service */
333 unsigned char last_lhup; /* Last hangup local? */
334 unsigned char last_dir; /* Last direction (in or out) */
335 struct timer_list nc_timer; /* Timer for delayed NO CARRIER */
336 int send_outstanding;/* # of outstanding send-requests */
337 int xmit_size; /* max. # of chars in xmit_buf */
338 int xmit_count; /* # of chars in xmit_buf */
339 struct sk_buff_head xmit_queue; /* transmit queue */
340 atomic_t xmit_lock; /* Semaphore for isdn_tty_write */
341#ifdef CONFIG_ISDN_AUDIO
342 int vonline; /* Voice-channel status */
343 /* Bit 0 = recording */
344 /* Bit 1 = playback */
345 /* Bit 2 = playback, DLE-ETX seen */
346 struct sk_buff_head dtmf_queue; /* queue for dtmf results */
347 void *adpcms; /* state for adpcm decompression */
348 void *adpcmr; /* state for adpcm compression */
349 void *dtmf_state; /* state for dtmf decoder */
350 void *silence_state; /* state for silence detection */
351#endif
352#ifdef CONFIG_ISDN_TTY_FAX
353 struct T30_s *fax; /* T30 Fax Group 3 data/interface */
354 int faxonline; /* Fax-channel status */
355#endif
356 atemu emu; /* AT-emulator data */
357 spinlock_t readlock;
358} modem_info;
359
360#define ISDN_MODEM_WINSIZE 8
361
362/* Description of one ISDN-tty */
363typedef struct _isdn_modem {
364 int refcount; /* Number of opens */
365 struct tty_driver *tty_modem; /* tty-device */
366 struct tty_struct *modem_table[ISDN_MAX_CHANNELS]; /* ?? copied from Orig */
367 struct ktermios *modem_termios[ISDN_MAX_CHANNELS];
368 struct ktermios *modem_termios_locked[ISDN_MAX_CHANNELS];
369 modem_info info[ISDN_MAX_CHANNELS]; /* Private data */
370} isdn_modem_t;
371
372/*======================= End of ISDN-tty stuff ============================*/
373
374/*======================== Start of V.110 stuff ============================*/
375#define V110_BUFSIZE 1024
376
377typedef struct {
378 int nbytes; /* 1 Matrixbyte -> nbytes in stream */
379 int nbits; /* Number of used bits in streambyte */
380 unsigned char key; /* Bitmask in stream eg. 11 (nbits=2) */
381 int decodelen; /* Amount of data in decodebuf */
382 int SyncInit; /* Number of sync frames to send */
383 unsigned char *OnlineFrame; /* Precalculated V110 idle frame */
384 unsigned char *OfflineFrame; /* Precalculated V110 sync Frame */
385 int framelen; /* Length of frames */
386 int skbuser; /* Number of unacked userdata skbs */
387 int skbidle; /* Number of unacked idle/sync skbs */
388 int introducer; /* Local vars for decoder */
389 int dbit;
390 unsigned char b;
391 int skbres; /* space to reserve in outgoing skb */
392 int maxsize; /* maxbufsize of lowlevel driver */
393 unsigned char *encodebuf; /* temporary buffer for encoding */
394 unsigned char decodebuf[V110_BUFSIZE]; /* incomplete V110 matrices */
395} isdn_v110_stream;
396
397/*========================= End of V.110 stuff =============================*/
398
399/*======================= Start of general stuff ===========================*/
400
401typedef struct {
402 char *next;
403 char *private;
404} infostruct;
405
406#define DRV_FLAG_RUNNING 1
407#define DRV_FLAG_REJBUS 2
408#define DRV_FLAG_LOADED 4
409
410/* Description of hardware-level-driver */
411typedef struct _isdn_driver {
412 ulong online; /* Channel-Online flags */
413 ulong flags; /* Misc driver Flags */
414 int locks; /* Number of locks for this driver */
415 int channels; /* Number of channels */
416 wait_queue_head_t st_waitq; /* Wait-Queue for status-read's */
417 int maxbufsize; /* Maximum Buffersize supported */
418 unsigned long pktcount; /* Until now: unused */
419 int stavail; /* Chars avail on Status-device */
420 isdn_if *interface; /* Interface to driver */
421 int *rcverr; /* Error-counters for B-Ch.-receive */
422 int *rcvcount; /* Byte-counters for B-Ch.-receive */
423#ifdef CONFIG_ISDN_AUDIO
424 unsigned long DLEflag; /* Flags: Insert DLE at next read */
425#endif
426 struct sk_buff_head *rpqueue; /* Pointers to start of Rcv-Queue */
427 wait_queue_head_t *rcv_waitq; /* Wait-Queues for B-Channel-Reads */
428 wait_queue_head_t *snd_waitq; /* Wait-Queue for B-Channel-Send's */
429 char msn2eaz[10][ISDN_MSNLEN]; /* Mapping-Table MSN->EAZ */
430} isdn_driver_t;
431
432/* Main driver-data */
433typedef struct isdn_devt {
434 struct module *owner;
435 spinlock_t lock;
436 unsigned short flags; /* Bitmapped Flags: */
437 int drivers; /* Current number of drivers */
438 int channels; /* Current number of channels */
439 int net_verbose; /* Verbose-Flag */
440 int modempoll; /* Flag: tty-read active */
441 spinlock_t timerlock;
442 int tflags; /* Timer-Flags: */
443 /* see ISDN_TIMER_..defines */
444 int global_flags;
445 infostruct *infochain; /* List of open info-devs. */
446 wait_queue_head_t info_waitq; /* Wait-Queue for isdninfo */
447 struct timer_list timer; /* Misc.-function Timer */
448 int chanmap[ISDN_MAX_CHANNELS]; /* Map minor->device-channel */
449 int drvmap[ISDN_MAX_CHANNELS]; /* Map minor->driver-index */
450 int usage[ISDN_MAX_CHANNELS]; /* Used by tty/ip/voice */
451 char num[ISDN_MAX_CHANNELS][ISDN_MSNLEN];
452 /* Remote number of active ch.*/
453 int m_idx[ISDN_MAX_CHANNELS]; /* Index for mdm.... */
454 isdn_driver_t *drv[ISDN_MAX_DRIVERS]; /* Array of drivers */
455 isdn_net_dev *netdev; /* Linked list of net-if's */
456 char drvid[ISDN_MAX_DRIVERS][20];/* Driver-ID */
457 struct task_struct *profd; /* For iprofd */
458 isdn_modem_t mdm; /* tty-driver-data */
459 isdn_net_dev *rx_netdev[ISDN_MAX_CHANNELS]; /* rx netdev-pointers */
460 isdn_net_dev *st_netdev[ISDN_MAX_CHANNELS]; /* stat netdev-pointers */
461 ulong ibytes[ISDN_MAX_CHANNELS]; /* Statistics incoming bytes */
462 ulong obytes[ISDN_MAX_CHANNELS]; /* Statistics outgoing bytes */
463 int v110emu[ISDN_MAX_CHANNELS]; /* V.110 emulator-mode 0=none */
464 atomic_t v110use[ISDN_MAX_CHANNELS]; /* Usage-Semaphore for stream */
465 isdn_v110_stream *v110[ISDN_MAX_CHANNELS]; /* V.110 private data */
466 struct mutex mtx; /* serialize list access*/
467 unsigned long global_features;
468} isdn_dev;
469
470extern isdn_dev *dev;
471
472
473#endif /* __ISDN_H__ */
diff --git a/include/linux/isdn_divertif.h b/include/linux/isdn_divertif.h
deleted file mode 100644
index 19ab361f9f07..000000000000
--- a/include/linux/isdn_divertif.h
+++ /dev/null
@@ -1,35 +0,0 @@
1/* $Id: isdn_divertif.h,v 1.4.6.1 2001/09/23 22:25:05 kai Exp $
2 *
3 * Header for the diversion supplementary interface for i4l.
4 *
5 * Author Werner Cornelius (werner@titro.de)
6 * Copyright by Werner Cornelius (werner@titro.de)
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#ifndef _LINUX_ISDN_DIVERTIF_H
13#define _LINUX_ISDN_DIVERTIF_H
14
15#include <linux/isdnif.h>
16#include <linux/types.h>
17#include <uapi/linux/isdn_divertif.h>
18
19/***************************************************************/
20/* structure exchanging data between isdn hl and divert module */
21/***************************************************************/
22typedef struct
23 { ulong if_magic; /* magic info and version */
24 int cmd; /* command */
25 int (*stat_callback)(isdn_ctrl *); /* supplied by divert module when calling */
26 int (*ll_cmd)(isdn_ctrl *); /* supplied by hl on return */
27 char * (*drv_to_name)(int); /* map a driver id to name, supplied by hl */
28 int (*name_to_drv)(char *); /* map a driver id to name, supplied by hl */
29 } isdn_divert_if;
30
31/*********************/
32/* function register */
33/*********************/
34extern int DIVERT_REG_NAME(isdn_divert_if *);
35#endif /* _LINUX_ISDN_DIVERTIF_H */
diff --git a/include/linux/isdn_ppp.h b/include/linux/isdn_ppp.h
deleted file mode 100644
index a0070c6dfaf8..000000000000
--- a/include/linux/isdn_ppp.h
+++ /dev/null
@@ -1,194 +0,0 @@
1/* Linux ISDN subsystem, sync PPP, interface to ipppd
2 *
3 * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de)
4 * Copyright 1995,96 Thinking Objects Software GmbH Wuerzburg
5 * Copyright 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
6 * Copyright 2000-2002 by Kai Germaschewski (kai@germaschewski.name)
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#ifndef _LINUX_ISDN_PPP_H
13#define _LINUX_ISDN_PPP_H
14
15
16
17
18#ifdef CONFIG_IPPP_FILTER
19#include <linux/filter.h>
20#endif
21#include <uapi/linux/isdn_ppp.h>
22
23#define DECOMP_ERR_NOMEM (-10)
24
25#define MP_END_FRAG 0x40
26#define MP_BEGIN_FRAG 0x80
27
28#define MP_MAX_QUEUE_LEN 16
29
30/*
31 * We need a way for the decompressor to influence the generation of CCP
32 * Reset-Requests in a variety of ways. The decompressor is already returning
33 * a lot of information (generated skb length, error conditions) so we use
34 * another parameter. This parameter is a pointer to a structure which is
35 * to be marked valid by the decompressor and only in this case is ever used.
36 * Furthermore, the only case where this data is used is when the decom-
37 * pressor returns DECOMP_ERROR.
38 *
39 * We use this same struct for the reset entry of the compressor to commu-
40 * nicate to its caller how to deal with sending of a Reset Ack. In this
41 * case, expra is not used, but other options still apply (suppressing
42 * sending with rsend, appending arbitrary data, etc).
43 */
44
45#define IPPP_RESET_MAXDATABYTES 32
46
47struct isdn_ppp_resetparams {
48 unsigned char valid:1; /* rw Is this structure filled at all ? */
49 unsigned char rsend:1; /* rw Should we send one at all ? */
50 unsigned char idval:1; /* rw Is the id field valid ? */
51 unsigned char dtval:1; /* rw Is the data field valid ? */
52 unsigned char expra:1; /* rw Is an Ack expected for this Req ? */
53 unsigned char id; /* wo Send CCP ResetReq with this id */
54 unsigned short maxdlen; /* ro Max bytes to be stored in data field */
55 unsigned short dlen; /* rw Bytes stored in data field */
56 unsigned char *data; /* wo Data for ResetReq info field */
57};
58
59/*
60 * this is an 'old friend' from ppp-comp.h under a new name
61 * check the original include for more information
62 */
63struct isdn_ppp_compressor {
64 struct isdn_ppp_compressor *next, *prev;
65 struct module *owner;
66 int num; /* CCP compression protocol number */
67
68 void *(*alloc) (struct isdn_ppp_comp_data *);
69 void (*free) (void *state);
70 int (*init) (void *state, struct isdn_ppp_comp_data *,
71 int unit,int debug);
72
73 /* The reset entry needs to get more exact information about the
74 ResetReq or ResetAck it was called with. The parameters are
75 obvious. If reset is called without a Req or Ack frame which
76 could be handed into it, code MUST be set to 0. Using rsparm,
77 the reset entry can control if and how a ResetAck is returned. */
78
79 void (*reset) (void *state, unsigned char code, unsigned char id,
80 unsigned char *data, unsigned len,
81 struct isdn_ppp_resetparams *rsparm);
82
83 int (*compress) (void *state, struct sk_buff *in,
84 struct sk_buff *skb_out, int proto);
85
86 int (*decompress) (void *state,struct sk_buff *in,
87 struct sk_buff *skb_out,
88 struct isdn_ppp_resetparams *rsparm);
89
90 void (*incomp) (void *state, struct sk_buff *in,int proto);
91 void (*stat) (void *state, struct compstat *stats);
92};
93
94extern int isdn_ppp_register_compressor(struct isdn_ppp_compressor *);
95extern int isdn_ppp_unregister_compressor(struct isdn_ppp_compressor *);
96extern int isdn_ppp_dial_slave(char *);
97extern int isdn_ppp_hangup_slave(char *);
98
99typedef struct {
100 unsigned long seqerrs;
101 unsigned long frame_drops;
102 unsigned long overflows;
103 unsigned long max_queue_len;
104} isdn_mppp_stats;
105
106typedef struct {
107 int mp_mrru; /* unused */
108 struct sk_buff * frags; /* fragments sl list -- use skb->next */
109 long frames; /* number of frames in the frame list */
110 unsigned int seq; /* last processed packet seq #: any packets
111 * with smaller seq # will be dropped
112 * unconditionally */
113 spinlock_t lock;
114 int ref_ct;
115 /* statistics */
116 isdn_mppp_stats stats;
117} ippp_bundle;
118
119#define NUM_RCV_BUFFS 64
120
121struct ippp_buf_queue {
122 struct ippp_buf_queue *next;
123 struct ippp_buf_queue *last;
124 char *buf; /* NULL here indicates end of queue */
125 int len;
126};
127
128/* The data structure for one CCP reset transaction */
129enum ippp_ccp_reset_states {
130 CCPResetIdle,
131 CCPResetSentReq,
132 CCPResetRcvdReq,
133 CCPResetSentAck,
134 CCPResetRcvdAck
135};
136
137struct ippp_ccp_reset_state {
138 enum ippp_ccp_reset_states state; /* State of this transaction */
139 struct ippp_struct *is; /* Backlink to device stuff */
140 unsigned char id; /* Backlink id index */
141 unsigned char ta:1; /* The timer is active (flag) */
142 unsigned char expra:1; /* We expect a ResetAck at all */
143 int dlen; /* Databytes stored in data */
144 struct timer_list timer; /* For timeouts/retries */
145 /* This is a hack but seems sufficient for the moment. We do not want
146 to have this be yet another allocation for some bytes, it is more
147 memory management overhead than the whole mess is worth. */
148 unsigned char data[IPPP_RESET_MAXDATABYTES];
149};
150
151/* The data structure keeping track of the currently outstanding CCP Reset
152 transactions. */
153struct ippp_ccp_reset {
154 struct ippp_ccp_reset_state *rs[256]; /* One per possible id */
155 unsigned char lastid; /* Last id allocated by the engine */
156};
157
158struct ippp_struct {
159 struct ippp_struct *next_link;
160 int state;
161 spinlock_t buflock;
162 struct ippp_buf_queue rq[NUM_RCV_BUFFS]; /* packet queue for isdn_ppp_read() */
163 struct ippp_buf_queue *first; /* pointer to (current) first packet */
164 struct ippp_buf_queue *last; /* pointer to (current) last used packet in queue */
165 wait_queue_head_t wq;
166 struct task_struct *tk;
167 unsigned int mpppcfg;
168 unsigned int pppcfg;
169 unsigned int mru;
170 unsigned int mpmru;
171 unsigned int mpmtu;
172 unsigned int maxcid;
173 struct isdn_net_local_s *lp;
174 int unit;
175 int minor;
176 unsigned int last_link_seqno;
177 long mp_seqno;
178#ifdef CONFIG_ISDN_PPP_VJ
179 unsigned char *cbuf;
180 struct slcompress *slcomp;
181#endif
182#ifdef CONFIG_IPPP_FILTER
183 struct bpf_prog *pass_filter; /* filter for packets to pass */
184 struct bpf_prog *active_filter; /* filter for pkts to reset idle */
185#endif
186 unsigned long debug;
187 struct isdn_ppp_compressor *compressor,*decompressor;
188 struct isdn_ppp_compressor *link_compressor,*link_decompressor;
189 void *decomp_stat,*comp_stat,*link_decomp_stat,*link_comp_stat;
190 struct ippp_ccp_reset *reset; /* Allocated on demand, may never be needed */
191 unsigned long compflags;
192};
193
194#endif /* _LINUX_ISDN_PPP_H */
diff --git a/include/linux/isdnif.h b/include/linux/isdnif.h
deleted file mode 100644
index 8d80fdc68647..000000000000
--- a/include/linux/isdnif.h
+++ /dev/null
@@ -1,505 +0,0 @@
1/* $Id: isdnif.h,v 1.43.2.2 2004/01/12 23:08:35 keil Exp $
2 *
3 * Linux ISDN subsystem
4 * Definition of the interface between the subsystem and its low-level drivers.
5 *
6 * Copyright 1994,95,96 by Fritz Elfert (fritz@isdn4linux.de)
7 * Copyright 1995,96 Thinking Objects Software GmbH Wuerzburg
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#ifndef __ISDNIF_H__
14#define __ISDNIF_H__
15
16
17#include <linux/skbuff.h>
18#include <uapi/linux/isdnif.h>
19
20/***************************************************************************/
21/* Extensions made by Werner Cornelius (werner@ikt.de) */
22/* */
23/* The proceed command holds a incoming call in a state to leave processes */
24/* enough time to check whether ist should be accepted. */
25/* The PROT_IO Command extends the interface to make protocol dependent */
26/* features available (call diversion, call waiting...). */
27/* */
28/* The PROT_IO Command is executed with the desired driver id and the arg */
29/* parameter coded as follows: */
30/* The lower 8 bits of arg contain the desired protocol from ISDN_PTYPE */
31/* definitions. The upper 24 bits represent the protocol specific cmd/stat.*/
32/* Any additional data is protocol and command specific. */
33/* This mechanism also applies to the statcallb callback STAT_PROT. */
34/* */
35/* This suggested extension permits an easy expansion of protocol specific */
36/* handling. Extensions may be added at any time without changing the HL */
37/* driver code and not getting conflicts without certifications. */
38/* The well known CAPI 2.0 interface handles such extensions in a similar */
39/* way. Perhaps a protocol specific module may be added and separately */
40/* loaded and linked to the basic isdn module for handling. */
41/***************************************************************************/
42
43/*****************/
44/* DSS1 commands */
45/*****************/
46#define DSS1_CMD_INVOKE ((0x00 << 8) | ISDN_PTYPE_EURO) /* invoke a supplementary service */
47#define DSS1_CMD_INVOKE_ABORT ((0x01 << 8) | ISDN_PTYPE_EURO) /* abort a invoke cmd */
48
49/*******************************/
50/* DSS1 Status callback values */
51/*******************************/
52#define DSS1_STAT_INVOKE_RES ((0x80 << 8) | ISDN_PTYPE_EURO) /* Result for invocation */
53#define DSS1_STAT_INVOKE_ERR ((0x81 << 8) | ISDN_PTYPE_EURO) /* Error Return for invocation */
54#define DSS1_STAT_INVOKE_BRD ((0x82 << 8) | ISDN_PTYPE_EURO) /* Deliver invoke broadcast info */
55
56
57/*********************************************************************/
58/* structures for DSS1 commands and callback */
59/* */
60/* An action is invoked by sending a DSS1_CMD_INVOKE. The ll_id, proc*/
61/* timeout, datalen and data fields must be set before calling. */
62/* */
63/* The return value is a positive hl_id value also delivered in the */
64/* hl_id field. A value of zero signals no more left hl_id capacitys.*/
65/* A negative return value signals errors in LL. So if the return */
66/* value is <= 0 no action in LL will be taken -> request ignored */
67/* */
68/* The timeout field must be filled with a positive value specifying */
69/* the amount of time the INVOKED process waits for a reaction from */
70/* the network. */
71/* If a response (either error or result) is received during this */
72/* intervall, a reporting callback is initiated and the process will */
73/* be deleted, the hl identifier will be freed. */
74/* If no response is received during the specified intervall, a error*/
75/* callback is initiated with timeout set to -1 and a datalen set */
76/* to 0. */
77/* If timeout is set to a value <= 0 during INVOCATION the process is*/
78/* immediately deleted after sending the data. No callback occurs ! */
79/* */
80/* A currently waiting process may be aborted with INVOKE_ABORT. No */
81/* callback will occur when a process has been aborted. */
82/* */
83/* Broadcast invoke frames from the network are reported via the */
84/* STAT_INVOKE_BRD callback. The ll_id is set to 0, the other fields */
85/* are supplied by the network and not by the HL. */
86/*********************************************************************/
87
88/*****************/
89/* NI1 commands */
90/*****************/
91#define NI1_CMD_INVOKE ((0x00 << 8) | ISDN_PTYPE_NI1) /* invoke a supplementary service */
92#define NI1_CMD_INVOKE_ABORT ((0x01 << 8) | ISDN_PTYPE_NI1) /* abort a invoke cmd */
93
94/*******************************/
95/* NI1 Status callback values */
96/*******************************/
97#define NI1_STAT_INVOKE_RES ((0x80 << 8) | ISDN_PTYPE_NI1) /* Result for invocation */
98#define NI1_STAT_INVOKE_ERR ((0x81 << 8) | ISDN_PTYPE_NI1) /* Error Return for invocation */
99#define NI1_STAT_INVOKE_BRD ((0x82 << 8) | ISDN_PTYPE_NI1) /* Deliver invoke broadcast info */
100
101typedef struct
102 { ulong ll_id; /* ID supplied by LL when executing */
103 /* a command and returned by HL for */
104 /* INVOKE_RES and INVOKE_ERR */
105 int hl_id; /* ID supplied by HL when called */
106 /* for executing a cmd and delivered */
107 /* for results and errors */
108 /* must be supplied by LL when aborting*/
109 int proc; /* invoke procedure used by CMD_INVOKE */
110 /* returned by callback and broadcast */
111 int timeout; /* timeout for INVOKE CMD in ms */
112 /* -1 in stat callback when timed out */
113 /* error value when error callback */
114 int datalen; /* length of cmd or stat data */
115 u_char *data;/* pointer to data delivered or send */
116 } isdn_cmd_stat;
117
118/*
119 * Commands from linklevel to lowlevel
120 *
121 */
122#define ISDN_CMD_IOCTL 0 /* Perform ioctl */
123#define ISDN_CMD_DIAL 1 /* Dial out */
124#define ISDN_CMD_ACCEPTD 2 /* Accept an incoming call on D-Chan. */
125#define ISDN_CMD_ACCEPTB 3 /* Request B-Channel connect. */
126#define ISDN_CMD_HANGUP 4 /* Hangup */
127#define ISDN_CMD_CLREAZ 5 /* Clear EAZ(s) of channel */
128#define ISDN_CMD_SETEAZ 6 /* Set EAZ(s) of channel */
129#define ISDN_CMD_GETEAZ 7 /* Get EAZ(s) of channel */
130#define ISDN_CMD_SETSIL 8 /* Set Service-Indicator-List of channel */
131#define ISDN_CMD_GETSIL 9 /* Get Service-Indicator-List of channel */
132#define ISDN_CMD_SETL2 10 /* Set B-Chan. Layer2-Parameter */
133#define ISDN_CMD_GETL2 11 /* Get B-Chan. Layer2-Parameter */
134#define ISDN_CMD_SETL3 12 /* Set B-Chan. Layer3-Parameter */
135#define ISDN_CMD_GETL3 13 /* Get B-Chan. Layer3-Parameter */
136// #define ISDN_CMD_LOCK 14 /* Signal usage by upper levels */
137// #define ISDN_CMD_UNLOCK 15 /* Release usage-lock */
138#define ISDN_CMD_SUSPEND 16 /* Suspend connection */
139#define ISDN_CMD_RESUME 17 /* Resume connection */
140#define ISDN_CMD_PROCEED 18 /* Proceed with call establishment */
141#define ISDN_CMD_ALERT 19 /* Alert after Proceeding */
142#define ISDN_CMD_REDIR 20 /* Redir a incoming call */
143#define ISDN_CMD_PROT_IO 21 /* Protocol specific commands */
144#define CAPI_PUT_MESSAGE 22 /* CAPI message send down or up */
145#define ISDN_CMD_FAXCMD 23 /* FAX commands to HL-driver */
146#define ISDN_CMD_AUDIO 24 /* DSP, DTMF, ... settings */
147
148/*
149 * Status-Values delivered from lowlevel to linklevel via
150 * statcallb().
151 *
152 */
153#define ISDN_STAT_STAVAIL 256 /* Raw status-data available */
154#define ISDN_STAT_ICALL 257 /* Incoming call detected */
155#define ISDN_STAT_RUN 258 /* Signal protocol-code is running */
156#define ISDN_STAT_STOP 259 /* Signal halt of protocol-code */
157#define ISDN_STAT_DCONN 260 /* Signal D-Channel connect */
158#define ISDN_STAT_BCONN 261 /* Signal B-Channel connect */
159#define ISDN_STAT_DHUP 262 /* Signal D-Channel disconnect */
160#define ISDN_STAT_BHUP 263 /* Signal B-Channel disconnect */
161#define ISDN_STAT_CINF 264 /* Charge-Info */
162#define ISDN_STAT_LOAD 265 /* Signal new lowlevel-driver is loaded */
163#define ISDN_STAT_UNLOAD 266 /* Signal unload of lowlevel-driver */
164#define ISDN_STAT_BSENT 267 /* Signal packet sent */
165#define ISDN_STAT_NODCH 268 /* Signal no D-Channel */
166#define ISDN_STAT_ADDCH 269 /* Add more Channels */
167#define ISDN_STAT_CAUSE 270 /* Cause-Message */
168#define ISDN_STAT_ICALLW 271 /* Incoming call without B-chan waiting */
169#define ISDN_STAT_REDIR 272 /* Redir result */
170#define ISDN_STAT_PROT 273 /* protocol IO specific callback */
171#define ISDN_STAT_DISPLAY 274 /* deliver a received display message */
172#define ISDN_STAT_L1ERR 275 /* Signal Layer-1 Error */
173#define ISDN_STAT_FAXIND 276 /* FAX indications from HL-driver */
174#define ISDN_STAT_AUDIO 277 /* DTMF, DSP indications */
175#define ISDN_STAT_DISCH 278 /* Disable/Enable channel usage */
176
177/*
178 * Audio commands
179 */
180#define ISDN_AUDIO_SETDD 0 /* Set DTMF detection */
181#define ISDN_AUDIO_DTMF 1 /* Rx/Tx DTMF */
182
183/*
184 * Values for errcode field
185 */
186#define ISDN_STAT_L1ERR_SEND 1
187#define ISDN_STAT_L1ERR_RECV 2
188
189/*
190 * Values for feature-field of interface-struct.
191 */
192/* Layer 2 */
193#define ISDN_FEATURE_L2_X75I (0x0001 << ISDN_PROTO_L2_X75I)
194#define ISDN_FEATURE_L2_X75UI (0x0001 << ISDN_PROTO_L2_X75UI)
195#define ISDN_FEATURE_L2_X75BUI (0x0001 << ISDN_PROTO_L2_X75BUI)
196#define ISDN_FEATURE_L2_HDLC (0x0001 << ISDN_PROTO_L2_HDLC)
197#define ISDN_FEATURE_L2_TRANS (0x0001 << ISDN_PROTO_L2_TRANS)
198#define ISDN_FEATURE_L2_X25DTE (0x0001 << ISDN_PROTO_L2_X25DTE)
199#define ISDN_FEATURE_L2_X25DCE (0x0001 << ISDN_PROTO_L2_X25DCE)
200#define ISDN_FEATURE_L2_V11096 (0x0001 << ISDN_PROTO_L2_V11096)
201#define ISDN_FEATURE_L2_V11019 (0x0001 << ISDN_PROTO_L2_V11019)
202#define ISDN_FEATURE_L2_V11038 (0x0001 << ISDN_PROTO_L2_V11038)
203#define ISDN_FEATURE_L2_MODEM (0x0001 << ISDN_PROTO_L2_MODEM)
204#define ISDN_FEATURE_L2_FAX (0x0001 << ISDN_PROTO_L2_FAX)
205#define ISDN_FEATURE_L2_HDLC_56K (0x0001 << ISDN_PROTO_L2_HDLC_56K)
206
207#define ISDN_FEATURE_L2_MASK (0x0FFFF) /* Max. 16 protocols */
208#define ISDN_FEATURE_L2_SHIFT (0)
209
210/* Layer 3 */
211#define ISDN_FEATURE_L3_TRANS (0x10000 << ISDN_PROTO_L3_TRANS)
212#define ISDN_FEATURE_L3_TRANSDSP (0x10000 << ISDN_PROTO_L3_TRANSDSP)
213#define ISDN_FEATURE_L3_FCLASS2 (0x10000 << ISDN_PROTO_L3_FCLASS2)
214#define ISDN_FEATURE_L3_FCLASS1 (0x10000 << ISDN_PROTO_L3_FCLASS1)
215
216#define ISDN_FEATURE_L3_MASK (0x0FF0000) /* Max. 8 Protocols */
217#define ISDN_FEATURE_L3_SHIFT (16)
218
219/* Signaling */
220#define ISDN_FEATURE_P_UNKNOWN (0x1000000 << ISDN_PTYPE_UNKNOWN)
221#define ISDN_FEATURE_P_1TR6 (0x1000000 << ISDN_PTYPE_1TR6)
222#define ISDN_FEATURE_P_EURO (0x1000000 << ISDN_PTYPE_EURO)
223#define ISDN_FEATURE_P_NI1 (0x1000000 << ISDN_PTYPE_NI1)
224
225#define ISDN_FEATURE_P_MASK (0x0FF000000) /* Max. 8 Protocols */
226#define ISDN_FEATURE_P_SHIFT (24)
227
228typedef struct setup_parm {
229 unsigned char phone[32]; /* Remote Phone-Number */
230 unsigned char eazmsn[32]; /* Local EAZ or MSN */
231 unsigned char si1; /* Service Indicator 1 */
232 unsigned char si2; /* Service Indicator 2 */
233 unsigned char plan; /* Numbering plan */
234 unsigned char screen; /* Screening info */
235} setup_parm;
236
237
238#ifdef CONFIG_ISDN_TTY_FAX
239/* T.30 Fax G3 */
240
241#define FAXIDLEN 21
242
243typedef struct T30_s {
244 /* session parameters */
245 __u8 resolution;
246 __u8 rate;
247 __u8 width;
248 __u8 length;
249 __u8 compression;
250 __u8 ecm;
251 __u8 binary;
252 __u8 scantime;
253 __u8 id[FAXIDLEN];
254 /* additional parameters */
255 __u8 phase;
256 __u8 direction;
257 __u8 code;
258 __u8 badlin;
259 __u8 badmul;
260 __u8 bor;
261 __u8 fet;
262 __u8 pollid[FAXIDLEN];
263 __u8 cq;
264 __u8 cr;
265 __u8 ctcrty;
266 __u8 minsp;
267 __u8 phcto;
268 __u8 rel;
269 __u8 nbc;
270 /* remote station parameters */
271 __u8 r_resolution;
272 __u8 r_rate;
273 __u8 r_width;
274 __u8 r_length;
275 __u8 r_compression;
276 __u8 r_ecm;
277 __u8 r_binary;
278 __u8 r_scantime;
279 __u8 r_id[FAXIDLEN];
280 __u8 r_code;
281} __packed T30_s;
282
283#define ISDN_TTY_FAX_CONN_IN 0
284#define ISDN_TTY_FAX_CONN_OUT 1
285
286#define ISDN_TTY_FAX_FCON 0
287#define ISDN_TTY_FAX_DIS 1
288#define ISDN_TTY_FAX_FTT 2
289#define ISDN_TTY_FAX_MCF 3
290#define ISDN_TTY_FAX_DCS 4
291#define ISDN_TTY_FAX_TRAIN_OK 5
292#define ISDN_TTY_FAX_EOP 6
293#define ISDN_TTY_FAX_EOM 7
294#define ISDN_TTY_FAX_MPS 8
295#define ISDN_TTY_FAX_DTC 9
296#define ISDN_TTY_FAX_RID 10
297#define ISDN_TTY_FAX_HNG 11
298#define ISDN_TTY_FAX_DT 12
299#define ISDN_TTY_FAX_FCON_I 13
300#define ISDN_TTY_FAX_DR 14
301#define ISDN_TTY_FAX_ET 15
302#define ISDN_TTY_FAX_CFR 16
303#define ISDN_TTY_FAX_PTS 17
304#define ISDN_TTY_FAX_SENT 18
305
306#define ISDN_FAX_PHASE_IDLE 0
307#define ISDN_FAX_PHASE_A 1
308#define ISDN_FAX_PHASE_B 2
309#define ISDN_FAX_PHASE_C 3
310#define ISDN_FAX_PHASE_D 4
311#define ISDN_FAX_PHASE_E 5
312
313#endif /* TTY_FAX */
314
315#define ISDN_FAX_CLASS1_FAE 0
316#define ISDN_FAX_CLASS1_FTS 1
317#define ISDN_FAX_CLASS1_FRS 2
318#define ISDN_FAX_CLASS1_FTM 3
319#define ISDN_FAX_CLASS1_FRM 4
320#define ISDN_FAX_CLASS1_FTH 5
321#define ISDN_FAX_CLASS1_FRH 6
322#define ISDN_FAX_CLASS1_CTRL 7
323
324#define ISDN_FAX_CLASS1_OK 0
325#define ISDN_FAX_CLASS1_CONNECT 1
326#define ISDN_FAX_CLASS1_NOCARR 2
327#define ISDN_FAX_CLASS1_ERROR 3
328#define ISDN_FAX_CLASS1_FCERROR 4
329#define ISDN_FAX_CLASS1_QUERY 5
330
331typedef struct {
332 __u8 cmd;
333 __u8 subcmd;
334 __u8 para[50];
335} aux_s;
336
337#define AT_COMMAND 0
338#define AT_EQ_VALUE 1
339#define AT_QUERY 2
340#define AT_EQ_QUERY 3
341
342/* CAPI structs */
343
344/* this is compatible to the old union size */
345#define MAX_CAPI_PARA_LEN 50
346
347typedef struct {
348 /* Header */
349 __u16 Length;
350 __u16 ApplId;
351 __u8 Command;
352 __u8 Subcommand;
353 __u16 Messagenumber;
354
355 /* Parameter */
356 union {
357 __u32 Controller;
358 __u32 PLCI;
359 __u32 NCCI;
360 } adr;
361 __u8 para[MAX_CAPI_PARA_LEN];
362} capi_msg;
363
364/*
365 * Structure for exchanging above infos
366 *
367 */
368typedef struct {
369 int driver; /* Lowlevel-Driver-ID */
370 int command; /* Command or Status (see above) */
371 ulong arg; /* Additional Data */
372 union {
373 ulong errcode; /* Type of error with STAT_L1ERR */
374 int length; /* Amount of bytes sent with STAT_BSENT */
375 u_char num[50]; /* Additional Data */
376 setup_parm setup;/* For SETUP msg */
377 capi_msg cmsg; /* For CAPI like messages */
378 char display[85];/* display message data */
379 isdn_cmd_stat isdn_io; /* ISDN IO-parameter/result */
380 aux_s aux; /* for modem commands/indications */
381#ifdef CONFIG_ISDN_TTY_FAX
382 T30_s *fax; /* Pointer to ttys fax struct */
383#endif
384 ulong userdata; /* User Data */
385 } parm;
386} isdn_ctrl;
387
388#define dss1_io isdn_io
389#define ni1_io isdn_io
390
391/*
392 * The interface-struct itself (initialized at load-time of lowlevel-driver)
393 *
394 * See Documentation/isdn/INTERFACE for a description, how the communication
395 * between the ISDN subsystem and its drivers is done.
396 *
397 */
398typedef struct {
399 struct module *owner;
400
401 /* Number of channels supported by this driver
402 */
403 int channels;
404
405 /*
406 * Maximum Size of transmit/receive-buffer this driver supports.
407 */
408 int maxbufsize;
409
410 /* Feature-Flags for this driver.
411 * See defines ISDN_FEATURE_... for Values
412 */
413 unsigned long features;
414
415 /*
416 * Needed for calculating
417 * dev->hard_header_len = linklayer header + hl_hdrlen;
418 * Drivers, not supporting sk_buff's should set this to 0.
419 */
420 unsigned short hl_hdrlen;
421
422 /*
423 * Receive-Callback using sk_buff's
424 * Parameters:
425 * int Driver-ID
426 * int local channel-number (0 ...)
427 * struct sk_buff *skb received Data
428 */
429 void (*rcvcallb_skb)(int, int, struct sk_buff *);
430
431 /* Status-Callback
432 * Parameters:
433 * isdn_ctrl*
434 * driver = Driver ID.
435 * command = One of above ISDN_STAT_... constants.
436 * arg = depending on status-type.
437 * num = depending on status-type.
438 */
439 int (*statcallb)(isdn_ctrl*);
440
441 /* Send command
442 * Parameters:
443 * isdn_ctrl*
444 * driver = Driver ID.
445 * command = One of above ISDN_CMD_... constants.
446 * arg = depending on command.
447 * num = depending on command.
448 */
449 int (*command)(isdn_ctrl*);
450
451 /*
452 * Send data using sk_buff's
453 * Parameters:
454 * int driverId
455 * int local channel-number (0...)
456 * int Flag: Need ACK for this packet.
457 * struct sk_buff *skb Data to send
458 */
459 int (*writebuf_skb) (int, int, int, struct sk_buff *);
460
461 /* Send raw D-Channel-Commands
462 * Parameters:
463 * u_char pointer data
464 * int length of data
465 * int driverId
466 * int local channel-number (0 ...)
467 */
468 int (*writecmd)(const u_char __user *, int, int, int);
469
470 /* Read raw Status replies
471 * u_char pointer data (volatile)
472 * int length of buffer
473 * int driverId
474 * int local channel-number (0 ...)
475 */
476 int (*readstat)(u_char __user *, int, int, int);
477
478 char id[20];
479} isdn_if;
480
481/*
482 * Function which must be called by lowlevel-driver at loadtime with
483 * the following fields of above struct set:
484 *
485 * channels Number of channels that will be supported.
486 * hl_hdrlen Space to preserve in sk_buff's when sending. Drivers, not
487 * supporting sk_buff's should set this to 0.
488 * command Address of Command-Handler.
489 * features Bitwise coded Features of this driver. (use ISDN_FEATURE_...)
490 * writebuf_skb Address of Skbuff-Send-Handler.
491 * writecmd " " D-Channel " which accepts raw D-Ch-Commands.
492 * readstat " " D-Channel " which delivers raw Status-Data.
493 *
494 * The linklevel-driver fills the following fields:
495 *
496 * channels Driver-ID assigned to this driver. (Must be used on all
497 * subsequent callbacks.
498 * rcvcallb_skb Address of handler for received Skbuff's.
499 * statcallb " " " for status-changes.
500 *
501 */
502extern int register_isdn(isdn_if*);
503#include <linux/uaccess.h>
504
505#endif /* __ISDNIF_H__ */
diff --git a/include/linux/wanrouter.h b/include/linux/wanrouter.h
deleted file mode 100644
index f6358558f9f5..000000000000
--- a/include/linux/wanrouter.h
+++ /dev/null
@@ -1,11 +0,0 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * wanrouter.h Legacy declarations kept around until X25 is removed
4 */
5
6#ifndef _ROUTER_H
7#define _ROUTER_H
8
9#include <uapi/linux/wanrouter.h>
10
11#endif /* _ROUTER_H */
diff --git a/include/uapi/linux/isdn.h b/include/uapi/linux/isdn.h
deleted file mode 100644
index f371fd52ed75..000000000000
--- a/include/uapi/linux/isdn.h
+++ /dev/null
@@ -1,144 +0,0 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
2/* $Id: isdn.h,v 1.125.2.3 2004/02/10 01:07:14 keil Exp $
3 *
4 * Main header for the Linux ISDN subsystem (linklevel).
5 *
6 * Copyright 1994,95,96 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#ifndef _UAPI__ISDN_H__
16#define _UAPI__ISDN_H__
17
18#include <linux/ioctl.h>
19#include <linux/tty.h>
20
21#define ISDN_MAX_DRIVERS 32
22#define ISDN_MAX_CHANNELS 64
23
24/* New ioctl-codes */
25#define IIOCNETAIF _IO('I',1)
26#define IIOCNETDIF _IO('I',2)
27#define IIOCNETSCF _IO('I',3)
28#define IIOCNETGCF _IO('I',4)
29#define IIOCNETANM _IO('I',5)
30#define IIOCNETDNM _IO('I',6)
31#define IIOCNETGNM _IO('I',7)
32#define IIOCGETSET _IO('I',8) /* no longer supported */
33#define IIOCSETSET _IO('I',9) /* no longer supported */
34#define IIOCSETVER _IO('I',10)
35#define IIOCNETHUP _IO('I',11)
36#define IIOCSETGST _IO('I',12)
37#define IIOCSETBRJ _IO('I',13)
38#define IIOCSIGPRF _IO('I',14)
39#define IIOCGETPRF _IO('I',15)
40#define IIOCSETPRF _IO('I',16)
41#define IIOCGETMAP _IO('I',17)
42#define IIOCSETMAP _IO('I',18)
43#define IIOCNETASL _IO('I',19)
44#define IIOCNETDIL _IO('I',20)
45#define IIOCGETCPS _IO('I',21)
46#define IIOCGETDVR _IO('I',22)
47#define IIOCNETLCR _IO('I',23) /* dwabc ioctl for LCR from isdnlog */
48#define IIOCNETDWRSET _IO('I',24) /* dwabc ioctl to reset abc-values to default on a net-interface */
49
50#define IIOCNETALN _IO('I',32)
51#define IIOCNETDLN _IO('I',33)
52
53#define IIOCNETGPN _IO('I',34)
54
55#define IIOCDBGVAR _IO('I',127)
56
57#define IIOCDRVCTL _IO('I',128)
58
59/* cisco hdlck device private ioctls */
60#define SIOCGKEEPPERIOD (SIOCDEVPRIVATE + 0)
61#define SIOCSKEEPPERIOD (SIOCDEVPRIVATE + 1)
62#define SIOCGDEBSERINT (SIOCDEVPRIVATE + 2)
63#define SIOCSDEBSERINT (SIOCDEVPRIVATE + 3)
64
65/* Packet encapsulations for net-interfaces */
66#define ISDN_NET_ENCAP_ETHER 0
67#define ISDN_NET_ENCAP_RAWIP 1
68#define ISDN_NET_ENCAP_IPTYP 2
69#define ISDN_NET_ENCAP_CISCOHDLC 3 /* Without SLARP and keepalive */
70#define ISDN_NET_ENCAP_SYNCPPP 4
71#define ISDN_NET_ENCAP_UIHDLC 5
72#define ISDN_NET_ENCAP_CISCOHDLCK 6 /* With SLARP and keepalive */
73#define ISDN_NET_ENCAP_X25IFACE 7 /* Documentation/networking/x25-iface.txt */
74#define ISDN_NET_ENCAP_MAX_ENCAP ISDN_NET_ENCAP_X25IFACE
75
76/* Facility which currently uses an ISDN-channel */
77#define ISDN_USAGE_NONE 0
78#define ISDN_USAGE_RAW 1
79#define ISDN_USAGE_MODEM 2
80#define ISDN_USAGE_NET 3
81#define ISDN_USAGE_VOICE 4
82#define ISDN_USAGE_FAX 5
83#define ISDN_USAGE_MASK 7 /* Mask to get plain usage */
84#define ISDN_USAGE_DISABLED 32 /* This bit is set, if channel is disabled */
85#define ISDN_USAGE_EXCLUSIVE 64 /* This bit is set, if channel is exclusive */
86#define ISDN_USAGE_OUTGOING 128 /* This bit is set, if channel is outgoing */
87
88#define ISDN_MODEM_NUMREG 24 /* Number of Modem-Registers */
89#define ISDN_LMSNLEN 255 /* Length of tty's Listen-MSN string */
90#define ISDN_CMSGLEN 50 /* Length of CONNECT-Message to add for Modem */
91
92#define ISDN_MSNLEN 32
93#define NET_DV 0x06 /* Data version for isdn_net_ioctl_cfg */
94#define TTY_DV 0x06 /* Data version for iprofd etc. */
95
96#define INF_DV 0x01 /* Data version for /dev/isdninfo */
97
98typedef struct {
99 char drvid[25];
100 unsigned long arg;
101} isdn_ioctl_struct;
102
103typedef struct {
104 char name[10];
105 char phone[ISDN_MSNLEN];
106 int outgoing;
107} isdn_net_ioctl_phone;
108
109typedef struct {
110 char name[10]; /* Name of interface */
111 char master[10]; /* Name of Master for Bundling */
112 char slave[10]; /* Name of Slave for Bundling */
113 char eaz[256]; /* EAZ/MSN */
114 char drvid[25]; /* DriverId for Bindings */
115 int onhtime; /* Hangup-Timeout */
116 int charge; /* Charge-Units */
117 int l2_proto; /* Layer-2 protocol */
118 int l3_proto; /* Layer-3 protocol */
119 int p_encap; /* Encapsulation */
120 int exclusive; /* Channel, if bound exclusive */
121 int dialmax; /* Dial Retry-Counter */
122 int slavedelay; /* Delay until slave starts up */
123 int cbdelay; /* Delay before Callback */
124 int chargehup; /* Flag: Charge-Hangup */
125 int ihup; /* Flag: Hangup-Timeout on incoming line */
126 int secure; /* Flag: Secure */
127 int callback; /* Flag: Callback */
128 int cbhup; /* Flag: Reject Call before Callback */
129 int pppbind; /* ippp device for bindings */
130 int chargeint; /* Use fixed charge interval length */
131 int triggercps; /* BogoCPS needed for triggering slave */
132 int dialtimeout; /* Dial-Timeout */
133 int dialwait; /* Time to wait after failed dial */
134 int dialmode; /* Flag: off / on / auto */
135} isdn_net_ioctl_cfg;
136
137#define ISDN_NET_DIALMODE_MASK 0xC0 /* bits for status */
138#define ISDN_NET_DM_OFF 0x00 /* this interface is stopped */
139#define ISDN_NET_DM_MANUAL 0x40 /* this interface is on (manual) */
140#define ISDN_NET_DM_AUTO 0x80 /* this interface is autodial */
141#define ISDN_NET_DIALMODE(x) ((&(x))->flags & ISDN_NET_DIALMODE_MASK)
142
143
144#endif /* _UAPI__ISDN_H__ */
diff --git a/include/uapi/linux/isdn_divertif.h b/include/uapi/linux/isdn_divertif.h
deleted file mode 100644
index 0a17bb1bcb1b..000000000000
--- a/include/uapi/linux/isdn_divertif.h
+++ /dev/null
@@ -1,31 +0,0 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
2/* $Id: isdn_divertif.h,v 1.4.6.1 2001/09/23 22:25:05 kai Exp $
3 *
4 * Header for the diversion supplementary interface for i4l.
5 *
6 * Author Werner Cornelius (werner@titro.de)
7 * Copyright by Werner Cornelius (werner@titro.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#ifndef _UAPI_LINUX_ISDN_DIVERTIF_H
15#define _UAPI_LINUX_ISDN_DIVERTIF_H
16
17/***********************************************************/
18/* magic value is also used to control version information */
19/***********************************************************/
20#define DIVERT_IF_MAGIC 0x25873401
21#define DIVERT_CMD_REG 0x00 /* register command */
22#define DIVERT_CMD_REL 0x01 /* release command */
23#define DIVERT_NO_ERR 0x00 /* return value no error */
24#define DIVERT_CMD_ERR 0x01 /* invalid cmd */
25#define DIVERT_VER_ERR 0x02 /* magic/version invalid */
26#define DIVERT_REG_ERR 0x03 /* module already registered */
27#define DIVERT_REL_ERR 0x04 /* module not registered */
28#define DIVERT_REG_NAME isdn_register_divert
29
30
31#endif /* _UAPI_LINUX_ISDN_DIVERTIF_H */
diff --git a/include/uapi/linux/isdn_ppp.h b/include/uapi/linux/isdn_ppp.h
deleted file mode 100644
index 0bdc4efaacb2..000000000000
--- a/include/uapi/linux/isdn_ppp.h
+++ /dev/null
@@ -1,68 +0,0 @@
1/* SPDX-License-Identifier: GPL-1.0+ WITH Linux-syscall-note */
2/* Linux ISDN subsystem, sync PPP, interface to ipppd
3 *
4 * Copyright 1994-1999 by Fritz Elfert (fritz@isdn4linux.de)
5 * Copyright 1995,96 Thinking Objects Software GmbH Wuerzburg
6 * Copyright 1995,96 by Michael Hipp (Michael.Hipp@student.uni-tuebingen.de)
7 * Copyright 2000-2002 by Kai Germaschewski (kai@germaschewski.name)
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#ifndef _UAPI_LINUX_ISDN_PPP_H
15#define _UAPI_LINUX_ISDN_PPP_H
16
17#define CALLTYPE_INCOMING 0x1
18#define CALLTYPE_OUTGOING 0x2
19#define CALLTYPE_CALLBACK 0x4
20
21#define IPPP_VERSION "2.2.0"
22
23struct pppcallinfo
24{
25 int calltype;
26 unsigned char local_num[64];
27 unsigned char remote_num[64];
28 int charge_units;
29};
30
31#define PPPIOCGCALLINFO _IOWR('t',128,struct pppcallinfo)
32#define PPPIOCBUNDLE _IOW('t',129,int)
33#define PPPIOCGMPFLAGS _IOR('t',130,int)
34#define PPPIOCSMPFLAGS _IOW('t',131,int)
35#define PPPIOCSMPMTU _IOW('t',132,int)
36#define PPPIOCSMPMRU _IOW('t',133,int)
37#define PPPIOCGCOMPRESSORS _IOR('t',134,unsigned long [8])
38#define PPPIOCSCOMPRESSOR _IOW('t',135,int)
39#define PPPIOCGIFNAME _IOR('t',136, char [IFNAMSIZ] )
40
41
42#define SC_MP_PROT 0x00000200
43#define SC_REJ_MP_PROT 0x00000400
44#define SC_OUT_SHORT_SEQ 0x00000800
45#define SC_IN_SHORT_SEQ 0x00004000
46
47#define SC_DECOMP_ON 0x01
48#define SC_COMP_ON 0x02
49#define SC_DECOMP_DISCARD 0x04
50#define SC_COMP_DISCARD 0x08
51#define SC_LINK_DECOMP_ON 0x10
52#define SC_LINK_COMP_ON 0x20
53#define SC_LINK_DECOMP_DISCARD 0x40
54#define SC_LINK_COMP_DISCARD 0x80
55
56#define ISDN_PPP_COMP_MAX_OPTIONS 16
57
58#define IPPP_COMP_FLAG_XMIT 0x1
59#define IPPP_COMP_FLAG_LINK 0x2
60
61struct isdn_ppp_comp_data {
62 int num;
63 unsigned char options[ISDN_PPP_COMP_MAX_OPTIONS];
64 int optlen;
65 int flags;
66};
67
68#endif /* _UAPI_LINUX_ISDN_PPP_H */
diff --git a/include/uapi/linux/isdnif.h b/include/uapi/linux/isdnif.h
deleted file mode 100644
index 611a69196738..000000000000
--- a/include/uapi/linux/isdnif.h
+++ /dev/null
@@ -1,57 +0,0 @@
1/* SPDX-License-Identifier: GPL-1.0+ WITH Linux-syscall-note */
2/* $Id: isdnif.h,v 1.43.2.2 2004/01/12 23:08:35 keil Exp $
3 *
4 * Linux ISDN subsystem
5 * Definition of the interface between the subsystem and its low-level drivers.
6 *
7 * Copyright 1994,95,96 by Fritz Elfert (fritz@isdn4linux.de)
8 * Copyright 1995,96 Thinking Objects Software GmbH Wuerzburg
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#ifndef _UAPI__ISDNIF_H__
16#define _UAPI__ISDNIF_H__
17
18
19/*
20 * Values for general protocol-selection
21 */
22#define ISDN_PTYPE_UNKNOWN 0 /* Protocol undefined */
23#define ISDN_PTYPE_1TR6 1 /* german 1TR6-protocol */
24#define ISDN_PTYPE_EURO 2 /* EDSS1-protocol */
25#define ISDN_PTYPE_LEASED 3 /* for leased lines */
26#define ISDN_PTYPE_NI1 4 /* US NI-1 protocol */
27#define ISDN_PTYPE_MAX 7 /* Max. 8 Protocols */
28
29/*
30 * Values for Layer-2-protocol-selection
31 */
32#define ISDN_PROTO_L2_X75I 0 /* X75/LAPB with I-Frames */
33#define ISDN_PROTO_L2_X75UI 1 /* X75/LAPB with UI-Frames */
34#define ISDN_PROTO_L2_X75BUI 2 /* X75/LAPB with UI-Frames */
35#define ISDN_PROTO_L2_HDLC 3 /* HDLC */
36#define ISDN_PROTO_L2_TRANS 4 /* Transparent (Voice) */
37#define ISDN_PROTO_L2_X25DTE 5 /* X25/LAPB DTE mode */
38#define ISDN_PROTO_L2_X25DCE 6 /* X25/LAPB DCE mode */
39#define ISDN_PROTO_L2_V11096 7 /* V.110 bitrate adaption 9600 Baud */
40#define ISDN_PROTO_L2_V11019 8 /* V.110 bitrate adaption 19200 Baud */
41#define ISDN_PROTO_L2_V11038 9 /* V.110 bitrate adaption 38400 Baud */
42#define ISDN_PROTO_L2_MODEM 10 /* Analog Modem on Board */
43#define ISDN_PROTO_L2_FAX 11 /* Fax Group 2/3 */
44#define ISDN_PROTO_L2_HDLC_56K 12 /* HDLC 56k */
45#define ISDN_PROTO_L2_MAX 15 /* Max. 16 Protocols */
46
47/*
48 * Values for Layer-3-protocol-selection
49 */
50#define ISDN_PROTO_L3_TRANS 0 /* Transparent */
51#define ISDN_PROTO_L3_TRANSDSP 1 /* Transparent with DSP */
52#define ISDN_PROTO_L3_FCLASS2 2 /* Fax Group 2/3 CLASS 2 */
53#define ISDN_PROTO_L3_FCLASS1 3 /* Fax Group 2/3 CLASS 1 */
54#define ISDN_PROTO_L3_MAX 7 /* Max. 8 Protocols */
55
56
57#endif /* _UAPI__ISDNIF_H__ */
diff --git a/include/uapi/linux/wanrouter.h b/include/uapi/linux/wanrouter.h
deleted file mode 100644
index 2f1216d00caa..000000000000
--- a/include/uapi/linux/wanrouter.h
+++ /dev/null
@@ -1,18 +0,0 @@
1/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
2/*
3 * wanrouter.h Legacy declarations kept around until X25 is removed
4 */
5
6#ifndef _UAPI_ROUTER_H
7#define _UAPI_ROUTER_H
8
9/* 'state' defines */
10enum wan_states
11{
12 WAN_UNCONFIGURED, /* link/channel is not configured */
13 WAN_DISCONNECTED, /* link/channel is disconnected */
14 WAN_CONNECTING, /* connection is in progress */
15 WAN_CONNECTED /* link/channel is operational */
16};
17
18#endif /* _UAPI_ROUTER_H */