capi.c 31.8 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11
/* $Id: capi.c,v 1.1.2.7 2004/04/28 09:48:59 armin Exp $
 *
 * CAPI 2.0 Interface for Linux
 *
 * Copyright 1996 by Carsten Paeth <calle@calle.de>
 *
 * This software may be used and distributed according to the terms
 * of the GNU General Public License, incorporated herein by reference.
 *
 */

12
#include <linux/compiler.h>
L
Linus Torvalds 已提交
13 14 15 16 17 18 19 20 21
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/fcntl.h>
#include <linux/fs.h>
#include <linux/signal.h>
22
#include <linux/mutex.h>
L
Linus Torvalds 已提交
23 24 25 26 27 28
#include <linux/mm.h>
#include <linux/timer.h>
#include <linux/wait.h>
#include <linux/tty.h>
#include <linux/netdevice.h>
#include <linux/ppp_defs.h>
29
#include <linux/ppp-ioctl.h>
L
Linus Torvalds 已提交
30 31
#include <linux/skbuff.h>
#include <linux/proc_fs.h>
32
#include <linux/seq_file.h>
L
Linus Torvalds 已提交
33 34 35 36 37 38 39 40
#include <linux/poll.h>
#include <linux/capi.h>
#include <linux/kernelcapi.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/moduleparam.h>
#include <linux/isdn/capiutil.h>
#include <linux/isdn/capicmd.h>
J
Jan Kiszka 已提交
41

L
Linus Torvalds 已提交
42 43 44 45 46 47
MODULE_DESCRIPTION("CAPI4Linux: Userspace /dev/capi20 interface");
MODULE_AUTHOR("Carsten Paeth");
MODULE_LICENSE("GPL");

/* -------- driver information -------------------------------------- */

48
static DEFINE_MUTEX(capi_mutex);
49
static struct class *capi_class;
A
Adrian Bunk 已提交
50
static int capi_major = 68;		/* allocated */
51 52 53

module_param_named(major, capi_major, uint, 0);

L
Linus Torvalds 已提交
54
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
55
#define CAPINC_NR_PORTS		32
L
Linus Torvalds 已提交
56
#define CAPINC_MAX_PORTS	256
57

A
Adrian Bunk 已提交
58
static int capi_ttyminors = CAPINC_NR_PORTS;
L
Linus Torvalds 已提交
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74

module_param_named(ttyminors, capi_ttyminors, uint, 0);
#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */

/* -------- defines ------------------------------------------------- */

#define CAPINC_MAX_RECVQUEUE	10
#define CAPINC_MAX_SENDQUEUE	10
#define CAPI_MAX_BLKSIZE	2048

/* -------- data structures ----------------------------------------- */

struct capidev;
struct capincci;
struct capiminor;

75
struct ackqueue_entry {
76 77 78 79
	struct list_head	list;
	u16			datahandle;
};

L
Linus Torvalds 已提交
80 81 82
struct capiminor {
	unsigned int      minor;

83 84 85 86
	struct capi20_appl	*ap;
	u32			ncci;
	atomic_t		datahandle;
	atomic_t		msgid;
L
Linus Torvalds 已提交
87

88
	struct tty_port port;
L
Linus Torvalds 已提交
89 90 91
	int                ttyinstop;
	int                ttyoutstop;

92 93 94 95 96 97
	struct sk_buff_head	inqueue;

	struct sk_buff_head	outqueue;
	int			outbytes;
	struct sk_buff		*outskb;
	spinlock_t		outlock;
L
Linus Torvalds 已提交
98 99

	/* transmit path */
100
	struct list_head ackqueue;
L
Linus Torvalds 已提交
101
	int nack;
102
	spinlock_t ackqlock;
L
Linus Torvalds 已提交
103 104 105
};

struct capincci {
106
	struct list_head list;
L
Linus Torvalds 已提交
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
	u32		 ncci;
	struct capidev	*cdev;
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
	struct capiminor *minorp;
#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
};

struct capidev {
	struct list_head list;
	struct capi20_appl ap;
	u16		errcode;
	unsigned        userflags;

	struct sk_buff_head recvqueue;
	wait_queue_head_t recvwait;

123
	struct list_head nccis;
L
Linus Torvalds 已提交
124

125
	struct mutex lock;
L
Linus Torvalds 已提交
126 127 128 129
};

/* -------- global variables ---------------------------------------- */

130
static DEFINE_MUTEX(capidev_list_lock);
L
Linus Torvalds 已提交
131 132 133
static LIST_HEAD(capidev_list);

#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
134

J
Jan Kiszka 已提交
135
static DEFINE_SPINLOCK(capiminors_lock);
136
static struct capiminor **capiminors;
L
Linus Torvalds 已提交
137

138 139
static struct tty_driver *capinc_tty_driver;

L
Linus Torvalds 已提交
140 141
/* -------- datahandles --------------------------------------------- */

142
static int capiminor_add_ack(struct capiminor *mp, u16 datahandle)
L
Linus Torvalds 已提交
143
{
144
	struct ackqueue_entry *n;
L
Linus Torvalds 已提交
145 146

	n = kmalloc(sizeof(*n), GFP_ATOMIC);
147 148 149
	if (unlikely(!n)) {
		printk(KERN_ERR "capi: alloc datahandle failed\n");
		return -1;
L
Linus Torvalds 已提交
150 151
	}
	n->datahandle = datahandle;
152
	INIT_LIST_HEAD(&n->list);
J
Jan Kiszka 已提交
153
	spin_lock_bh(&mp->ackqlock);
154
	list_add_tail(&n->list, &mp->ackqueue);
L
Linus Torvalds 已提交
155
	mp->nack++;
J
Jan Kiszka 已提交
156
	spin_unlock_bh(&mp->ackqlock);
L
Linus Torvalds 已提交
157 158 159 160 161
	return 0;
}

static int capiminor_del_ack(struct capiminor *mp, u16 datahandle)
{
162
	struct ackqueue_entry *p, *tmp;
L
Linus Torvalds 已提交
163

J
Jan Kiszka 已提交
164
	spin_lock_bh(&mp->ackqlock);
165
	list_for_each_entry_safe(p, tmp, &mp->ackqueue, list) {
166
		if (p->datahandle == datahandle) {
167
			list_del(&p->list);
L
Linus Torvalds 已提交
168
			mp->nack--;
J
Jan Kiszka 已提交
169 170
			spin_unlock_bh(&mp->ackqlock);
			kfree(p);
L
Linus Torvalds 已提交
171 172 173
			return 0;
		}
	}
J
Jan Kiszka 已提交
174
	spin_unlock_bh(&mp->ackqlock);
L
Linus Torvalds 已提交
175 176 177 178 179
	return -1;
}

static void capiminor_del_all_ack(struct capiminor *mp)
{
180
	struct ackqueue_entry *p, *tmp;
L
Linus Torvalds 已提交
181

182 183
	list_for_each_entry_safe(p, tmp, &mp->ackqueue, list) {
		list_del(&p->list);
L
Linus Torvalds 已提交
184 185 186 187 188 189 190 191
		kfree(p);
		mp->nack--;
	}
}


/* -------- struct capiminor ---------------------------------------- */

J
Jiri Slaby 已提交
192 193 194 195 196 197 198 199 200 201 202 203 204 205
static void capiminor_destroy(struct tty_port *port)
{
	struct capiminor *mp = container_of(port, struct capiminor, port);

	kfree_skb(mp->outskb);
	skb_queue_purge(&mp->inqueue);
	skb_queue_purge(&mp->outqueue);
	capiminor_del_all_ack(mp);
	kfree(mp);
}

static const struct tty_port_operations capiminor_port_ops = {
	.destruct = capiminor_destroy,
};
206

L
Linus Torvalds 已提交
207 208
static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci)
{
209
	struct capiminor *mp;
210
	struct device *dev;
211
	unsigned int minor;
L
Linus Torvalds 已提交
212

213
	mp = kzalloc(sizeof(*mp), GFP_KERNEL);
214 215
	if (!mp) {
		printk(KERN_ERR "capi: can't alloc capiminor\n");
L
Linus Torvalds 已提交
216 217 218 219 220
		return NULL;
	}

	mp->ap = ap;
	mp->ncci = ncci;
221 222
	INIT_LIST_HEAD(&mp->ackqueue);
	spin_lock_init(&mp->ackqlock);
L
Linus Torvalds 已提交
223 224 225

	skb_queue_head_init(&mp->inqueue);
	skb_queue_head_init(&mp->outqueue);
226
	spin_lock_init(&mp->outlock);
L
Linus Torvalds 已提交
227

228 229 230
	tty_port_init(&mp->port);
	mp->port.ops = &capiminor_port_ops;

231
	/* Allocate the least unused minor number. */
J
Jan Kiszka 已提交
232
	spin_lock(&capiminors_lock);
233 234 235 236
	for (minor = 0; minor < capi_ttyminors; minor++)
		if (!capiminors[minor]) {
			capiminors[minor] = mp;
			break;
L
Linus Torvalds 已提交
237
		}
J
Jan Kiszka 已提交
238
	spin_unlock(&capiminors_lock);
L
Linus Torvalds 已提交
239

240
	if (minor == capi_ttyminors) {
L
Linus Torvalds 已提交
241
		printk(KERN_NOTICE "capi: out of minors\n");
242
		goto err_out1;
L
Linus Torvalds 已提交
243 244
	}

245 246
	mp->minor = minor;

J
Jiri Slaby 已提交
247 248
	dev = tty_port_register_device(&mp->port, capinc_tty_driver, minor,
			NULL);
249 250 251
	if (IS_ERR(dev))
		goto err_out2;

L
Linus Torvalds 已提交
252
	return mp;
253 254

err_out2:
J
Jan Kiszka 已提交
255
	spin_lock(&capiminors_lock);
256
	capiminors[minor] = NULL;
J
Jan Kiszka 已提交
257
	spin_unlock(&capiminors_lock);
258 259

err_out1:
J
Jiri Slaby 已提交
260
	tty_port_put(&mp->port);
261
	return NULL;
L
Linus Torvalds 已提交
262 263
}

264
static struct capiminor *capiminor_get(unsigned int minor)
L
Linus Torvalds 已提交
265
{
266
	struct capiminor *mp;
L
Linus Torvalds 已提交
267

J
Jan Kiszka 已提交
268
	spin_lock(&capiminors_lock);
269
	mp = capiminors[minor];
J
Jan Kiszka 已提交
270
	if (mp)
J
Jiri Slaby 已提交
271
		tty_port_get(&mp->port);
J
Jan Kiszka 已提交
272
	spin_unlock(&capiminors_lock);
273 274

	return mp;
L
Linus Torvalds 已提交
275 276
}

J
Jan Kiszka 已提交
277 278
static inline void capiminor_put(struct capiminor *mp)
{
J
Jiri Slaby 已提交
279
	tty_port_put(&mp->port);
J
Jan Kiszka 已提交
280 281 282 283 284 285
}

static void capiminor_free(struct capiminor *mp)
{
	tty_unregister_device(capinc_tty_driver, mp->minor);

J
Jan Kiszka 已提交
286
	spin_lock(&capiminors_lock);
J
Jan Kiszka 已提交
287
	capiminors[mp->minor] = NULL;
J
Jan Kiszka 已提交
288
	spin_unlock(&capiminors_lock);
J
Jan Kiszka 已提交
289 290 291 292

	capiminor_put(mp);
}

L
Linus Torvalds 已提交
293 294
/* -------- struct capincci ----------------------------------------- */

295
static void capincci_alloc_minor(struct capidev *cdev, struct capincci *np)
L
Linus Torvalds 已提交
296
{
297 298
	if (cdev->userflags & CAPIFLAG_HIGHJACKING)
		np->minorp = capiminor_alloc(&cdev->ap, np->ncci);
299 300 301 302 303
}

static void capincci_free_minor(struct capincci *np)
{
	struct capiminor *mp = np->minorp;
304
	struct tty_struct *tty;
305 306

	if (mp) {
307 308
		tty = tty_port_tty_get(&mp->port);
		if (tty) {
309
			tty_vhangup(tty);
310
			tty_kref_put(tty);
311
		}
312 313

		capiminor_free(mp);
314 315 316 317 318 319
	}
}

static inline unsigned int capincci_minor_opencount(struct capincci *np)
{
	struct capiminor *mp = np->minorp;
J
Jan Kiszka 已提交
320 321
	unsigned int count = 0;
	struct tty_struct *tty;
322

J
Jan Kiszka 已提交
323 324 325 326 327 328 329 330
	if (mp) {
		tty = tty_port_tty_get(&mp->port);
		if (tty) {
			count = tty->count;
			tty_kref_put(tty);
		}
	}
	return count;
331 332 333 334 335 336 337 338 339 340 341 342
}

#else /* !CONFIG_ISDN_CAPI_MIDDLEWARE */

static inline void
capincci_alloc_minor(struct capidev *cdev, struct capincci *np) { }
static inline void capincci_free_minor(struct capincci *np) { }

#endif /* !CONFIG_ISDN_CAPI_MIDDLEWARE */

static struct capincci *capincci_alloc(struct capidev *cdev, u32 ncci)
{
343
	struct capincci *np;
344

345
	np = kzalloc(sizeof(*np), GFP_KERNEL);
346 347 348 349 350 351 352
	if (!np)
		return NULL;
	np->ncci = ncci;
	np->cdev = cdev;

	capincci_alloc_minor(cdev, np);

353 354 355
	list_add_tail(&np->list, &cdev->nccis);

	return np;
L
Linus Torvalds 已提交
356 357 358 359
}

static void capincci_free(struct capidev *cdev, u32 ncci)
{
360
	struct capincci *np, *tmp;
L
Linus Torvalds 已提交
361

362
	list_for_each_entry_safe(np, tmp, &cdev->nccis, list)
L
Linus Torvalds 已提交
363
		if (ncci == 0xffffffff || np->ncci == ncci) {
364
			capincci_free_minor(np);
365
			list_del(&np->list);
L
Linus Torvalds 已提交
366 367 368 369
			kfree(np);
		}
}

370
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
L
Linus Torvalds 已提交
371 372
static struct capincci *capincci_find(struct capidev *cdev, u32 ncci)
{
373
	struct capincci *np;
L
Linus Torvalds 已提交
374

375 376 377 378
	list_for_each_entry(np, &cdev->nccis, list)
		if (np->ncci == ncci)
			return np;
	return NULL;
L
Linus Torvalds 已提交
379 380 381 382 383 384 385 386
}

/* -------- handle data queue --------------------------------------- */

static struct sk_buff *
gen_data_b3_resp_for(struct capiminor *mp, struct sk_buff *skb)
{
	struct sk_buff *nskb;
387
	nskb = alloc_skb(CAPI_DATA_B3_RESP_LEN, GFP_KERNEL);
L
Linus Torvalds 已提交
388
	if (nskb) {
389
		u16 datahandle = CAPIMSG_U16(skb->data, CAPIMSG_BASELEN + 4 + 4 + 2);
L
Linus Torvalds 已提交
390 391 392 393 394
		unsigned char *s = skb_put(nskb, CAPI_DATA_B3_RESP_LEN);
		capimsg_setu16(s, 0, CAPI_DATA_B3_RESP_LEN);
		capimsg_setu16(s, 2, mp->ap->applid);
		capimsg_setu8 (s, 4, CAPI_DATA_B3);
		capimsg_setu8 (s, 5, CAPI_RESP);
395
		capimsg_setu16(s, 6, atomic_inc_return(&mp->msgid));
L
Linus Torvalds 已提交
396 397 398 399 400 401 402 403
		capimsg_setu32(s, 8, mp->ncci);
		capimsg_setu16(s, 12, datahandle);
	}
	return nskb;
}

static int handle_recv_skb(struct capiminor *mp, struct sk_buff *skb)
{
J
Jan Kiszka 已提交
404
	unsigned int datalen = skb->len - CAPIMSG_LEN(skb->data);
405
	struct tty_struct *tty;
L
Linus Torvalds 已提交
406 407 408
	struct sk_buff *nskb;
	u16 errcode, datahandle;
	struct tty_ldisc *ld;
409 410 411 412
	int ret = -1;

	tty = tty_port_tty_get(&mp->port);
	if (!tty) {
413
		pr_debug("capi: currently no receiver\n");
L
Linus Torvalds 已提交
414 415
		return -1;
	}
416

417
	ld = tty_ldisc_ref(tty);
J
Jan Kiszka 已提交
418 419 420 421 422 423
	if (!ld) {
		/* fatal error, do not requeue */
		ret = 0;
		kfree_skb(skb);
		goto deref_tty;
	}
424

A
Alan Cox 已提交
425
	if (ld->ops->receive_buf == NULL) {
426
		pr_debug("capi: ldisc has no receive_buf function\n");
J
Jan Kiszka 已提交
427 428
		/* fatal error, do not requeue */
		goto free_skb;
L
Linus Torvalds 已提交
429 430
	}
	if (mp->ttyinstop) {
431
		pr_debug("capi: recv tty throttled\n");
J
Jan Kiszka 已提交
432
		goto deref_ldisc;
L
Linus Torvalds 已提交
433
	}
J
Jan Kiszka 已提交
434

435
	if (tty->receive_room < datalen) {
436
		pr_debug("capi: no room in tty\n");
J
Jan Kiszka 已提交
437
		goto deref_ldisc;
L
Linus Torvalds 已提交
438
	}
J
Jan Kiszka 已提交
439 440 441

	nskb = gen_data_b3_resp_for(mp, skb);
	if (!nskb) {
L
Linus Torvalds 已提交
442
		printk(KERN_ERR "capi: gen_data_b3_resp failed\n");
J
Jan Kiszka 已提交
443
		goto deref_ldisc;
L
Linus Torvalds 已提交
444
	}
J
Jan Kiszka 已提交
445 446 447

	datahandle = CAPIMSG_U16(skb->data, CAPIMSG_BASELEN + 4);

L
Linus Torvalds 已提交
448
	errcode = capi20_put_message(mp->ap, nskb);
J
Jan Kiszka 已提交
449 450 451

	if (errcode == CAPI_NOERROR) {
		skb_pull(skb, CAPIMSG_LEN(skb->data));
452 453
		pr_debug("capi: DATA_B3_RESP %u len=%d => ldisc\n",
			 datahandle, skb->len);
J
Jan Kiszka 已提交
454 455
		ld->ops->receive_buf(tty, skb->data, NULL, skb->len);
	} else {
L
Linus Torvalds 已提交
456
		printk(KERN_ERR "capi: send DATA_B3_RESP failed=%x\n",
457
		       errcode);
L
Linus Torvalds 已提交
458
		kfree_skb(nskb);
J
Jan Kiszka 已提交
459 460 461

		if (errcode == CAPI_SENDQUEUEFULL)
			goto deref_ldisc;
L
Linus Torvalds 已提交
462
	}
J
Jan Kiszka 已提交
463 464

free_skb:
465
	ret = 0;
J
Jan Kiszka 已提交
466 467 468
	kfree_skb(skb);

deref_ldisc:
L
Linus Torvalds 已提交
469
	tty_ldisc_deref(ld);
J
Jan Kiszka 已提交
470 471

deref_tty:
472 473
	tty_kref_put(tty);
	return ret;
L
Linus Torvalds 已提交
474 475 476 477 478
}

static void handle_minor_recv(struct capiminor *mp)
{
	struct sk_buff *skb;
479 480

	while ((skb = skb_dequeue(&mp->inqueue)) != NULL)
L
Linus Torvalds 已提交
481 482 483 484 485 486
		if (handle_recv_skb(mp, skb) < 0) {
			skb_queue_head(&mp->inqueue, skb);
			return;
		}
}

487
static void handle_minor_send(struct capiminor *mp)
L
Linus Torvalds 已提交
488
{
489
	struct tty_struct *tty;
L
Linus Torvalds 已提交
490 491 492 493 494
	struct sk_buff *skb;
	u16 len;
	u16 errcode;
	u16 datahandle;

495 496
	tty = tty_port_tty_get(&mp->port);
	if (!tty)
497
		return;
498 499

	if (mp->ttyoutstop) {
500
		pr_debug("capi: send: tty stopped\n");
501
		tty_kref_put(tty);
502
		return;
L
Linus Torvalds 已提交
503 504
	}

505 506 507 508 509 510 511
	while (1) {
		spin_lock_bh(&mp->outlock);
		skb = __skb_dequeue(&mp->outqueue);
		if (!skb) {
			spin_unlock_bh(&mp->outlock);
			break;
		}
L
Linus Torvalds 已提交
512
		len = (u16)skb->len;
513 514 515 516
		mp->outbytes -= len;
		spin_unlock_bh(&mp->outlock);

		datahandle = atomic_inc_return(&mp->datahandle);
L
Linus Torvalds 已提交
517 518 519 520 521 522
		skb_push(skb, CAPI_DATA_B3_REQ_LEN);
		memset(skb->data, 0, CAPI_DATA_B3_REQ_LEN);
		capimsg_setu16(skb->data, 0, CAPI_DATA_B3_REQ_LEN);
		capimsg_setu16(skb->data, 2, mp->ap->applid);
		capimsg_setu8 (skb->data, 4, CAPI_DATA_B3);
		capimsg_setu8 (skb->data, 5, CAPI_REQ);
523
		capimsg_setu16(skb->data, 6, atomic_inc_return(&mp->msgid));
L
Linus Torvalds 已提交
524
		capimsg_setu32(skb->data, 8, mp->ncci);	/* NCCI */
A
Andrew Morton 已提交
525
		capimsg_setu32(skb->data, 12, (u32)(long)skb->data);/* Data32 */
L
Linus Torvalds 已提交
526 527 528 529
		capimsg_setu16(skb->data, 16, len);	/* Data length */
		capimsg_setu16(skb->data, 18, datahandle);
		capimsg_setu16(skb->data, 20, 0);	/* Flags */

530
		if (capiminor_add_ack(mp, datahandle) < 0) {
L
Linus Torvalds 已提交
531
			skb_pull(skb, CAPI_DATA_B3_REQ_LEN);
532 533 534 535 536 537

			spin_lock_bh(&mp->outlock);
			__skb_queue_head(&mp->outqueue, skb);
			mp->outbytes += len;
			spin_unlock_bh(&mp->outlock);

538
			break;
L
Linus Torvalds 已提交
539 540 541
		}
		errcode = capi20_put_message(mp->ap, skb);
		if (errcode == CAPI_NOERROR) {
542 543
			pr_debug("capi: DATA_B3_REQ %u len=%u\n",
				 datahandle, len);
L
Linus Torvalds 已提交
544 545 546 547 548 549
			continue;
		}
		capiminor_del_ack(mp, datahandle);

		if (errcode == CAPI_SENDQUEUEFULL) {
			skb_pull(skb, CAPI_DATA_B3_REQ_LEN);
550 551 552 553 554 555

			spin_lock_bh(&mp->outlock);
			__skb_queue_head(&mp->outqueue, skb);
			mp->outbytes += len;
			spin_unlock_bh(&mp->outlock);

L
Linus Torvalds 已提交
556 557 558 559 560 561 562
			break;
		}

		/* ups, drop packet */
		printk(KERN_ERR "capi: put_message = %x\n", errcode);
		kfree_skb(skb);
	}
563
	tty_kref_put(tty);
L
Linus Torvalds 已提交
564 565 566 567 568 569 570 571 572 573 574 575
}

#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
/* -------- function called by lower level -------------------------- */

static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb)
{
	struct capidev *cdev = ap->private;
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
	struct capiminor *mp;
	u16 datahandle;
	struct capincci *np;
576
#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
L
Linus Torvalds 已提交
577

578 579
	mutex_lock(&cdev->lock);

L
Linus Torvalds 已提交
580 581
	if (CAPIMSG_CMD(skb->data) == CAPI_CONNECT_B3_CONF) {
		u16 info = CAPIMSG_U16(skb->data, 12); // Info field
582
		if ((info & 0xff00) == 0)
L
Linus Torvalds 已提交
583 584
			capincci_alloc(cdev, CAPIMSG_NCCI(skb->data));
	}
585
	if (CAPIMSG_CMD(skb->data) == CAPI_CONNECT_B3_IND)
L
Linus Torvalds 已提交
586
		capincci_alloc(cdev, CAPIMSG_NCCI(skb->data));
587

L
Linus Torvalds 已提交
588 589 590
	if (CAPIMSG_COMMAND(skb->data) != CAPI_DATA_B3) {
		skb_queue_tail(&cdev->recvqueue, skb);
		wake_up_interruptible(&cdev->recvwait);
591
		goto unlock_out;
L
Linus Torvalds 已提交
592
	}
593

594 595 596 597 598 599
#ifndef CONFIG_ISDN_CAPI_MIDDLEWARE
	skb_queue_tail(&cdev->recvqueue, skb);
	wake_up_interruptible(&cdev->recvwait);

#else /* CONFIG_ISDN_CAPI_MIDDLEWARE */

600
	np = capincci_find(cdev, CAPIMSG_CONTROL(skb->data));
L
Linus Torvalds 已提交
601 602 603 604
	if (!np) {
		printk(KERN_ERR "BUG: capi_signal: ncci not found\n");
		skb_queue_tail(&cdev->recvqueue, skb);
		wake_up_interruptible(&cdev->recvwait);
605
		goto unlock_out;
L
Linus Torvalds 已提交
606
	}
607

L
Linus Torvalds 已提交
608 609 610 611
	mp = np->minorp;
	if (!mp) {
		skb_queue_tail(&cdev->recvqueue, skb);
		wake_up_interruptible(&cdev->recvwait);
612
		goto unlock_out;
L
Linus Torvalds 已提交
613 614
	}
	if (CAPIMSG_SUBCOMMAND(skb->data) == CAPI_IND) {
615
		datahandle = CAPIMSG_U16(skb->data, CAPIMSG_BASELEN + 4 + 4 + 2);
616 617
		pr_debug("capi_signal: DATA_B3_IND %u len=%d\n",
			 datahandle, skb->len-CAPIMSG_LEN(skb->data));
L
Linus Torvalds 已提交
618
		skb_queue_tail(&mp->inqueue, skb);
619

L
Linus Torvalds 已提交
620 621 622 623
		handle_minor_recv(mp);

	} else if (CAPIMSG_SUBCOMMAND(skb->data) == CAPI_CONF) {

624
		datahandle = CAPIMSG_U16(skb->data, CAPIMSG_BASELEN + 4);
625 626
		pr_debug("capi_signal: DATA_B3_CONF %u 0x%x\n",
			 datahandle,
627
			 CAPIMSG_U16(skb->data, CAPIMSG_BASELEN + 4 + 2));
L
Linus Torvalds 已提交
628
		kfree_skb(skb);
J
Jan Kiszka 已提交
629
		capiminor_del_ack(mp, datahandle);
J
Jiri Slaby 已提交
630
		tty_port_tty_wakeup(&mp->port);
631
		handle_minor_send(mp);
L
Linus Torvalds 已提交
632 633 634 635 636 637 638

	} else {
		/* ups, let capi application handle it :-) */
		skb_queue_tail(&cdev->recvqueue, skb);
		wake_up_interruptible(&cdev->recvwait);
	}
#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
639

640 641
unlock_out:
	mutex_unlock(&cdev->lock);
L
Linus Torvalds 已提交
642 643 644 645 646 647 648
}

/* -------- file_operations for capidev ----------------------------- */

static ssize_t
capi_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
649
	struct capidev *cdev = file->private_data;
L
Linus Torvalds 已提交
650 651
	struct sk_buff *skb;
	size_t copied;
J
Jan Kiszka 已提交
652
	int err;
L
Linus Torvalds 已提交
653 654 655 656

	if (!cdev->ap.applid)
		return -ENODEV;

J
Jan Kiszka 已提交
657 658
	skb = skb_dequeue(&cdev->recvqueue);
	if (!skb) {
L
Linus Torvalds 已提交
659 660
		if (file->f_flags & O_NONBLOCK)
			return -EAGAIN;
J
Jan Kiszka 已提交
661
		err = wait_event_interruptible(cdev->recvwait,
662
					       (skb = skb_dequeue(&cdev->recvqueue)));
J
Jan Kiszka 已提交
663 664
		if (err)
			return err;
L
Linus Torvalds 已提交
665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683
	}
	if (skb->len > count) {
		skb_queue_head(&cdev->recvqueue, skb);
		return -EMSGSIZE;
	}
	if (copy_to_user(buf, skb->data, skb->len)) {
		skb_queue_head(&cdev->recvqueue, skb);
		return -EFAULT;
	}
	copied = skb->len;

	kfree_skb(skb);

	return copied;
}

static ssize_t
capi_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
684
	struct capidev *cdev = file->private_data;
L
Linus Torvalds 已提交
685 686 687 688 689 690
	struct sk_buff *skb;
	u16 mlen;

	if (!cdev->ap.applid)
		return -ENODEV;

691 692 693
	if (count < CAPIMSG_BASELEN)
		return -EINVAL;

L
Linus Torvalds 已提交
694 695 696 697 698 699 700 701 702 703
	skb = alloc_skb(count, GFP_USER);
	if (!skb)
		return -ENOMEM;

	if (copy_from_user(skb_put(skb, count), buf, count)) {
		kfree_skb(skb);
		return -EFAULT;
	}
	mlen = CAPIMSG_LEN(skb->data);
	if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_REQ) {
704 705
		if (count < CAPI_DATA_B3_REQ_LEN ||
		    (size_t)(mlen + CAPIMSG_DATALEN(skb->data)) != count) {
L
Linus Torvalds 已提交
706 707 708 709 710 711 712 713 714 715 716 717
			kfree_skb(skb);
			return -EINVAL;
		}
	} else {
		if (mlen != count) {
			kfree_skb(skb);
			return -EINVAL;
		}
	}
	CAPIMSG_SETAPPID(skb->data, cdev->ap.applid);

	if (CAPIMSG_CMD(skb->data) == CAPI_DISCONNECT_B3_RESP) {
718 719 720 721
		if (count < CAPI_DISCONNECT_B3_RESP_LEN) {
			kfree_skb(skb);
			return -EINVAL;
		}
722
		mutex_lock(&cdev->lock);
L
Linus Torvalds 已提交
723
		capincci_free(cdev, CAPIMSG_NCCI(skb->data));
724
		mutex_unlock(&cdev->lock);
L
Linus Torvalds 已提交
725 726 727 728 729 730 731 732 733 734 735
	}

	cdev->errcode = capi20_put_message(&cdev->ap, skb);

	if (cdev->errcode) {
		kfree_skb(skb);
		return -EIO;
	}
	return count;
}

736
static __poll_t
737
capi_poll(struct file *file, poll_table *wait)
L
Linus Torvalds 已提交
738
{
739
	struct capidev *cdev = file->private_data;
740
	__poll_t mask = 0;
L
Linus Torvalds 已提交
741 742

	if (!cdev->ap.applid)
743
		return EPOLLERR;
L
Linus Torvalds 已提交
744 745

	poll_wait(file, &(cdev->recvwait), wait);
746
	mask = EPOLLOUT | EPOLLWRNORM;
747
	if (!skb_queue_empty_lockless(&cdev->recvqueue))
748
		mask |= EPOLLIN | EPOLLRDNORM;
L
Linus Torvalds 已提交
749 750 751 752
	return mask;
}

static int
753
capi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
L
Linus Torvalds 已提交
754 755 756 757 758 759 760 761
{
	struct capidev *cdev = file->private_data;
	capi_ioctl_struct data;
	int retval = -EINVAL;
	void __user *argp = (void __user *)arg;

	switch (cmd) {
	case CAPI_REGISTER:
762
		mutex_lock(&cdev->lock);
L
Linus Torvalds 已提交
763

764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779
		if (cdev->ap.applid) {
			retval = -EEXIST;
			goto register_out;
		}
		if (copy_from_user(&cdev->ap.rparam, argp,
				   sizeof(struct capi_register_params))) {
			retval = -EFAULT;
			goto register_out;
		}
		cdev->ap.private = cdev;
		cdev->ap.recv_message = capi_recv_message;
		cdev->errcode = capi20_register(&cdev->ap);
		retval = (int)cdev->ap.applid;
		if (cdev->errcode) {
			cdev->ap.applid = 0;
			retval = -EIO;
L
Linus Torvalds 已提交
780
		}
781 782 783 784

register_out:
		mutex_unlock(&cdev->lock);
		return retval;
L
Linus Torvalds 已提交
785 786

	case CAPI_GET_VERSION:
787 788 789 790 791 792 793 794 795
		if (copy_from_user(&data.contr, argp,
				   sizeof(data.contr)))
			return -EFAULT;
		cdev->errcode = capi20_get_version(data.contr, &data.version);
		if (cdev->errcode)
			return -EIO;
		if (copy_to_user(argp, &data.version,
				 sizeof(data.version)))
			return -EFAULT;
796
		return 0;
L
Linus Torvalds 已提交
797 798

	case CAPI_GET_SERIAL:
799 800 801 802 803 804 805 806 807
		if (copy_from_user(&data.contr, argp,
				   sizeof(data.contr)))
			return -EFAULT;
		cdev->errcode = capi20_get_serial(data.contr, data.serial);
		if (cdev->errcode)
			return -EIO;
		if (copy_to_user(argp, data.serial,
				 sizeof(data.serial)))
			return -EFAULT;
808 809
		return 0;

L
Linus Torvalds 已提交
810
	case CAPI_GET_PROFILE:
811 812 813
		if (copy_from_user(&data.contr, argp,
				   sizeof(data.contr)))
			return -EFAULT;
L
Linus Torvalds 已提交
814

815 816 817 818
		if (data.contr == 0) {
			cdev->errcode = capi20_get_profile(data.contr, &data.profile);
			if (cdev->errcode)
				return -EIO;
L
Linus Torvalds 已提交
819

820 821 822
			retval = copy_to_user(argp,
					      &data.profile.ncontroller,
					      sizeof(data.profile.ncontroller));
L
Linus Torvalds 已提交
823

824 825 826 827
		} else {
			cdev->errcode = capi20_get_profile(data.contr, &data.profile);
			if (cdev->errcode)
				return -EIO;
L
Linus Torvalds 已提交
828

829 830
			retval = copy_to_user(argp, &data.profile,
					      sizeof(data.profile));
L
Linus Torvalds 已提交
831
		}
832 833
		if (retval)
			return -EFAULT;
834
		return 0;
L
Linus Torvalds 已提交
835 836

	case CAPI_GET_MANUFACTURER:
837 838 839 840 841 842
		if (copy_from_user(&data.contr, argp,
				   sizeof(data.contr)))
			return -EFAULT;
		cdev->errcode = capi20_get_manufacturer(data.contr, data.manufacturer);
		if (cdev->errcode)
			return -EIO;
L
Linus Torvalds 已提交
843

844 845 846
		if (copy_to_user(argp, data.manufacturer,
				 sizeof(data.manufacturer)))
			return -EFAULT;
L
Linus Torvalds 已提交
847

848 849
		return 0;

L
Linus Torvalds 已提交
850 851 852 853 854 855 856 857 858 859 860 861 862 863 864
	case CAPI_GET_ERRCODE:
		data.errcode = cdev->errcode;
		cdev->errcode = CAPI_NOERROR;
		if (arg) {
			if (copy_to_user(argp, &data.errcode,
					 sizeof(data.errcode)))
				return -EFAULT;
		}
		return data.errcode;

	case CAPI_INSTALLED:
		if (capi20_isinstalled() == CAPI_NOERROR)
			return 0;
		return -ENXIO;

865
	case CAPI_MANUFACTURER_CMD: {
866 867 868 869 870 871 872
		struct capi_manufacturer_cmd mcmd;
		if (!capable(CAP_SYS_ADMIN))
			return -EPERM;
		if (copy_from_user(&mcmd, argp, sizeof(mcmd)))
			return -EFAULT;
		return capi20_manufacturer(mcmd.cmd, mcmd.data);
	}
L
Linus Torvalds 已提交
873
	case CAPI_SET_FLAGS:
874 875 876 877 878
	case CAPI_CLR_FLAGS: {
		unsigned userflags;

		if (copy_from_user(&userflags, argp, sizeof(userflags)))
			return -EFAULT;
L
Linus Torvalds 已提交
879

880 881 882 883 884 885 886 887
		mutex_lock(&cdev->lock);
		if (cmd == CAPI_SET_FLAGS)
			cdev->userflags |= userflags;
		else
			cdev->userflags &= ~userflags;
		mutex_unlock(&cdev->lock);
		return 0;
	}
L
Linus Torvalds 已提交
888 889 890 891 892 893
	case CAPI_GET_FLAGS:
		if (copy_to_user(argp, &cdev->userflags,
				 sizeof(cdev->userflags)))
			return -EFAULT;
		return 0;

894 895 896 897 898
#ifndef CONFIG_ISDN_CAPI_MIDDLEWARE
	case CAPI_NCCI_OPENCOUNT:
		return 0;

#else /* CONFIG_ISDN_CAPI_MIDDLEWARE */
899 900 901 902
	case CAPI_NCCI_OPENCOUNT: {
		struct capincci *nccip;
		unsigned ncci;
		int count = 0;
L
Linus Torvalds 已提交
903

904 905 906 907 908 909 910 911 912 913
		if (copy_from_user(&ncci, argp, sizeof(ncci)))
			return -EFAULT;

		mutex_lock(&cdev->lock);
		nccip = capincci_find(cdev, (u32)ncci);
		if (nccip)
			count = capincci_minor_opencount(nccip);
		mutex_unlock(&cdev->lock);
		return count;
	}
L
Linus Torvalds 已提交
914

915 916 917 918 919 920 921 922 923 924 925 926 927 928 929
	case CAPI_NCCI_GETUNIT: {
		struct capincci *nccip;
		struct capiminor *mp;
		unsigned ncci;
		int unit = -ESRCH;

		if (copy_from_user(&ncci, argp, sizeof(ncci)))
			return -EFAULT;

		mutex_lock(&cdev->lock);
		nccip = capincci_find(cdev, (u32)ncci);
		if (nccip) {
			mp = nccip->minorp;
			if (mp)
				unit = mp->minor;
L
Linus Torvalds 已提交
930
		}
931 932 933
		mutex_unlock(&cdev->lock);
		return unit;
	}
L
Linus Torvalds 已提交
934
#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */
935 936 937

	default:
		return -EINVAL;
L
Linus Torvalds 已提交
938 939 940
	}
}

941 942 943 944 945
static long
capi_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	int ret;

946
	mutex_lock(&capi_mutex);
947
	ret = capi_ioctl(file, cmd, arg);
948
	mutex_unlock(&capi_mutex);
949 950 951 952

	return ret;
}

J
Jan Kiszka 已提交
953
static int capi_open(struct inode *inode, struct file *file)
L
Linus Torvalds 已提交
954
{
J
Jan Kiszka 已提交
955 956 957 958 959 960
	struct capidev *cdev;

	cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);
	if (!cdev)
		return -ENOMEM;

961
	mutex_init(&cdev->lock);
J
Jan Kiszka 已提交
962 963
	skb_queue_head_init(&cdev->recvqueue);
	init_waitqueue_head(&cdev->recvwait);
964
	INIT_LIST_HEAD(&cdev->nccis);
J
Jan Kiszka 已提交
965 966 967 968 969 970 971
	file->private_data = cdev;

	mutex_lock(&capidev_list_lock);
	list_add_tail(&cdev->list, &capidev_list);
	mutex_unlock(&capidev_list_lock);

	return nonseekable_open(inode, file);
L
Linus Torvalds 已提交
972 973
}

J
Jan Kiszka 已提交
974
static int capi_release(struct inode *inode, struct file *file)
L
Linus Torvalds 已提交
975
{
J
Jan Kiszka 已提交
976
	struct capidev *cdev = file->private_data;
L
Linus Torvalds 已提交
977

J
Jan Kiszka 已提交
978 979 980 981
	mutex_lock(&capidev_list_lock);
	list_del(&cdev->list);
	mutex_unlock(&capidev_list_lock);

982
	if (cdev->ap.applid)
J
Jan Kiszka 已提交
983 984 985 986 987
		capi20_release(&cdev->ap);
	skb_queue_purge(&cdev->recvqueue);
	capincci_free(cdev, 0xffffffff);

	kfree(cdev);
L
Linus Torvalds 已提交
988 989 990
	return 0;
}

991
static const struct file_operations capi_fops =
L
Linus Torvalds 已提交
992 993 994 995 996 997
{
	.owner		= THIS_MODULE,
	.llseek		= no_llseek,
	.read		= capi_read,
	.write		= capi_write,
	.poll		= capi_poll,
998
	.unlocked_ioctl	= capi_unlocked_ioctl,
L
Linus Torvalds 已提交
999 1000 1001 1002 1003 1004 1005
	.open		= capi_open,
	.release	= capi_release,
};

#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
/* -------- tty_operations for capincci ----------------------------- */

1006 1007
static int
capinc_tty_install(struct tty_driver *driver, struct tty_struct *tty)
L
Linus Torvalds 已提交
1008
{
1009
	struct capiminor *mp = capiminor_get(tty->index);
J
Jiri Slaby 已提交
1010
	int ret = tty_standard_install(driver, tty);
1011

J
Jiri Slaby 已提交
1012
	if (ret == 0)
1013
		tty->driver_data = mp;
J
Jiri Slaby 已提交
1014
	else
1015 1016 1017
		capiminor_put(mp);
	return ret;
}
L
Linus Torvalds 已提交
1018

1019 1020 1021 1022 1023 1024
static void capinc_tty_cleanup(struct tty_struct *tty)
{
	struct capiminor *mp = tty->driver_data;
	tty->driver_data = NULL;
	capiminor_put(mp);
}
L
Linus Torvalds 已提交
1025

1026
static int capinc_tty_open(struct tty_struct *tty, struct file *filp)
1027 1028
{
	struct capiminor *mp = tty->driver_data;
1029 1030 1031 1032 1033
	int err;

	err = tty_port_open(&mp->port, tty, filp);
	if (err)
		return err;
L
Linus Torvalds 已提交
1034 1035 1036 1037 1038

	handle_minor_recv(mp);
	return 0;
}

1039
static void capinc_tty_close(struct tty_struct *tty, struct file *filp)
L
Linus Torvalds 已提交
1040
{
1041
	struct capiminor *mp = tty->driver_data;
L
Linus Torvalds 已提交
1042

1043
	tty_port_close(&mp->port, tty, filp);
L
Linus Torvalds 已提交
1044 1045
}

1046
static int capinc_tty_write(struct tty_struct *tty,
L
Linus Torvalds 已提交
1047 1048
			    const unsigned char *buf, int count)
{
1049
	struct capiminor *mp = tty->driver_data;
L
Linus Torvalds 已提交
1050 1051
	struct sk_buff *skb;

1052
	pr_debug("capinc_tty_write(count=%d)\n", count);
L
Linus Torvalds 已提交
1053

1054 1055
	spin_lock_bh(&mp->outlock);
	skb = mp->outskb;
L
Linus Torvalds 已提交
1056
	if (skb) {
1057 1058
		mp->outskb = NULL;
		__skb_queue_tail(&mp->outqueue, skb);
L
Linus Torvalds 已提交
1059 1060 1061
		mp->outbytes += skb->len;
	}

1062
	skb = alloc_skb(CAPI_DATA_B3_REQ_LEN + count, GFP_ATOMIC);
L
Linus Torvalds 已提交
1063 1064
	if (!skb) {
		printk(KERN_ERR "capinc_tty_write: alloc_skb failed\n");
1065
		spin_unlock_bh(&mp->outlock);
L
Linus Torvalds 已提交
1066 1067 1068 1069
		return -ENOMEM;
	}

	skb_reserve(skb, CAPI_DATA_B3_REQ_LEN);
1070
	skb_put_data(skb, buf, count);
L
Linus Torvalds 已提交
1071

1072
	__skb_queue_tail(&mp->outqueue, skb);
L
Linus Torvalds 已提交
1073
	mp->outbytes += skb->len;
1074 1075
	spin_unlock_bh(&mp->outlock);

1076
	handle_minor_send(mp);
1077

L
Linus Torvalds 已提交
1078 1079 1080
	return count;
}

A
Alan Cox 已提交
1081
static int capinc_tty_put_char(struct tty_struct *tty, unsigned char ch)
L
Linus Torvalds 已提交
1082
{
1083
	struct capiminor *mp = tty->driver_data;
1084
	bool invoke_send = false;
L
Linus Torvalds 已提交
1085
	struct sk_buff *skb;
A
Alan Cox 已提交
1086
	int ret = 1;
L
Linus Torvalds 已提交
1087

1088
	pr_debug("capinc_put_char(%u)\n", ch);
L
Linus Torvalds 已提交
1089

1090 1091
	spin_lock_bh(&mp->outlock);
	skb = mp->outskb;
L
Linus Torvalds 已提交
1092 1093
	if (skb) {
		if (skb_tailroom(skb) > 0) {
1094
			skb_put_u8(skb, ch);
1095
			goto unlock_out;
L
Linus Torvalds 已提交
1096
		}
1097 1098
		mp->outskb = NULL;
		__skb_queue_tail(&mp->outqueue, skb);
L
Linus Torvalds 已提交
1099
		mp->outbytes += skb->len;
1100
		invoke_send = true;
L
Linus Torvalds 已提交
1101
	}
1102

1103
	skb = alloc_skb(CAPI_DATA_B3_REQ_LEN + CAPI_MAX_BLKSIZE, GFP_ATOMIC);
L
Linus Torvalds 已提交
1104 1105
	if (skb) {
		skb_reserve(skb, CAPI_DATA_B3_REQ_LEN);
1106
		skb_put_u8(skb, ch);
1107
		mp->outskb = skb;
L
Linus Torvalds 已提交
1108 1109
	} else {
		printk(KERN_ERR "capinc_put_char: char %u lost\n", ch);
A
Alan Cox 已提交
1110
		ret = 0;
L
Linus Torvalds 已提交
1111
	}
1112 1113 1114 1115 1116

unlock_out:
	spin_unlock_bh(&mp->outlock);

	if (invoke_send)
1117
		handle_minor_send(mp);
1118

A
Alan Cox 已提交
1119
	return ret;
L
Linus Torvalds 已提交
1120 1121 1122 1123
}

static void capinc_tty_flush_chars(struct tty_struct *tty)
{
1124
	struct capiminor *mp = tty->driver_data;
L
Linus Torvalds 已提交
1125 1126
	struct sk_buff *skb;

1127
	pr_debug("capinc_tty_flush_chars\n");
L
Linus Torvalds 已提交
1128

1129 1130
	spin_lock_bh(&mp->outlock);
	skb = mp->outskb;
L
Linus Torvalds 已提交
1131
	if (skb) {
1132 1133
		mp->outskb = NULL;
		__skb_queue_tail(&mp->outqueue, skb);
L
Linus Torvalds 已提交
1134
		mp->outbytes += skb->len;
1135 1136
		spin_unlock_bh(&mp->outlock);

1137
		handle_minor_send(mp);
1138 1139 1140 1141
	} else
		spin_unlock_bh(&mp->outlock);

	handle_minor_recv(mp);
L
Linus Torvalds 已提交
1142 1143 1144 1145
}

static int capinc_tty_write_room(struct tty_struct *tty)
{
1146
	struct capiminor *mp = tty->driver_data;
L
Linus Torvalds 已提交
1147
	int room;
1148

L
Linus Torvalds 已提交
1149 1150
	room = CAPINC_MAX_SENDQUEUE-skb_queue_len(&mp->outqueue);
	room *= CAPI_MAX_BLKSIZE;
1151
	pr_debug("capinc_tty_write_room = %d\n", room);
L
Linus Torvalds 已提交
1152 1153 1154
	return room;
}

A
Adrian Bunk 已提交
1155
static int capinc_tty_chars_in_buffer(struct tty_struct *tty)
L
Linus Torvalds 已提交
1156
{
1157 1158
	struct capiminor *mp = tty->driver_data;

1159 1160 1161 1162
	pr_debug("capinc_tty_chars_in_buffer = %d nack=%d sq=%d rq=%d\n",
		 mp->outbytes, mp->nack,
		 skb_queue_len(&mp->outqueue),
		 skb_queue_len(&mp->inqueue));
L
Linus Torvalds 已提交
1163 1164 1165
	return mp->outbytes;
}

1166
static int capinc_tty_ioctl(struct tty_struct *tty,
1167
			    unsigned int cmd, unsigned long arg)
L
Linus Torvalds 已提交
1168
{
1169
	return -ENOIOCTLCMD;
L
Linus Torvalds 已提交
1170 1171
}

1172
static void capinc_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
L
Linus Torvalds 已提交
1173
{
1174
	pr_debug("capinc_tty_set_termios\n");
L
Linus Torvalds 已提交
1175 1176
}

1177
static void capinc_tty_throttle(struct tty_struct *tty)
L
Linus Torvalds 已提交
1178
{
1179
	struct capiminor *mp = tty->driver_data;
1180
	pr_debug("capinc_tty_throttle\n");
1181
	mp->ttyinstop = 1;
L
Linus Torvalds 已提交
1182 1183
}

1184
static void capinc_tty_unthrottle(struct tty_struct *tty)
L
Linus Torvalds 已提交
1185
{
1186 1187
	struct capiminor *mp = tty->driver_data;

1188
	pr_debug("capinc_tty_unthrottle\n");
1189 1190
	mp->ttyinstop = 0;
	handle_minor_recv(mp);
L
Linus Torvalds 已提交
1191 1192 1193 1194
}

static void capinc_tty_stop(struct tty_struct *tty)
{
1195 1196
	struct capiminor *mp = tty->driver_data;

1197
	pr_debug("capinc_tty_stop\n");
1198
	mp->ttyoutstop = 1;
L
Linus Torvalds 已提交
1199 1200 1201 1202
}

static void capinc_tty_start(struct tty_struct *tty)
{
1203 1204
	struct capiminor *mp = tty->driver_data;

1205
	pr_debug("capinc_tty_start\n");
1206
	mp->ttyoutstop = 0;
1207
	handle_minor_send(mp);
L
Linus Torvalds 已提交
1208 1209 1210 1211
}

static void capinc_tty_hangup(struct tty_struct *tty)
{
1212 1213
	struct capiminor *mp = tty->driver_data;

1214
	pr_debug("capinc_tty_hangup\n");
1215
	tty_port_hangup(&mp->port);
L
Linus Torvalds 已提交
1216 1217
}

A
Alan Cox 已提交
1218
static int capinc_tty_break_ctl(struct tty_struct *tty, int state)
L
Linus Torvalds 已提交
1219
{
1220
	pr_debug("capinc_tty_break_ctl(%d)\n", state);
A
Alan Cox 已提交
1221
	return 0;
L
Linus Torvalds 已提交
1222 1223 1224 1225
}

static void capinc_tty_flush_buffer(struct tty_struct *tty)
{
1226
	pr_debug("capinc_tty_flush_buffer\n");
L
Linus Torvalds 已提交
1227 1228 1229 1230
}

static void capinc_tty_set_ldisc(struct tty_struct *tty)
{
1231
	pr_debug("capinc_tty_set_ldisc\n");
L
Linus Torvalds 已提交
1232 1233 1234 1235
}

static void capinc_tty_send_xchar(struct tty_struct *tty, char ch)
{
1236
	pr_debug("capinc_tty_send_xchar(%d)\n", ch);
L
Linus Torvalds 已提交
1237 1238
}

J
Jeff Dike 已提交
1239
static const struct tty_operations capinc_ops = {
L
Linus Torvalds 已提交
1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257
	.open = capinc_tty_open,
	.close = capinc_tty_close,
	.write = capinc_tty_write,
	.put_char = capinc_tty_put_char,
	.flush_chars = capinc_tty_flush_chars,
	.write_room = capinc_tty_write_room,
	.chars_in_buffer = capinc_tty_chars_in_buffer,
	.ioctl = capinc_tty_ioctl,
	.set_termios = capinc_tty_set_termios,
	.throttle = capinc_tty_throttle,
	.unthrottle = capinc_tty_unthrottle,
	.stop = capinc_tty_stop,
	.start = capinc_tty_start,
	.hangup = capinc_tty_hangup,
	.break_ctl = capinc_tty_break_ctl,
	.flush_buffer = capinc_tty_flush_buffer,
	.set_ldisc = capinc_tty_set_ldisc,
	.send_xchar = capinc_tty_send_xchar,
1258 1259
	.install = capinc_tty_install,
	.cleanup = capinc_tty_cleanup,
L
Linus Torvalds 已提交
1260 1261
};

J
Jan Kiszka 已提交
1262
static int __init capinc_tty_init(void)
L
Linus Torvalds 已提交
1263 1264
{
	struct tty_driver *drv;
J
Jan Kiszka 已提交
1265 1266
	int err;

L
Linus Torvalds 已提交
1267 1268 1269 1270 1271
	if (capi_ttyminors > CAPINC_MAX_PORTS)
		capi_ttyminors = CAPINC_MAX_PORTS;
	if (capi_ttyminors <= 0)
		capi_ttyminors = CAPINC_NR_PORTS;

K
Kees Cook 已提交
1272
	capiminors = kcalloc(capi_ttyminors, sizeof(struct capiminor *),
1273 1274
			     GFP_KERNEL);
	if (!capiminors)
L
Linus Torvalds 已提交
1275 1276
		return -ENOMEM;

1277 1278 1279 1280 1281
	drv = alloc_tty_driver(capi_ttyminors);
	if (!drv) {
		kfree(capiminors);
		return -ENOMEM;
	}
L
Linus Torvalds 已提交
1282
	drv->driver_name = "capi_nc";
1283
	drv->name = "capi!";
1284
	drv->major = 0;
L
Linus Torvalds 已提交
1285 1286 1287 1288 1289 1290 1291 1292
	drv->minor_start = 0;
	drv->type = TTY_DRIVER_TYPE_SERIAL;
	drv->subtype = SERIAL_TYPE_NORMAL;
	drv->init_termios = tty_std_termios;
	drv->init_termios.c_iflag = ICRNL;
	drv->init_termios.c_oflag = OPOST | ONLCR;
	drv->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
	drv->init_termios.c_lflag = 0;
1293 1294 1295
	drv->flags =
		TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS |
		TTY_DRIVER_DYNAMIC_DEV;
L
Linus Torvalds 已提交
1296
	tty_set_operations(drv, &capinc_ops);
J
Jan Kiszka 已提交
1297 1298 1299

	err = tty_register_driver(drv);
	if (err) {
L
Linus Torvalds 已提交
1300
		put_tty_driver(drv);
1301
		kfree(capiminors);
L
Linus Torvalds 已提交
1302
		printk(KERN_ERR "Couldn't register capi_nc driver\n");
J
Jan Kiszka 已提交
1303
		return err;
L
Linus Torvalds 已提交
1304 1305 1306 1307 1308
	}
	capinc_tty_driver = drv;
	return 0;
}

J
Jan Kiszka 已提交
1309
static void __exit capinc_tty_exit(void)
L
Linus Torvalds 已提交
1310
{
J
Jan Kiszka 已提交
1311 1312
	tty_unregister_driver(capinc_tty_driver);
	put_tty_driver(capinc_tty_driver);
1313
	kfree(capiminors);
L
Linus Torvalds 已提交
1314 1315
}

1316 1317 1318 1319 1320 1321 1322 1323 1324 1325
#else /* !CONFIG_ISDN_CAPI_MIDDLEWARE */

static inline int capinc_tty_init(void)
{
	return 0;
}

static inline void capinc_tty_exit(void) { }

#endif /* !CONFIG_ISDN_CAPI_MIDDLEWARE */
L
Linus Torvalds 已提交
1326 1327 1328 1329 1330 1331 1332

/* -------- /proc functions ----------------------------------------- */

/*
 * /proc/capi/capi20:
 *  minor applid nrecvctlpkt nrecvdatapkt nsendctlpkt nsenddatapkt
 */
1333
static int __maybe_unused capi20_proc_show(struct seq_file *m, void *v)
L
Linus Torvalds 已提交
1334
{
1335
	struct capidev *cdev;
L
Linus Torvalds 已提交
1336 1337
	struct list_head *l;

1338
	mutex_lock(&capidev_list_lock);
L
Linus Torvalds 已提交
1339 1340
	list_for_each(l, &capidev_list) {
		cdev = list_entry(l, struct capidev, list);
1341
		seq_printf(m, "0 %d %lu %lu %lu %lu\n",
1342 1343 1344 1345 1346
			   cdev->ap.applid,
			   cdev->ap.nrecvctlpkt,
			   cdev->ap.nrecvdatapkt,
			   cdev->ap.nsentctlpkt,
			   cdev->ap.nsentdatapkt);
L
Linus Torvalds 已提交
1347
	}
1348
	mutex_unlock(&capidev_list_lock);
1349
	return 0;
L
Linus Torvalds 已提交
1350 1351 1352 1353 1354 1355
}

/*
 * /proc/capi/capi20ncci:
 *  applid ncci
 */
1356
static int __maybe_unused capi20ncci_proc_show(struct seq_file *m, void *v)
L
Linus Torvalds 已提交
1357
{
1358 1359
	struct capidev *cdev;
	struct capincci *np;
L
Linus Torvalds 已提交
1360

1361
	mutex_lock(&capidev_list_lock);
1362
	list_for_each_entry(cdev, &capidev_list, list) {
1363
		mutex_lock(&cdev->lock);
1364 1365
		list_for_each_entry(np, &cdev->nccis, list)
			seq_printf(m, "%d 0x%x\n", cdev->ap.applid, np->ncci);
1366
		mutex_unlock(&cdev->lock);
L
Linus Torvalds 已提交
1367
	}
1368
	mutex_unlock(&capidev_list_lock);
1369
	return 0;
L
Linus Torvalds 已提交
1370 1371 1372 1373
}

static void __init proc_init(void)
{
1374 1375
	proc_create_single("capi/capi20", 0, NULL, capi20_proc_show);
	proc_create_single("capi/capi20ncci", 0, NULL, capi20ncci_proc_show);
L
Linus Torvalds 已提交
1376 1377 1378 1379
}

static void __exit proc_exit(void)
{
1380 1381
	remove_proc_entry("capi/capi20", NULL);
	remove_proc_entry("capi/capi20ncci", NULL);
L
Linus Torvalds 已提交
1382 1383 1384 1385 1386 1387 1388
}

/* -------- init function and module interface ---------------------- */


static int __init capi_init(void)
{
1389
	const char *compileinfo;
1390
	int major_ret;
L
Linus Torvalds 已提交
1391

1392 1393
	major_ret = register_chrdev(capi_major, "capi20", &capi_fops);
	if (major_ret < 0) {
L
Linus Torvalds 已提交
1394
		printk(KERN_ERR "capi20: unable to get major %d\n", capi_major);
1395
		return major_ret;
L
Linus Torvalds 已提交
1396
	}
1397
	capi_class = class_create(THIS_MODULE, "capi");
L
Linus Torvalds 已提交
1398 1399 1400 1401 1402
	if (IS_ERR(capi_class)) {
		unregister_chrdev(capi_major, "capi20");
		return PTR_ERR(capi_class);
	}

1403
	device_create(capi_class, NULL, MKDEV(capi_major, 0), NULL, "capi20");
L
Linus Torvalds 已提交
1404 1405

	if (capinc_tty_init() < 0) {
1406
		device_destroy(capi_class, MKDEV(capi_major, 0));
1407
		class_destroy(capi_class);
L
Linus Torvalds 已提交
1408 1409 1410 1411 1412 1413
		unregister_chrdev(capi_major, "capi20");
		return -ENOMEM;
	}

	proc_init();

1414
#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE
1415
	compileinfo = " (middleware)";
L
Linus Torvalds 已提交
1416
#else
1417
	compileinfo = " (no middleware)";
L
Linus Torvalds 已提交
1418
#endif
1419 1420
	printk(KERN_NOTICE "CAPI 2.0 started up with major %d%s\n",
	       capi_major, compileinfo);
L
Linus Torvalds 已提交
1421 1422 1423 1424 1425 1426 1427 1428

	return 0;
}

static void __exit capi_exit(void)
{
	proc_exit();

1429
	device_destroy(capi_class, MKDEV(capi_major, 0));
1430
	class_destroy(capi_class);
L
Linus Torvalds 已提交
1431 1432 1433 1434 1435 1436 1437
	unregister_chrdev(capi_major, "capi20");

	capinc_tty_exit();
}

module_init(capi_init);
module_exit(capi_exit);