Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/isdn/capi/capi.c
17498 views
1
/* $Id: capi.c,v 1.1.2.7 2004/04/28 09:48:59 armin Exp $
2
*
3
* CAPI 2.0 Interface for Linux
4
*
5
* Copyright 1996 by Carsten Paeth <[email protected]>
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/errno.h>
14
#include <linux/kernel.h>
15
#include <linux/major.h>
16
#include <linux/sched.h>
17
#include <linux/slab.h>
18
#include <linux/fcntl.h>
19
#include <linux/fs.h>
20
#include <linux/signal.h>
21
#include <linux/mutex.h>
22
#include <linux/mm.h>
23
#include <linux/timer.h>
24
#include <linux/wait.h>
25
#include <linux/tty.h>
26
#include <linux/netdevice.h>
27
#include <linux/ppp_defs.h>
28
#include <linux/if_ppp.h>
29
#include <linux/skbuff.h>
30
#include <linux/proc_fs.h>
31
#include <linux/seq_file.h>
32
#include <linux/poll.h>
33
#include <linux/capi.h>
34
#include <linux/kernelcapi.h>
35
#include <linux/init.h>
36
#include <linux/device.h>
37
#include <linux/moduleparam.h>
38
#include <linux/isdn/capiutil.h>
39
#include <linux/isdn/capicmd.h>
40
41
MODULE_DESCRIPTION("CAPI4Linux: Userspace /dev/capi20 interface");
42
MODULE_AUTHOR("Carsten Paeth");
43
MODULE_LICENSE("GPL");
44
45
/* -------- driver information -------------------------------------- */
46
47
static DEFINE_MUTEX(capi_mutex);
48
static struct class *capi_class;
49
static int capi_major = 68; /* allocated */
50
51
module_param_named(major, capi_major, uint, 0);
52
53
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
54
#define CAPINC_NR_PORTS 32
55
#define CAPINC_MAX_PORTS 256
56
57
static int capi_ttyminors = CAPINC_NR_PORTS;
58
59
module_param_named(ttyminors, capi_ttyminors, uint, 0);
60
#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
61
62
/* -------- defines ------------------------------------------------- */
63
64
#define CAPINC_MAX_RECVQUEUE 10
65
#define CAPINC_MAX_SENDQUEUE 10
66
#define CAPI_MAX_BLKSIZE 2048
67
68
/* -------- data structures ----------------------------------------- */
69
70
struct capidev;
71
struct capincci;
72
struct capiminor;
73
74
struct ackqueue_entry {
75
struct list_head list;
76
u16 datahandle;
77
};
78
79
struct capiminor {
80
struct kref kref;
81
82
unsigned int minor;
83
84
struct capi20_appl *ap;
85
u32 ncci;
86
atomic_t datahandle;
87
atomic_t msgid;
88
89
struct tty_port port;
90
int ttyinstop;
91
int ttyoutstop;
92
93
struct sk_buff_head inqueue;
94
95
struct sk_buff_head outqueue;
96
int outbytes;
97
struct sk_buff *outskb;
98
spinlock_t outlock;
99
100
/* transmit path */
101
struct list_head ackqueue;
102
int nack;
103
spinlock_t ackqlock;
104
};
105
106
struct capincci {
107
struct list_head list;
108
u32 ncci;
109
struct capidev *cdev;
110
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
111
struct capiminor *minorp;
112
#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
113
};
114
115
struct capidev {
116
struct list_head list;
117
struct capi20_appl ap;
118
u16 errcode;
119
unsigned userflags;
120
121
struct sk_buff_head recvqueue;
122
wait_queue_head_t recvwait;
123
124
struct list_head nccis;
125
126
struct mutex lock;
127
};
128
129
/* -------- global variables ---------------------------------------- */
130
131
static DEFINE_MUTEX(capidev_list_lock);
132
static LIST_HEAD(capidev_list);
133
134
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
135
136
static DEFINE_SPINLOCK(capiminors_lock);
137
static struct capiminor **capiminors;
138
139
static struct tty_driver *capinc_tty_driver;
140
141
/* -------- datahandles --------------------------------------------- */
142
143
static int capiminor_add_ack(struct capiminor *mp, u16 datahandle)
144
{
145
struct ackqueue_entry *n;
146
147
n = kmalloc(sizeof(*n), GFP_ATOMIC);
148
if (unlikely(!n)) {
149
printk(KERN_ERR "capi: alloc datahandle failed\n");
150
return -1;
151
}
152
n->datahandle = datahandle;
153
INIT_LIST_HEAD(&n->list);
154
spin_lock_bh(&mp->ackqlock);
155
list_add_tail(&n->list, &mp->ackqueue);
156
mp->nack++;
157
spin_unlock_bh(&mp->ackqlock);
158
return 0;
159
}
160
161
static int capiminor_del_ack(struct capiminor *mp, u16 datahandle)
162
{
163
struct ackqueue_entry *p, *tmp;
164
165
spin_lock_bh(&mp->ackqlock);
166
list_for_each_entry_safe(p, tmp, &mp->ackqueue, list) {
167
if (p->datahandle == datahandle) {
168
list_del(&p->list);
169
mp->nack--;
170
spin_unlock_bh(&mp->ackqlock);
171
kfree(p);
172
return 0;
173
}
174
}
175
spin_unlock_bh(&mp->ackqlock);
176
return -1;
177
}
178
179
static void capiminor_del_all_ack(struct capiminor *mp)
180
{
181
struct ackqueue_entry *p, *tmp;
182
183
list_for_each_entry_safe(p, tmp, &mp->ackqueue, list) {
184
list_del(&p->list);
185
kfree(p);
186
mp->nack--;
187
}
188
}
189
190
191
/* -------- struct capiminor ---------------------------------------- */
192
193
static const struct tty_port_operations capiminor_port_ops; /* we have none */
194
195
static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci)
196
{
197
struct capiminor *mp;
198
struct device *dev;
199
unsigned int minor;
200
201
mp = kzalloc(sizeof(*mp), GFP_KERNEL);
202
if (!mp) {
203
printk(KERN_ERR "capi: can't alloc capiminor\n");
204
return NULL;
205
}
206
207
kref_init(&mp->kref);
208
209
mp->ap = ap;
210
mp->ncci = ncci;
211
INIT_LIST_HEAD(&mp->ackqueue);
212
spin_lock_init(&mp->ackqlock);
213
214
skb_queue_head_init(&mp->inqueue);
215
skb_queue_head_init(&mp->outqueue);
216
spin_lock_init(&mp->outlock);
217
218
tty_port_init(&mp->port);
219
mp->port.ops = &capiminor_port_ops;
220
221
/* Allocate the least unused minor number. */
222
spin_lock(&capiminors_lock);
223
for (minor = 0; minor < capi_ttyminors; minor++)
224
if (!capiminors[minor]) {
225
capiminors[minor] = mp;
226
break;
227
}
228
spin_unlock(&capiminors_lock);
229
230
if (minor == capi_ttyminors) {
231
printk(KERN_NOTICE "capi: out of minors\n");
232
goto err_out1;
233
}
234
235
mp->minor = minor;
236
237
dev = tty_register_device(capinc_tty_driver, minor, NULL);
238
if (IS_ERR(dev))
239
goto err_out2;
240
241
return mp;
242
243
err_out2:
244
spin_lock(&capiminors_lock);
245
capiminors[minor] = NULL;
246
spin_unlock(&capiminors_lock);
247
248
err_out1:
249
kfree(mp);
250
return NULL;
251
}
252
253
static void capiminor_destroy(struct kref *kref)
254
{
255
struct capiminor *mp = container_of(kref, struct capiminor, kref);
256
257
kfree_skb(mp->outskb);
258
skb_queue_purge(&mp->inqueue);
259
skb_queue_purge(&mp->outqueue);
260
capiminor_del_all_ack(mp);
261
kfree(mp);
262
}
263
264
static struct capiminor *capiminor_get(unsigned int minor)
265
{
266
struct capiminor *mp;
267
268
spin_lock(&capiminors_lock);
269
mp = capiminors[minor];
270
if (mp)
271
kref_get(&mp->kref);
272
spin_unlock(&capiminors_lock);
273
274
return mp;
275
}
276
277
static inline void capiminor_put(struct capiminor *mp)
278
{
279
kref_put(&mp->kref, capiminor_destroy);
280
}
281
282
static void capiminor_free(struct capiminor *mp)
283
{
284
tty_unregister_device(capinc_tty_driver, mp->minor);
285
286
spin_lock(&capiminors_lock);
287
capiminors[mp->minor] = NULL;
288
spin_unlock(&capiminors_lock);
289
290
capiminor_put(mp);
291
}
292
293
/* -------- struct capincci ----------------------------------------- */
294
295
static void capincci_alloc_minor(struct capidev *cdev, struct capincci *np)
296
{
297
if (cdev->userflags & CAPIFLAG_HIGHJACKING)
298
np->minorp = capiminor_alloc(&cdev->ap, np->ncci);
299
}
300
301
static void capincci_free_minor(struct capincci *np)
302
{
303
struct capiminor *mp = np->minorp;
304
struct tty_struct *tty;
305
306
if (mp) {
307
tty = tty_port_tty_get(&mp->port);
308
if (tty) {
309
tty_vhangup(tty);
310
tty_kref_put(tty);
311
}
312
313
capiminor_free(mp);
314
}
315
}
316
317
static inline unsigned int capincci_minor_opencount(struct capincci *np)
318
{
319
struct capiminor *mp = np->minorp;
320
unsigned int count = 0;
321
struct tty_struct *tty;
322
323
if (mp) {
324
tty = tty_port_tty_get(&mp->port);
325
if (tty) {
326
count = tty->count;
327
tty_kref_put(tty);
328
}
329
}
330
return count;
331
}
332
333
#else /* !CONFIG_ISDN_CAPI_MIDDLEWARE */
334
335
static inline void
336
capincci_alloc_minor(struct capidev *cdev, struct capincci *np) { }
337
static inline void capincci_free_minor(struct capincci *np) { }
338
339
static inline unsigned int capincci_minor_opencount(struct capincci *np)
340
{
341
return 0;
342
}
343
344
#endif /* !CONFIG_ISDN_CAPI_MIDDLEWARE */
345
346
static struct capincci *capincci_alloc(struct capidev *cdev, u32 ncci)
347
{
348
struct capincci *np;
349
350
np = kzalloc(sizeof(*np), GFP_KERNEL);
351
if (!np)
352
return NULL;
353
np->ncci = ncci;
354
np->cdev = cdev;
355
356
capincci_alloc_minor(cdev, np);
357
358
list_add_tail(&np->list, &cdev->nccis);
359
360
return np;
361
}
362
363
static void capincci_free(struct capidev *cdev, u32 ncci)
364
{
365
struct capincci *np, *tmp;
366
367
list_for_each_entry_safe(np, tmp, &cdev->nccis, list)
368
if (ncci == 0xffffffff || np->ncci == ncci) {
369
capincci_free_minor(np);
370
list_del(&np->list);
371
kfree(np);
372
}
373
}
374
375
static struct capincci *capincci_find(struct capidev *cdev, u32 ncci)
376
{
377
struct capincci *np;
378
379
list_for_each_entry(np, &cdev->nccis, list)
380
if (np->ncci == ncci)
381
return np;
382
return NULL;
383
}
384
385
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
386
/* -------- handle data queue --------------------------------------- */
387
388
static struct sk_buff *
389
gen_data_b3_resp_for(struct capiminor *mp, struct sk_buff *skb)
390
{
391
struct sk_buff *nskb;
392
nskb = alloc_skb(CAPI_DATA_B3_RESP_LEN, GFP_KERNEL);
393
if (nskb) {
394
u16 datahandle = CAPIMSG_U16(skb->data,CAPIMSG_BASELEN+4+4+2);
395
unsigned char *s = skb_put(nskb, CAPI_DATA_B3_RESP_LEN);
396
capimsg_setu16(s, 0, CAPI_DATA_B3_RESP_LEN);
397
capimsg_setu16(s, 2, mp->ap->applid);
398
capimsg_setu8 (s, 4, CAPI_DATA_B3);
399
capimsg_setu8 (s, 5, CAPI_RESP);
400
capimsg_setu16(s, 6, atomic_inc_return(&mp->msgid));
401
capimsg_setu32(s, 8, mp->ncci);
402
capimsg_setu16(s, 12, datahandle);
403
}
404
return nskb;
405
}
406
407
static int handle_recv_skb(struct capiminor *mp, struct sk_buff *skb)
408
{
409
unsigned int datalen = skb->len - CAPIMSG_LEN(skb->data);
410
struct tty_struct *tty;
411
struct sk_buff *nskb;
412
u16 errcode, datahandle;
413
struct tty_ldisc *ld;
414
int ret = -1;
415
416
tty = tty_port_tty_get(&mp->port);
417
if (!tty) {
418
pr_debug("capi: currently no receiver\n");
419
return -1;
420
}
421
422
ld = tty_ldisc_ref(tty);
423
if (!ld) {
424
/* fatal error, do not requeue */
425
ret = 0;
426
kfree_skb(skb);
427
goto deref_tty;
428
}
429
430
if (ld->ops->receive_buf == NULL) {
431
pr_debug("capi: ldisc has no receive_buf function\n");
432
/* fatal error, do not requeue */
433
goto free_skb;
434
}
435
if (mp->ttyinstop) {
436
pr_debug("capi: recv tty throttled\n");
437
goto deref_ldisc;
438
}
439
440
if (tty->receive_room < datalen) {
441
pr_debug("capi: no room in tty\n");
442
goto deref_ldisc;
443
}
444
445
nskb = gen_data_b3_resp_for(mp, skb);
446
if (!nskb) {
447
printk(KERN_ERR "capi: gen_data_b3_resp failed\n");
448
goto deref_ldisc;
449
}
450
451
datahandle = CAPIMSG_U16(skb->data, CAPIMSG_BASELEN + 4);
452
453
errcode = capi20_put_message(mp->ap, nskb);
454
455
if (errcode == CAPI_NOERROR) {
456
skb_pull(skb, CAPIMSG_LEN(skb->data));
457
pr_debug("capi: DATA_B3_RESP %u len=%d => ldisc\n",
458
datahandle, skb->len);
459
ld->ops->receive_buf(tty, skb->data, NULL, skb->len);
460
} else {
461
printk(KERN_ERR "capi: send DATA_B3_RESP failed=%x\n",
462
errcode);
463
kfree_skb(nskb);
464
465
if (errcode == CAPI_SENDQUEUEFULL)
466
goto deref_ldisc;
467
}
468
469
free_skb:
470
ret = 0;
471
kfree_skb(skb);
472
473
deref_ldisc:
474
tty_ldisc_deref(ld);
475
476
deref_tty:
477
tty_kref_put(tty);
478
return ret;
479
}
480
481
static void handle_minor_recv(struct capiminor *mp)
482
{
483
struct sk_buff *skb;
484
485
while ((skb = skb_dequeue(&mp->inqueue)) != NULL)
486
if (handle_recv_skb(mp, skb) < 0) {
487
skb_queue_head(&mp->inqueue, skb);
488
return;
489
}
490
}
491
492
static void handle_minor_send(struct capiminor *mp)
493
{
494
struct tty_struct *tty;
495
struct sk_buff *skb;
496
u16 len;
497
u16 errcode;
498
u16 datahandle;
499
500
tty = tty_port_tty_get(&mp->port);
501
if (!tty)
502
return;
503
504
if (mp->ttyoutstop) {
505
pr_debug("capi: send: tty stopped\n");
506
tty_kref_put(tty);
507
return;
508
}
509
510
while (1) {
511
spin_lock_bh(&mp->outlock);
512
skb = __skb_dequeue(&mp->outqueue);
513
if (!skb) {
514
spin_unlock_bh(&mp->outlock);
515
break;
516
}
517
len = (u16)skb->len;
518
mp->outbytes -= len;
519
spin_unlock_bh(&mp->outlock);
520
521
datahandle = atomic_inc_return(&mp->datahandle);
522
skb_push(skb, CAPI_DATA_B3_REQ_LEN);
523
memset(skb->data, 0, CAPI_DATA_B3_REQ_LEN);
524
capimsg_setu16(skb->data, 0, CAPI_DATA_B3_REQ_LEN);
525
capimsg_setu16(skb->data, 2, mp->ap->applid);
526
capimsg_setu8 (skb->data, 4, CAPI_DATA_B3);
527
capimsg_setu8 (skb->data, 5, CAPI_REQ);
528
capimsg_setu16(skb->data, 6, atomic_inc_return(&mp->msgid));
529
capimsg_setu32(skb->data, 8, mp->ncci); /* NCCI */
530
capimsg_setu32(skb->data, 12, (u32)(long)skb->data);/* Data32 */
531
capimsg_setu16(skb->data, 16, len); /* Data length */
532
capimsg_setu16(skb->data, 18, datahandle);
533
capimsg_setu16(skb->data, 20, 0); /* Flags */
534
535
if (capiminor_add_ack(mp, datahandle) < 0) {
536
skb_pull(skb, CAPI_DATA_B3_REQ_LEN);
537
538
spin_lock_bh(&mp->outlock);
539
__skb_queue_head(&mp->outqueue, skb);
540
mp->outbytes += len;
541
spin_unlock_bh(&mp->outlock);
542
543
break;
544
}
545
errcode = capi20_put_message(mp->ap, skb);
546
if (errcode == CAPI_NOERROR) {
547
pr_debug("capi: DATA_B3_REQ %u len=%u\n",
548
datahandle, len);
549
continue;
550
}
551
capiminor_del_ack(mp, datahandle);
552
553
if (errcode == CAPI_SENDQUEUEFULL) {
554
skb_pull(skb, CAPI_DATA_B3_REQ_LEN);
555
556
spin_lock_bh(&mp->outlock);
557
__skb_queue_head(&mp->outqueue, skb);
558
mp->outbytes += len;
559
spin_unlock_bh(&mp->outlock);
560
561
break;
562
}
563
564
/* ups, drop packet */
565
printk(KERN_ERR "capi: put_message = %x\n", errcode);
566
kfree_skb(skb);
567
}
568
tty_kref_put(tty);
569
}
570
571
#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
572
/* -------- function called by lower level -------------------------- */
573
574
static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb)
575
{
576
struct capidev *cdev = ap->private;
577
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
578
struct tty_struct *tty;
579
struct capiminor *mp;
580
u16 datahandle;
581
#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
582
struct capincci *np;
583
584
mutex_lock(&cdev->lock);
585
586
if (CAPIMSG_CMD(skb->data) == CAPI_CONNECT_B3_CONF) {
587
u16 info = CAPIMSG_U16(skb->data, 12); // Info field
588
if ((info & 0xff00) == 0)
589
capincci_alloc(cdev, CAPIMSG_NCCI(skb->data));
590
}
591
if (CAPIMSG_CMD(skb->data) == CAPI_CONNECT_B3_IND)
592
capincci_alloc(cdev, CAPIMSG_NCCI(skb->data));
593
594
if (CAPIMSG_COMMAND(skb->data) != CAPI_DATA_B3) {
595
skb_queue_tail(&cdev->recvqueue, skb);
596
wake_up_interruptible(&cdev->recvwait);
597
goto unlock_out;
598
}
599
600
np = capincci_find(cdev, CAPIMSG_CONTROL(skb->data));
601
if (!np) {
602
printk(KERN_ERR "BUG: capi_signal: ncci not found\n");
603
skb_queue_tail(&cdev->recvqueue, skb);
604
wake_up_interruptible(&cdev->recvwait);
605
goto unlock_out;
606
}
607
608
#ifndef CONFIG_ISDN_CAPI_MIDDLEWARE
609
skb_queue_tail(&cdev->recvqueue, skb);
610
wake_up_interruptible(&cdev->recvwait);
611
612
#else /* CONFIG_ISDN_CAPI_MIDDLEWARE */
613
614
mp = np->minorp;
615
if (!mp) {
616
skb_queue_tail(&cdev->recvqueue, skb);
617
wake_up_interruptible(&cdev->recvwait);
618
goto unlock_out;
619
}
620
if (CAPIMSG_SUBCOMMAND(skb->data) == CAPI_IND) {
621
datahandle = CAPIMSG_U16(skb->data, CAPIMSG_BASELEN+4+4+2);
622
pr_debug("capi_signal: DATA_B3_IND %u len=%d\n",
623
datahandle, skb->len-CAPIMSG_LEN(skb->data));
624
skb_queue_tail(&mp->inqueue, skb);
625
626
handle_minor_recv(mp);
627
628
} else if (CAPIMSG_SUBCOMMAND(skb->data) == CAPI_CONF) {
629
630
datahandle = CAPIMSG_U16(skb->data, CAPIMSG_BASELEN+4);
631
pr_debug("capi_signal: DATA_B3_CONF %u 0x%x\n",
632
datahandle,
633
CAPIMSG_U16(skb->data, CAPIMSG_BASELEN+4+2));
634
kfree_skb(skb);
635
capiminor_del_ack(mp, datahandle);
636
tty = tty_port_tty_get(&mp->port);
637
if (tty) {
638
tty_wakeup(tty);
639
tty_kref_put(tty);
640
}
641
handle_minor_send(mp);
642
643
} else {
644
/* ups, let capi application handle it :-) */
645
skb_queue_tail(&cdev->recvqueue, skb);
646
wake_up_interruptible(&cdev->recvwait);
647
}
648
#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
649
650
unlock_out:
651
mutex_unlock(&cdev->lock);
652
}
653
654
/* -------- file_operations for capidev ----------------------------- */
655
656
static ssize_t
657
capi_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
658
{
659
struct capidev *cdev = file->private_data;
660
struct sk_buff *skb;
661
size_t copied;
662
int err;
663
664
if (!cdev->ap.applid)
665
return -ENODEV;
666
667
skb = skb_dequeue(&cdev->recvqueue);
668
if (!skb) {
669
if (file->f_flags & O_NONBLOCK)
670
return -EAGAIN;
671
err = wait_event_interruptible(cdev->recvwait,
672
(skb = skb_dequeue(&cdev->recvqueue)));
673
if (err)
674
return err;
675
}
676
if (skb->len > count) {
677
skb_queue_head(&cdev->recvqueue, skb);
678
return -EMSGSIZE;
679
}
680
if (copy_to_user(buf, skb->data, skb->len)) {
681
skb_queue_head(&cdev->recvqueue, skb);
682
return -EFAULT;
683
}
684
copied = skb->len;
685
686
kfree_skb(skb);
687
688
return copied;
689
}
690
691
static ssize_t
692
capi_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
693
{
694
struct capidev *cdev = file->private_data;
695
struct sk_buff *skb;
696
u16 mlen;
697
698
if (!cdev->ap.applid)
699
return -ENODEV;
700
701
skb = alloc_skb(count, GFP_USER);
702
if (!skb)
703
return -ENOMEM;
704
705
if (copy_from_user(skb_put(skb, count), buf, count)) {
706
kfree_skb(skb);
707
return -EFAULT;
708
}
709
mlen = CAPIMSG_LEN(skb->data);
710
if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_REQ) {
711
if ((size_t)(mlen + CAPIMSG_DATALEN(skb->data)) != count) {
712
kfree_skb(skb);
713
return -EINVAL;
714
}
715
} else {
716
if (mlen != count) {
717
kfree_skb(skb);
718
return -EINVAL;
719
}
720
}
721
CAPIMSG_SETAPPID(skb->data, cdev->ap.applid);
722
723
if (CAPIMSG_CMD(skb->data) == CAPI_DISCONNECT_B3_RESP) {
724
mutex_lock(&cdev->lock);
725
capincci_free(cdev, CAPIMSG_NCCI(skb->data));
726
mutex_unlock(&cdev->lock);
727
}
728
729
cdev->errcode = capi20_put_message(&cdev->ap, skb);
730
731
if (cdev->errcode) {
732
kfree_skb(skb);
733
return -EIO;
734
}
735
return count;
736
}
737
738
static unsigned int
739
capi_poll(struct file *file, poll_table * wait)
740
{
741
struct capidev *cdev = file->private_data;
742
unsigned int mask = 0;
743
744
if (!cdev->ap.applid)
745
return POLLERR;
746
747
poll_wait(file, &(cdev->recvwait), wait);
748
mask = POLLOUT | POLLWRNORM;
749
if (!skb_queue_empty(&cdev->recvqueue))
750
mask |= POLLIN | POLLRDNORM;
751
return mask;
752
}
753
754
static int
755
capi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
756
{
757
struct capidev *cdev = file->private_data;
758
capi_ioctl_struct data;
759
int retval = -EINVAL;
760
void __user *argp = (void __user *)arg;
761
762
switch (cmd) {
763
case CAPI_REGISTER:
764
mutex_lock(&cdev->lock);
765
766
if (cdev->ap.applid) {
767
retval = -EEXIST;
768
goto register_out;
769
}
770
if (copy_from_user(&cdev->ap.rparam, argp,
771
sizeof(struct capi_register_params))) {
772
retval = -EFAULT;
773
goto register_out;
774
}
775
cdev->ap.private = cdev;
776
cdev->ap.recv_message = capi_recv_message;
777
cdev->errcode = capi20_register(&cdev->ap);
778
retval = (int)cdev->ap.applid;
779
if (cdev->errcode) {
780
cdev->ap.applid = 0;
781
retval = -EIO;
782
}
783
784
register_out:
785
mutex_unlock(&cdev->lock);
786
return retval;
787
788
case CAPI_GET_VERSION:
789
{
790
if (copy_from_user(&data.contr, argp,
791
sizeof(data.contr)))
792
return -EFAULT;
793
cdev->errcode = capi20_get_version(data.contr, &data.version);
794
if (cdev->errcode)
795
return -EIO;
796
if (copy_to_user(argp, &data.version,
797
sizeof(data.version)))
798
return -EFAULT;
799
}
800
return 0;
801
802
case CAPI_GET_SERIAL:
803
{
804
if (copy_from_user(&data.contr, argp,
805
sizeof(data.contr)))
806
return -EFAULT;
807
cdev->errcode = capi20_get_serial (data.contr, data.serial);
808
if (cdev->errcode)
809
return -EIO;
810
if (copy_to_user(argp, data.serial,
811
sizeof(data.serial)))
812
return -EFAULT;
813
}
814
return 0;
815
case CAPI_GET_PROFILE:
816
{
817
if (copy_from_user(&data.contr, argp,
818
sizeof(data.contr)))
819
return -EFAULT;
820
821
if (data.contr == 0) {
822
cdev->errcode = capi20_get_profile(data.contr, &data.profile);
823
if (cdev->errcode)
824
return -EIO;
825
826
retval = copy_to_user(argp,
827
&data.profile.ncontroller,
828
sizeof(data.profile.ncontroller));
829
830
} else {
831
cdev->errcode = capi20_get_profile(data.contr, &data.profile);
832
if (cdev->errcode)
833
return -EIO;
834
835
retval = copy_to_user(argp, &data.profile,
836
sizeof(data.profile));
837
}
838
if (retval)
839
return -EFAULT;
840
}
841
return 0;
842
843
case CAPI_GET_MANUFACTURER:
844
{
845
if (copy_from_user(&data.contr, argp,
846
sizeof(data.contr)))
847
return -EFAULT;
848
cdev->errcode = capi20_get_manufacturer(data.contr, data.manufacturer);
849
if (cdev->errcode)
850
return -EIO;
851
852
if (copy_to_user(argp, data.manufacturer,
853
sizeof(data.manufacturer)))
854
return -EFAULT;
855
856
}
857
return 0;
858
case CAPI_GET_ERRCODE:
859
data.errcode = cdev->errcode;
860
cdev->errcode = CAPI_NOERROR;
861
if (arg) {
862
if (copy_to_user(argp, &data.errcode,
863
sizeof(data.errcode)))
864
return -EFAULT;
865
}
866
return data.errcode;
867
868
case CAPI_INSTALLED:
869
if (capi20_isinstalled() == CAPI_NOERROR)
870
return 0;
871
return -ENXIO;
872
873
case CAPI_MANUFACTURER_CMD:
874
{
875
struct capi_manufacturer_cmd mcmd;
876
if (!capable(CAP_SYS_ADMIN))
877
return -EPERM;
878
if (copy_from_user(&mcmd, argp, sizeof(mcmd)))
879
return -EFAULT;
880
return capi20_manufacturer(mcmd.cmd, mcmd.data);
881
}
882
return 0;
883
884
case CAPI_SET_FLAGS:
885
case CAPI_CLR_FLAGS: {
886
unsigned userflags;
887
888
if (copy_from_user(&userflags, argp, sizeof(userflags)))
889
return -EFAULT;
890
891
mutex_lock(&cdev->lock);
892
if (cmd == CAPI_SET_FLAGS)
893
cdev->userflags |= userflags;
894
else
895
cdev->userflags &= ~userflags;
896
mutex_unlock(&cdev->lock);
897
return 0;
898
}
899
case CAPI_GET_FLAGS:
900
if (copy_to_user(argp, &cdev->userflags,
901
sizeof(cdev->userflags)))
902
return -EFAULT;
903
return 0;
904
905
case CAPI_NCCI_OPENCOUNT: {
906
struct capincci *nccip;
907
unsigned ncci;
908
int count = 0;
909
910
if (copy_from_user(&ncci, argp, sizeof(ncci)))
911
return -EFAULT;
912
913
mutex_lock(&cdev->lock);
914
nccip = capincci_find(cdev, (u32)ncci);
915
if (nccip)
916
count = capincci_minor_opencount(nccip);
917
mutex_unlock(&cdev->lock);
918
return count;
919
}
920
921
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
922
case CAPI_NCCI_GETUNIT: {
923
struct capincci *nccip;
924
struct capiminor *mp;
925
unsigned ncci;
926
int unit = -ESRCH;
927
928
if (copy_from_user(&ncci, argp, sizeof(ncci)))
929
return -EFAULT;
930
931
mutex_lock(&cdev->lock);
932
nccip = capincci_find(cdev, (u32)ncci);
933
if (nccip) {
934
mp = nccip->minorp;
935
if (mp)
936
unit = mp->minor;
937
}
938
mutex_unlock(&cdev->lock);
939
return unit;
940
}
941
#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
942
943
default:
944
return -EINVAL;
945
}
946
}
947
948
static long
949
capi_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
950
{
951
int ret;
952
953
mutex_lock(&capi_mutex);
954
ret = capi_ioctl(file, cmd, arg);
955
mutex_unlock(&capi_mutex);
956
957
return ret;
958
}
959
960
static int capi_open(struct inode *inode, struct file *file)
961
{
962
struct capidev *cdev;
963
964
cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
965
if (!cdev)
966
return -ENOMEM;
967
968
mutex_init(&cdev->lock);
969
skb_queue_head_init(&cdev->recvqueue);
970
init_waitqueue_head(&cdev->recvwait);
971
INIT_LIST_HEAD(&cdev->nccis);
972
file->private_data = cdev;
973
974
mutex_lock(&capidev_list_lock);
975
list_add_tail(&cdev->list, &capidev_list);
976
mutex_unlock(&capidev_list_lock);
977
978
return nonseekable_open(inode, file);
979
}
980
981
static int capi_release(struct inode *inode, struct file *file)
982
{
983
struct capidev *cdev = file->private_data;
984
985
mutex_lock(&capidev_list_lock);
986
list_del(&cdev->list);
987
mutex_unlock(&capidev_list_lock);
988
989
if (cdev->ap.applid)
990
capi20_release(&cdev->ap);
991
skb_queue_purge(&cdev->recvqueue);
992
capincci_free(cdev, 0xffffffff);
993
994
kfree(cdev);
995
return 0;
996
}
997
998
static const struct file_operations capi_fops =
999
{
1000
.owner = THIS_MODULE,
1001
.llseek = no_llseek,
1002
.read = capi_read,
1003
.write = capi_write,
1004
.poll = capi_poll,
1005
.unlocked_ioctl = capi_unlocked_ioctl,
1006
.open = capi_open,
1007
.release = capi_release,
1008
};
1009
1010
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
1011
/* -------- tty_operations for capincci ----------------------------- */
1012
1013
static int
1014
capinc_tty_install(struct tty_driver *driver, struct tty_struct *tty)
1015
{
1016
int idx = tty->index;
1017
struct capiminor *mp = capiminor_get(idx);
1018
int ret = tty_init_termios(tty);
1019
1020
if (ret == 0) {
1021
tty_driver_kref_get(driver);
1022
tty->count++;
1023
tty->driver_data = mp;
1024
driver->ttys[idx] = tty;
1025
} else
1026
capiminor_put(mp);
1027
return ret;
1028
}
1029
1030
static void capinc_tty_cleanup(struct tty_struct *tty)
1031
{
1032
struct capiminor *mp = tty->driver_data;
1033
tty->driver_data = NULL;
1034
capiminor_put(mp);
1035
}
1036
1037
static int capinc_tty_open(struct tty_struct *tty, struct file *filp)
1038
{
1039
struct capiminor *mp = tty->driver_data;
1040
int err;
1041
1042
err = tty_port_open(&mp->port, tty, filp);
1043
if (err)
1044
return err;
1045
1046
handle_minor_recv(mp);
1047
return 0;
1048
}
1049
1050
static void capinc_tty_close(struct tty_struct *tty, struct file *filp)
1051
{
1052
struct capiminor *mp = tty->driver_data;
1053
1054
tty_port_close(&mp->port, tty, filp);
1055
}
1056
1057
static int capinc_tty_write(struct tty_struct *tty,
1058
const unsigned char *buf, int count)
1059
{
1060
struct capiminor *mp = tty->driver_data;
1061
struct sk_buff *skb;
1062
1063
pr_debug("capinc_tty_write(count=%d)\n", count);
1064
1065
spin_lock_bh(&mp->outlock);
1066
skb = mp->outskb;
1067
if (skb) {
1068
mp->outskb = NULL;
1069
__skb_queue_tail(&mp->outqueue, skb);
1070
mp->outbytes += skb->len;
1071
}
1072
1073
skb = alloc_skb(CAPI_DATA_B3_REQ_LEN+count, GFP_ATOMIC);
1074
if (!skb) {
1075
printk(KERN_ERR "capinc_tty_write: alloc_skb failed\n");
1076
spin_unlock_bh(&mp->outlock);
1077
return -ENOMEM;
1078
}
1079
1080
skb_reserve(skb, CAPI_DATA_B3_REQ_LEN);
1081
memcpy(skb_put(skb, count), buf, count);
1082
1083
__skb_queue_tail(&mp->outqueue, skb);
1084
mp->outbytes += skb->len;
1085
spin_unlock_bh(&mp->outlock);
1086
1087
handle_minor_send(mp);
1088
1089
return count;
1090
}
1091
1092
static int capinc_tty_put_char(struct tty_struct *tty, unsigned char ch)
1093
{
1094
struct capiminor *mp = tty->driver_data;
1095
bool invoke_send = false;
1096
struct sk_buff *skb;
1097
int ret = 1;
1098
1099
pr_debug("capinc_put_char(%u)\n", ch);
1100
1101
spin_lock_bh(&mp->outlock);
1102
skb = mp->outskb;
1103
if (skb) {
1104
if (skb_tailroom(skb) > 0) {
1105
*(skb_put(skb, 1)) = ch;
1106
goto unlock_out;
1107
}
1108
mp->outskb = NULL;
1109
__skb_queue_tail(&mp->outqueue, skb);
1110
mp->outbytes += skb->len;
1111
invoke_send = true;
1112
}
1113
1114
skb = alloc_skb(CAPI_DATA_B3_REQ_LEN+CAPI_MAX_BLKSIZE, GFP_ATOMIC);
1115
if (skb) {
1116
skb_reserve(skb, CAPI_DATA_B3_REQ_LEN);
1117
*(skb_put(skb, 1)) = ch;
1118
mp->outskb = skb;
1119
} else {
1120
printk(KERN_ERR "capinc_put_char: char %u lost\n", ch);
1121
ret = 0;
1122
}
1123
1124
unlock_out:
1125
spin_unlock_bh(&mp->outlock);
1126
1127
if (invoke_send)
1128
handle_minor_send(mp);
1129
1130
return ret;
1131
}
1132
1133
static void capinc_tty_flush_chars(struct tty_struct *tty)
1134
{
1135
struct capiminor *mp = tty->driver_data;
1136
struct sk_buff *skb;
1137
1138
pr_debug("capinc_tty_flush_chars\n");
1139
1140
spin_lock_bh(&mp->outlock);
1141
skb = mp->outskb;
1142
if (skb) {
1143
mp->outskb = NULL;
1144
__skb_queue_tail(&mp->outqueue, skb);
1145
mp->outbytes += skb->len;
1146
spin_unlock_bh(&mp->outlock);
1147
1148
handle_minor_send(mp);
1149
} else
1150
spin_unlock_bh(&mp->outlock);
1151
1152
handle_minor_recv(mp);
1153
}
1154
1155
static int capinc_tty_write_room(struct tty_struct *tty)
1156
{
1157
struct capiminor *mp = tty->driver_data;
1158
int room;
1159
1160
room = CAPINC_MAX_SENDQUEUE-skb_queue_len(&mp->outqueue);
1161
room *= CAPI_MAX_BLKSIZE;
1162
pr_debug("capinc_tty_write_room = %d\n", room);
1163
return room;
1164
}
1165
1166
static int capinc_tty_chars_in_buffer(struct tty_struct *tty)
1167
{
1168
struct capiminor *mp = tty->driver_data;
1169
1170
pr_debug("capinc_tty_chars_in_buffer = %d nack=%d sq=%d rq=%d\n",
1171
mp->outbytes, mp->nack,
1172
skb_queue_len(&mp->outqueue),
1173
skb_queue_len(&mp->inqueue));
1174
return mp->outbytes;
1175
}
1176
1177
static int capinc_tty_ioctl(struct tty_struct *tty,
1178
unsigned int cmd, unsigned long arg)
1179
{
1180
return -ENOIOCTLCMD;
1181
}
1182
1183
static void capinc_tty_set_termios(struct tty_struct *tty, struct ktermios * old)
1184
{
1185
pr_debug("capinc_tty_set_termios\n");
1186
}
1187
1188
static void capinc_tty_throttle(struct tty_struct *tty)
1189
{
1190
struct capiminor *mp = tty->driver_data;
1191
pr_debug("capinc_tty_throttle\n");
1192
mp->ttyinstop = 1;
1193
}
1194
1195
static void capinc_tty_unthrottle(struct tty_struct *tty)
1196
{
1197
struct capiminor *mp = tty->driver_data;
1198
1199
pr_debug("capinc_tty_unthrottle\n");
1200
mp->ttyinstop = 0;
1201
handle_minor_recv(mp);
1202
}
1203
1204
static void capinc_tty_stop(struct tty_struct *tty)
1205
{
1206
struct capiminor *mp = tty->driver_data;
1207
1208
pr_debug("capinc_tty_stop\n");
1209
mp->ttyoutstop = 1;
1210
}
1211
1212
static void capinc_tty_start(struct tty_struct *tty)
1213
{
1214
struct capiminor *mp = tty->driver_data;
1215
1216
pr_debug("capinc_tty_start\n");
1217
mp->ttyoutstop = 0;
1218
handle_minor_send(mp);
1219
}
1220
1221
static void capinc_tty_hangup(struct tty_struct *tty)
1222
{
1223
struct capiminor *mp = tty->driver_data;
1224
1225
pr_debug("capinc_tty_hangup\n");
1226
tty_port_hangup(&mp->port);
1227
}
1228
1229
static int capinc_tty_break_ctl(struct tty_struct *tty, int state)
1230
{
1231
pr_debug("capinc_tty_break_ctl(%d)\n", state);
1232
return 0;
1233
}
1234
1235
static void capinc_tty_flush_buffer(struct tty_struct *tty)
1236
{
1237
pr_debug("capinc_tty_flush_buffer\n");
1238
}
1239
1240
static void capinc_tty_set_ldisc(struct tty_struct *tty)
1241
{
1242
pr_debug("capinc_tty_set_ldisc\n");
1243
}
1244
1245
static void capinc_tty_send_xchar(struct tty_struct *tty, char ch)
1246
{
1247
pr_debug("capinc_tty_send_xchar(%d)\n", ch);
1248
}
1249
1250
static const struct tty_operations capinc_ops = {
1251
.open = capinc_tty_open,
1252
.close = capinc_tty_close,
1253
.write = capinc_tty_write,
1254
.put_char = capinc_tty_put_char,
1255
.flush_chars = capinc_tty_flush_chars,
1256
.write_room = capinc_tty_write_room,
1257
.chars_in_buffer = capinc_tty_chars_in_buffer,
1258
.ioctl = capinc_tty_ioctl,
1259
.set_termios = capinc_tty_set_termios,
1260
.throttle = capinc_tty_throttle,
1261
.unthrottle = capinc_tty_unthrottle,
1262
.stop = capinc_tty_stop,
1263
.start = capinc_tty_start,
1264
.hangup = capinc_tty_hangup,
1265
.break_ctl = capinc_tty_break_ctl,
1266
.flush_buffer = capinc_tty_flush_buffer,
1267
.set_ldisc = capinc_tty_set_ldisc,
1268
.send_xchar = capinc_tty_send_xchar,
1269
.install = capinc_tty_install,
1270
.cleanup = capinc_tty_cleanup,
1271
};
1272
1273
static int __init capinc_tty_init(void)
1274
{
1275
struct tty_driver *drv;
1276
int err;
1277
1278
if (capi_ttyminors > CAPINC_MAX_PORTS)
1279
capi_ttyminors = CAPINC_MAX_PORTS;
1280
if (capi_ttyminors <= 0)
1281
capi_ttyminors = CAPINC_NR_PORTS;
1282
1283
capiminors = kzalloc(sizeof(struct capi_minor *) * capi_ttyminors,
1284
GFP_KERNEL);
1285
if (!capiminors)
1286
return -ENOMEM;
1287
1288
drv = alloc_tty_driver(capi_ttyminors);
1289
if (!drv) {
1290
kfree(capiminors);
1291
return -ENOMEM;
1292
}
1293
drv->owner = THIS_MODULE;
1294
drv->driver_name = "capi_nc";
1295
drv->name = "capi";
1296
drv->major = 0;
1297
drv->minor_start = 0;
1298
drv->type = TTY_DRIVER_TYPE_SERIAL;
1299
drv->subtype = SERIAL_TYPE_NORMAL;
1300
drv->init_termios = tty_std_termios;
1301
drv->init_termios.c_iflag = ICRNL;
1302
drv->init_termios.c_oflag = OPOST | ONLCR;
1303
drv->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
1304
drv->init_termios.c_lflag = 0;
1305
drv->flags =
1306
TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS |
1307
TTY_DRIVER_DYNAMIC_DEV;
1308
tty_set_operations(drv, &capinc_ops);
1309
1310
err = tty_register_driver(drv);
1311
if (err) {
1312
put_tty_driver(drv);
1313
kfree(capiminors);
1314
printk(KERN_ERR "Couldn't register capi_nc driver\n");
1315
return err;
1316
}
1317
capinc_tty_driver = drv;
1318
return 0;
1319
}
1320
1321
static void __exit capinc_tty_exit(void)
1322
{
1323
tty_unregister_driver(capinc_tty_driver);
1324
put_tty_driver(capinc_tty_driver);
1325
kfree(capiminors);
1326
}
1327
1328
#else /* !CONFIG_ISDN_CAPI_MIDDLEWARE */
1329
1330
static inline int capinc_tty_init(void)
1331
{
1332
return 0;
1333
}
1334
1335
static inline void capinc_tty_exit(void) { }
1336
1337
#endif /* !CONFIG_ISDN_CAPI_MIDDLEWARE */
1338
1339
/* -------- /proc functions ----------------------------------------- */
1340
1341
/*
1342
* /proc/capi/capi20:
1343
* minor applid nrecvctlpkt nrecvdatapkt nsendctlpkt nsenddatapkt
1344
*/
1345
static int capi20_proc_show(struct seq_file *m, void *v)
1346
{
1347
struct capidev *cdev;
1348
struct list_head *l;
1349
1350
mutex_lock(&capidev_list_lock);
1351
list_for_each(l, &capidev_list) {
1352
cdev = list_entry(l, struct capidev, list);
1353
seq_printf(m, "0 %d %lu %lu %lu %lu\n",
1354
cdev->ap.applid,
1355
cdev->ap.nrecvctlpkt,
1356
cdev->ap.nrecvdatapkt,
1357
cdev->ap.nsentctlpkt,
1358
cdev->ap.nsentdatapkt);
1359
}
1360
mutex_unlock(&capidev_list_lock);
1361
return 0;
1362
}
1363
1364
static int capi20_proc_open(struct inode *inode, struct file *file)
1365
{
1366
return single_open(file, capi20_proc_show, NULL);
1367
}
1368
1369
static const struct file_operations capi20_proc_fops = {
1370
.owner = THIS_MODULE,
1371
.open = capi20_proc_open,
1372
.read = seq_read,
1373
.llseek = seq_lseek,
1374
.release = single_release,
1375
};
1376
1377
/*
1378
* /proc/capi/capi20ncci:
1379
* applid ncci
1380
*/
1381
static int capi20ncci_proc_show(struct seq_file *m, void *v)
1382
{
1383
struct capidev *cdev;
1384
struct capincci *np;
1385
1386
mutex_lock(&capidev_list_lock);
1387
list_for_each_entry(cdev, &capidev_list, list) {
1388
mutex_lock(&cdev->lock);
1389
list_for_each_entry(np, &cdev->nccis, list)
1390
seq_printf(m, "%d 0x%x\n", cdev->ap.applid, np->ncci);
1391
mutex_unlock(&cdev->lock);
1392
}
1393
mutex_unlock(&capidev_list_lock);
1394
return 0;
1395
}
1396
1397
static int capi20ncci_proc_open(struct inode *inode, struct file *file)
1398
{
1399
return single_open(file, capi20ncci_proc_show, NULL);
1400
}
1401
1402
static const struct file_operations capi20ncci_proc_fops = {
1403
.owner = THIS_MODULE,
1404
.open = capi20ncci_proc_open,
1405
.read = seq_read,
1406
.llseek = seq_lseek,
1407
.release = single_release,
1408
};
1409
1410
static void __init proc_init(void)
1411
{
1412
proc_create("capi/capi20", 0, NULL, &capi20_proc_fops);
1413
proc_create("capi/capi20ncci", 0, NULL, &capi20ncci_proc_fops);
1414
}
1415
1416
static void __exit proc_exit(void)
1417
{
1418
remove_proc_entry("capi/capi20", NULL);
1419
remove_proc_entry("capi/capi20ncci", NULL);
1420
}
1421
1422
/* -------- init function and module interface ---------------------- */
1423
1424
1425
static int __init capi_init(void)
1426
{
1427
const char *compileinfo;
1428
int major_ret;
1429
1430
major_ret = register_chrdev(capi_major, "capi20", &capi_fops);
1431
if (major_ret < 0) {
1432
printk(KERN_ERR "capi20: unable to get major %d\n", capi_major);
1433
return major_ret;
1434
}
1435
capi_class = class_create(THIS_MODULE, "capi");
1436
if (IS_ERR(capi_class)) {
1437
unregister_chrdev(capi_major, "capi20");
1438
return PTR_ERR(capi_class);
1439
}
1440
1441
device_create(capi_class, NULL, MKDEV(capi_major, 0), NULL, "capi");
1442
1443
if (capinc_tty_init() < 0) {
1444
device_destroy(capi_class, MKDEV(capi_major, 0));
1445
class_destroy(capi_class);
1446
unregister_chrdev(capi_major, "capi20");
1447
return -ENOMEM;
1448
}
1449
1450
proc_init();
1451
1452
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
1453
compileinfo = " (middleware)";
1454
#else
1455
compileinfo = " (no middleware)";
1456
#endif
1457
printk(KERN_NOTICE "CAPI 2.0 started up with major %d%s\n",
1458
capi_major, compileinfo);
1459
1460
return 0;
1461
}
1462
1463
static void __exit capi_exit(void)
1464
{
1465
proc_exit();
1466
1467
device_destroy(capi_class, MKDEV(capi_major, 0));
1468
class_destroy(capi_class);
1469
unregister_chrdev(capi_major, "capi20");
1470
1471
capinc_tty_exit();
1472
}
1473
1474
module_init(capi_init);
1475
module_exit(capi_exit);
1476
1477