brintos

brintos / linux-shallow public Read only

0
0
Text · 31.7 KiB · 70dee9a Raw
1443 lines · c
1/* $Id: capi.c,v 1.1.2.7 2004/04/28 09:48:59 armin Exp $2 *3 * CAPI 2.0 Interface for Linux4 *5 * Copyright 1996 by Carsten Paeth <calle@calle.de>6 *7 * This software may be used and distributed according to the terms8 * 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/ethtool.h>15#include <linux/errno.h>16#include <linux/kernel.h>17#include <linux/major.h>18#include <linux/sched.h>19#include <linux/slab.h>20#include <linux/fcntl.h>21#include <linux/fs.h>22#include <linux/signal.h>23#include <linux/mutex.h>24#include <linux/mm.h>25#include <linux/timer.h>26#include <linux/wait.h>27#include <linux/tty.h>28#include <linux/netdevice.h>29#include <linux/ppp_defs.h>30#include <linux/ppp-ioctl.h>31#include <linux/skbuff.h>32#include <linux/proc_fs.h>33#include <linux/seq_file.h>34#include <linux/poll.h>35#include <linux/capi.h>36#include <linux/kernelcapi.h>37#include <linux/init.h>38#include <linux/device.h>39#include <linux/moduleparam.h>40#include <linux/isdn/capiutil.h>41#include <linux/isdn/capicmd.h>42 43#include "kcapi.h"44 45MODULE_DESCRIPTION("CAPI4Linux: kernel CAPI layer and /dev/capi20 interface");46MODULE_AUTHOR("Carsten Paeth");47MODULE_LICENSE("GPL");48 49/* -------- driver information -------------------------------------- */50 51static DEFINE_MUTEX(capi_mutex);52static const struct class capi_class = {53	.name = "capi",54};55static int capi_major = 68;		/* allocated */56 57module_param_named(major, capi_major, uint, 0);58 59#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE60#define CAPINC_NR_PORTS		3261#define CAPINC_MAX_PORTS	25662 63static int capi_ttyminors = CAPINC_NR_PORTS;64 65module_param_named(ttyminors, capi_ttyminors, uint, 0);66#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */67 68/* -------- defines ------------------------------------------------- */69 70#define CAPINC_MAX_RECVQUEUE	1071#define CAPINC_MAX_SENDQUEUE	1072#define CAPI_MAX_BLKSIZE	204873 74/* -------- data structures ----------------------------------------- */75 76struct capidev;77struct capincci;78struct capiminor;79 80struct ackqueue_entry {81	struct list_head	list;82	u16			datahandle;83};84 85struct capiminor {86	unsigned int      minor;87 88	struct capi20_appl	*ap;89	u32			ncci;90	atomic_t		datahandle;91	atomic_t		msgid;92 93	struct tty_port port;94	int                ttyinstop;95	int                ttyoutstop;96 97	struct sk_buff_head	inqueue;98 99	struct sk_buff_head	outqueue;100	int			outbytes;101	struct sk_buff		*outskb;102	spinlock_t		outlock;103 104	/* transmit path */105	struct list_head ackqueue;106	int nack;107	spinlock_t ackqlock;108};109 110struct capincci {111	struct list_head list;112	u32		 ncci;113	struct capidev	*cdev;114#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE115	struct capiminor *minorp;116#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */117};118 119struct capidev {120	struct list_head list;121	struct capi20_appl ap;122	u16		errcode;123	unsigned        userflags;124 125	struct sk_buff_head recvqueue;126	wait_queue_head_t recvwait;127 128	struct list_head nccis;129 130	struct mutex lock;131};132 133/* -------- global variables ---------------------------------------- */134 135static DEFINE_MUTEX(capidev_list_lock);136static LIST_HEAD(capidev_list);137 138#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE139 140static DEFINE_SPINLOCK(capiminors_lock);141static struct capiminor **capiminors;142 143static struct tty_driver *capinc_tty_driver;144 145/* -------- datahandles --------------------------------------------- */146 147static int capiminor_add_ack(struct capiminor *mp, u16 datahandle)148{149	struct ackqueue_entry *n;150 151	n = kmalloc(sizeof(*n), GFP_ATOMIC);152	if (unlikely(!n)) {153		printk(KERN_ERR "capi: alloc datahandle failed\n");154		return -1;155	}156	n->datahandle = datahandle;157	INIT_LIST_HEAD(&n->list);158	spin_lock_bh(&mp->ackqlock);159	list_add_tail(&n->list, &mp->ackqueue);160	mp->nack++;161	spin_unlock_bh(&mp->ackqlock);162	return 0;163}164 165static int capiminor_del_ack(struct capiminor *mp, u16 datahandle)166{167	struct ackqueue_entry *p, *tmp;168 169	spin_lock_bh(&mp->ackqlock);170	list_for_each_entry_safe(p, tmp, &mp->ackqueue, list) {171		if (p->datahandle == datahandle) {172			list_del(&p->list);173			mp->nack--;174			spin_unlock_bh(&mp->ackqlock);175			kfree(p);176			return 0;177		}178	}179	spin_unlock_bh(&mp->ackqlock);180	return -1;181}182 183static void capiminor_del_all_ack(struct capiminor *mp)184{185	struct ackqueue_entry *p, *tmp;186 187	list_for_each_entry_safe(p, tmp, &mp->ackqueue, list) {188		list_del(&p->list);189		kfree(p);190		mp->nack--;191	}192}193 194 195/* -------- struct capiminor ---------------------------------------- */196 197static void capiminor_destroy(struct tty_port *port)198{199	struct capiminor *mp = container_of(port, struct capiminor, port);200 201	kfree_skb(mp->outskb);202	skb_queue_purge(&mp->inqueue);203	skb_queue_purge(&mp->outqueue);204	capiminor_del_all_ack(mp);205	kfree(mp);206}207 208static const struct tty_port_operations capiminor_port_ops = {209	.destruct = capiminor_destroy,210};211 212static struct capiminor *capiminor_alloc(struct capi20_appl *ap, u32 ncci)213{214	struct capiminor *mp;215	struct device *dev;216	unsigned int minor;217 218	mp = kzalloc(sizeof(*mp), GFP_KERNEL);219	if (!mp) {220		printk(KERN_ERR "capi: can't alloc capiminor\n");221		return NULL;222	}223 224	mp->ap = ap;225	mp->ncci = ncci;226	INIT_LIST_HEAD(&mp->ackqueue);227	spin_lock_init(&mp->ackqlock);228 229	skb_queue_head_init(&mp->inqueue);230	skb_queue_head_init(&mp->outqueue);231	spin_lock_init(&mp->outlock);232 233	tty_port_init(&mp->port);234	mp->port.ops = &capiminor_port_ops;235 236	/* Allocate the least unused minor number. */237	spin_lock(&capiminors_lock);238	for (minor = 0; minor < capi_ttyminors; minor++)239		if (!capiminors[minor]) {240			capiminors[minor] = mp;241			break;242		}243	spin_unlock(&capiminors_lock);244 245	if (minor == capi_ttyminors) {246		printk(KERN_NOTICE "capi: out of minors\n");247		goto err_out1;248	}249 250	mp->minor = minor;251 252	dev = tty_port_register_device(&mp->port, capinc_tty_driver, minor,253			NULL);254	if (IS_ERR(dev))255		goto err_out2;256 257	return mp;258 259err_out2:260	spin_lock(&capiminors_lock);261	capiminors[minor] = NULL;262	spin_unlock(&capiminors_lock);263 264err_out1:265	tty_port_put(&mp->port);266	return NULL;267}268 269static struct capiminor *capiminor_get(unsigned int minor)270{271	struct capiminor *mp;272 273	spin_lock(&capiminors_lock);274	mp = capiminors[minor];275	if (mp)276		tty_port_get(&mp->port);277	spin_unlock(&capiminors_lock);278 279	return mp;280}281 282static inline void capiminor_put(struct capiminor *mp)283{284	tty_port_put(&mp->port);285}286 287static void capiminor_free(struct capiminor *mp)288{289	tty_unregister_device(capinc_tty_driver, mp->minor);290 291	spin_lock(&capiminors_lock);292	capiminors[mp->minor] = NULL;293	spin_unlock(&capiminors_lock);294 295	capiminor_put(mp);296}297 298/* -------- struct capincci ----------------------------------------- */299 300static void capincci_alloc_minor(struct capidev *cdev, struct capincci *np)301{302	if (cdev->userflags & CAPIFLAG_HIGHJACKING)303		np->minorp = capiminor_alloc(&cdev->ap, np->ncci);304}305 306static void capincci_free_minor(struct capincci *np)307{308	struct capiminor *mp = np->minorp;309	struct tty_struct *tty;310 311	if (mp) {312		tty = tty_port_tty_get(&mp->port);313		if (tty) {314			tty_vhangup(tty);315			tty_kref_put(tty);316		}317 318		capiminor_free(mp);319	}320}321 322static inline unsigned int capincci_minor_opencount(struct capincci *np)323{324	struct capiminor *mp = np->minorp;325	unsigned int count = 0;326	struct tty_struct *tty;327 328	if (mp) {329		tty = tty_port_tty_get(&mp->port);330		if (tty) {331			count = tty->count;332			tty_kref_put(tty);333		}334	}335	return count;336}337 338#else /* !CONFIG_ISDN_CAPI_MIDDLEWARE */339 340static inline void341capincci_alloc_minor(struct capidev *cdev, struct capincci *np) { }342static inline void capincci_free_minor(struct capincci *np) { }343 344#endif /* !CONFIG_ISDN_CAPI_MIDDLEWARE */345 346static 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 363static 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#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE376static struct capincci *capincci_find(struct capidev *cdev, u32 ncci)377{378	struct capincci *np;379 380	list_for_each_entry(np, &cdev->nccis, list)381		if (np->ncci == ncci)382			return np;383	return NULL;384}385 386/* -------- handle data queue --------------------------------------- */387 388static struct sk_buff *389gen_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 407static 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 469free_skb:470	ret = 0;471	kfree_skb(skb);472 473deref_ldisc:474	tty_ldisc_deref(ld);475 476deref_tty:477	tty_kref_put(tty);478	return ret;479}480 481static 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 492static 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 574static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb)575{576	struct capidev *cdev = ap->private;577#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE578	struct capiminor *mp;579	u16 datahandle;580	struct capincci *np;581#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */582 583	mutex_lock(&cdev->lock);584 585	if (CAPIMSG_CMD(skb->data) == CAPI_CONNECT_B3_CONF) {586		u16 info = CAPIMSG_U16(skb->data, 12); // Info field587		if ((info & 0xff00) == 0)588			capincci_alloc(cdev, CAPIMSG_NCCI(skb->data));589	}590	if (CAPIMSG_CMD(skb->data) == CAPI_CONNECT_B3_IND)591		capincci_alloc(cdev, CAPIMSG_NCCI(skb->data));592 593	if (CAPIMSG_COMMAND(skb->data) != CAPI_DATA_B3) {594		skb_queue_tail(&cdev->recvqueue, skb);595		wake_up_interruptible(&cdev->recvwait);596		goto unlock_out;597	}598 599#ifndef CONFIG_ISDN_CAPI_MIDDLEWARE600	skb_queue_tail(&cdev->recvqueue, skb);601	wake_up_interruptible(&cdev->recvwait);602 603#else /* CONFIG_ISDN_CAPI_MIDDLEWARE */604 605	np = capincci_find(cdev, CAPIMSG_CONTROL(skb->data));606	if (!np) {607		printk(KERN_ERR "BUG: capi_signal: ncci not found\n");608		skb_queue_tail(&cdev->recvqueue, skb);609		wake_up_interruptible(&cdev->recvwait);610		goto unlock_out;611	}612 613	mp = np->minorp;614	if (!mp) {615		skb_queue_tail(&cdev->recvqueue, skb);616		wake_up_interruptible(&cdev->recvwait);617		goto unlock_out;618	}619	if (CAPIMSG_SUBCOMMAND(skb->data) == CAPI_IND) {620		datahandle = CAPIMSG_U16(skb->data, CAPIMSG_BASELEN + 4 + 4 + 2);621		pr_debug("capi_signal: DATA_B3_IND %u len=%d\n",622			 datahandle, skb->len-CAPIMSG_LEN(skb->data));623		skb_queue_tail(&mp->inqueue, skb);624 625		handle_minor_recv(mp);626 627	} else if (CAPIMSG_SUBCOMMAND(skb->data) == CAPI_CONF) {628 629		datahandle = CAPIMSG_U16(skb->data, CAPIMSG_BASELEN + 4);630		pr_debug("capi_signal: DATA_B3_CONF %u 0x%x\n",631			 datahandle,632			 CAPIMSG_U16(skb->data, CAPIMSG_BASELEN + 4 + 2));633		kfree_skb(skb);634		capiminor_del_ack(mp, datahandle);635		tty_port_tty_wakeup(&mp->port);636		handle_minor_send(mp);637 638	} else {639		/* ups, let capi application handle it :-) */640		skb_queue_tail(&cdev->recvqueue, skb);641		wake_up_interruptible(&cdev->recvwait);642	}643#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */644 645unlock_out:646	mutex_unlock(&cdev->lock);647}648 649/* -------- file_operations for capidev ----------------------------- */650 651static ssize_t652capi_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)653{654	struct capidev *cdev = file->private_data;655	struct sk_buff *skb;656	size_t copied;657	int err;658 659	if (!cdev->ap.applid)660		return -ENODEV;661 662	skb = skb_dequeue(&cdev->recvqueue);663	if (!skb) {664		if (file->f_flags & O_NONBLOCK)665			return -EAGAIN;666		err = wait_event_interruptible(cdev->recvwait,667					       (skb = skb_dequeue(&cdev->recvqueue)));668		if (err)669			return err;670	}671	if (skb->len > count) {672		skb_queue_head(&cdev->recvqueue, skb);673		return -EMSGSIZE;674	}675	if (copy_to_user(buf, skb->data, skb->len)) {676		skb_queue_head(&cdev->recvqueue, skb);677		return -EFAULT;678	}679	copied = skb->len;680 681	kfree_skb(skb);682 683	return copied;684}685 686static ssize_t687capi_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)688{689	struct capidev *cdev = file->private_data;690	struct sk_buff *skb;691	u16 mlen;692 693	if (!cdev->ap.applid)694		return -ENODEV;695 696	if (count < CAPIMSG_BASELEN)697		return -EINVAL;698 699	skb = alloc_skb(count, GFP_USER);700	if (!skb)701		return -ENOMEM;702 703	if (copy_from_user(skb_put(skb, count), buf, count)) {704		kfree_skb(skb);705		return -EFAULT;706	}707	mlen = CAPIMSG_LEN(skb->data);708	if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3_REQ) {709		if (count < CAPI_DATA_B3_REQ_LEN ||710		    (size_t)(mlen + CAPIMSG_DATALEN(skb->data)) != count) {711			kfree_skb(skb);712			return -EINVAL;713		}714	} else {715		if (mlen != count) {716			kfree_skb(skb);717			return -EINVAL;718		}719	}720	CAPIMSG_SETAPPID(skb->data, cdev->ap.applid);721 722	if (CAPIMSG_CMD(skb->data) == CAPI_DISCONNECT_B3_RESP) {723		if (count < CAPI_DISCONNECT_B3_RESP_LEN) {724			kfree_skb(skb);725			return -EINVAL;726		}727		mutex_lock(&cdev->lock);728		capincci_free(cdev, CAPIMSG_NCCI(skb->data));729		mutex_unlock(&cdev->lock);730	}731 732	cdev->errcode = capi20_put_message(&cdev->ap, skb);733 734	if (cdev->errcode) {735		kfree_skb(skb);736		return -EIO;737	}738	return count;739}740 741static __poll_t742capi_poll(struct file *file, poll_table *wait)743{744	struct capidev *cdev = file->private_data;745	__poll_t mask = 0;746 747	if (!cdev->ap.applid)748		return EPOLLERR;749 750	poll_wait(file, &(cdev->recvwait), wait);751	mask = EPOLLOUT | EPOLLWRNORM;752	if (!skb_queue_empty_lockless(&cdev->recvqueue))753		mask |= EPOLLIN | EPOLLRDNORM;754	return mask;755}756 757static int758capi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)759{760	struct capidev *cdev = file->private_data;761	capi_ioctl_struct data;762	int retval = -EINVAL;763	void __user *argp = (void __user *)arg;764 765	switch (cmd) {766	case CAPI_REGISTER:767		mutex_lock(&cdev->lock);768 769		if (cdev->ap.applid) {770			retval = -EEXIST;771			goto register_out;772		}773		if (copy_from_user(&cdev->ap.rparam, argp,774				   sizeof(struct capi_register_params))) {775			retval = -EFAULT;776			goto register_out;777		}778		cdev->ap.private = cdev;779		cdev->ap.recv_message = capi_recv_message;780		cdev->errcode = capi20_register(&cdev->ap);781		retval = (int)cdev->ap.applid;782		if (cdev->errcode) {783			cdev->ap.applid = 0;784			retval = -EIO;785		}786 787register_out:788		mutex_unlock(&cdev->lock);789		return retval;790 791	case CAPI_GET_VERSION:792		if (copy_from_user(&data.contr, argp,793				   sizeof(data.contr)))794			return -EFAULT;795		cdev->errcode = capi20_get_version(data.contr, &data.version);796		if (cdev->errcode)797			return -EIO;798		if (copy_to_user(argp, &data.version,799				 sizeof(data.version)))800			return -EFAULT;801		return 0;802 803	case CAPI_GET_SERIAL: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		return 0;814 815	case CAPI_GET_PROFILE:816		if (copy_from_user(&data.contr, argp,817				   sizeof(data.contr)))818			return -EFAULT;819 820		if (data.contr == 0) {821			cdev->errcode = capi20_get_profile(data.contr, &data.profile);822			if (cdev->errcode)823				return -EIO;824 825			retval = copy_to_user(argp,826					      &data.profile.ncontroller,827					      sizeof(data.profile.ncontroller));828 829		} else {830			cdev->errcode = capi20_get_profile(data.contr, &data.profile);831			if (cdev->errcode)832				return -EIO;833 834			retval = copy_to_user(argp, &data.profile,835					      sizeof(data.profile));836		}837		if (retval)838			return -EFAULT;839		return 0;840 841	case CAPI_GET_MANUFACTURER:842		if (copy_from_user(&data.contr, argp,843				   sizeof(data.contr)))844			return -EFAULT;845		cdev->errcode = capi20_get_manufacturer(data.contr, data.manufacturer);846		if (cdev->errcode)847			return -EIO;848 849		if (copy_to_user(argp, data.manufacturer,850				 sizeof(data.manufacturer)))851			return -EFAULT;852 853		return 0;854 855	case CAPI_GET_ERRCODE:856		data.errcode = cdev->errcode;857		cdev->errcode = CAPI_NOERROR;858		if (arg) {859			if (copy_to_user(argp, &data.errcode,860					 sizeof(data.errcode)))861				return -EFAULT;862		}863		return data.errcode;864 865	case CAPI_INSTALLED:866		if (capi20_isinstalled() == CAPI_NOERROR)867			return 0;868		return -ENXIO;869 870	case CAPI_MANUFACTURER_CMD: {871		struct capi_manufacturer_cmd mcmd;872		if (!capable(CAP_SYS_ADMIN))873			return -EPERM;874		if (copy_from_user(&mcmd, argp, sizeof(mcmd)))875			return -EFAULT;876		return capi20_manufacturer(mcmd.cmd, mcmd.data);877	}878	case CAPI_SET_FLAGS:879	case CAPI_CLR_FLAGS: {880		unsigned userflags;881 882		if (copy_from_user(&userflags, argp, sizeof(userflags)))883			return -EFAULT;884 885		mutex_lock(&cdev->lock);886		if (cmd == CAPI_SET_FLAGS)887			cdev->userflags |= userflags;888		else889			cdev->userflags &= ~userflags;890		mutex_unlock(&cdev->lock);891		return 0;892	}893	case CAPI_GET_FLAGS:894		if (copy_to_user(argp, &cdev->userflags,895				 sizeof(cdev->userflags)))896			return -EFAULT;897		return 0;898 899#ifndef CONFIG_ISDN_CAPI_MIDDLEWARE900	case CAPI_NCCI_OPENCOUNT:901		return 0;902 903#else /* CONFIG_ISDN_CAPI_MIDDLEWARE */904	case CAPI_NCCI_OPENCOUNT: {905		struct capincci *nccip;906		unsigned ncci;907		int count = 0;908 909		if (copy_from_user(&ncci, argp, sizeof(ncci)))910			return -EFAULT;911 912		mutex_lock(&cdev->lock);913		nccip = capincci_find(cdev, (u32)ncci);914		if (nccip)915			count = capincci_minor_opencount(nccip);916		mutex_unlock(&cdev->lock);917		return count;918	}919 920	case CAPI_NCCI_GETUNIT: {921		struct capincci *nccip;922		struct capiminor *mp;923		unsigned ncci;924		int unit = -ESRCH;925 926		if (copy_from_user(&ncci, argp, sizeof(ncci)))927			return -EFAULT;928 929		mutex_lock(&cdev->lock);930		nccip = capincci_find(cdev, (u32)ncci);931		if (nccip) {932			mp = nccip->minorp;933			if (mp)934				unit = mp->minor;935		}936		mutex_unlock(&cdev->lock);937		return unit;938	}939#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */940 941	default:942		return -EINVAL;943	}944}945 946static long947capi_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)948{949	int ret;950 951	mutex_lock(&capi_mutex);952	ret = capi_ioctl(file, cmd, arg);953	mutex_unlock(&capi_mutex);954 955	return ret;956}957 958#ifdef CONFIG_COMPAT959static long960capi_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)961{962	int ret;963 964	if (cmd == CAPI_MANUFACTURER_CMD) {965		struct {966			compat_ulong_t cmd;967			compat_uptr_t data;968		} mcmd32;969 970		if (!capable(CAP_SYS_ADMIN))971			return -EPERM;972		if (copy_from_user(&mcmd32, compat_ptr(arg), sizeof(mcmd32)))973			return -EFAULT;974 975		mutex_lock(&capi_mutex);976		ret = capi20_manufacturer(mcmd32.cmd, compat_ptr(mcmd32.data));977		mutex_unlock(&capi_mutex);978 979		return ret;980	}981 982	return capi_unlocked_ioctl(file, cmd, (unsigned long)compat_ptr(arg));983}984#endif985 986static int capi_open(struct inode *inode, struct file *file)987{988	struct capidev *cdev;989 990	cdev = kzalloc(sizeof(*cdev), GFP_KERNEL);991	if (!cdev)992		return -ENOMEM;993 994	mutex_init(&cdev->lock);995	skb_queue_head_init(&cdev->recvqueue);996	init_waitqueue_head(&cdev->recvwait);997	INIT_LIST_HEAD(&cdev->nccis);998	file->private_data = cdev;999 1000	mutex_lock(&capidev_list_lock);1001	list_add_tail(&cdev->list, &capidev_list);1002	mutex_unlock(&capidev_list_lock);1003 1004	return stream_open(inode, file);1005}1006 1007static int capi_release(struct inode *inode, struct file *file)1008{1009	struct capidev *cdev = file->private_data;1010 1011	mutex_lock(&capidev_list_lock);1012	list_del(&cdev->list);1013	mutex_unlock(&capidev_list_lock);1014 1015	if (cdev->ap.applid)1016		capi20_release(&cdev->ap);1017	skb_queue_purge(&cdev->recvqueue);1018	capincci_free(cdev, 0xffffffff);1019 1020	kfree(cdev);1021	return 0;1022}1023 1024static const struct file_operations capi_fops =1025{1026	.owner		= THIS_MODULE,1027	.read		= capi_read,1028	.write		= capi_write,1029	.poll		= capi_poll,1030	.unlocked_ioctl	= capi_unlocked_ioctl,1031#ifdef CONFIG_COMPAT1032	.compat_ioctl	= capi_compat_ioctl,1033#endif1034	.open		= capi_open,1035	.release	= capi_release,1036};1037 1038#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE1039/* -------- tty_operations for capincci ----------------------------- */1040 1041static int1042capinc_tty_install(struct tty_driver *driver, struct tty_struct *tty)1043{1044	struct capiminor *mp = capiminor_get(tty->index);1045	int ret = tty_standard_install(driver, tty);1046 1047	if (ret == 0)1048		tty->driver_data = mp;1049	else1050		capiminor_put(mp);1051	return ret;1052}1053 1054static void capinc_tty_cleanup(struct tty_struct *tty)1055{1056	struct capiminor *mp = tty->driver_data;1057	tty->driver_data = NULL;1058	capiminor_put(mp);1059}1060 1061static int capinc_tty_open(struct tty_struct *tty, struct file *filp)1062{1063	struct capiminor *mp = tty->driver_data;1064	int err;1065 1066	err = tty_port_open(&mp->port, tty, filp);1067	if (err)1068		return err;1069 1070	handle_minor_recv(mp);1071	return 0;1072}1073 1074static void capinc_tty_close(struct tty_struct *tty, struct file *filp)1075{1076	struct capiminor *mp = tty->driver_data;1077 1078	tty_port_close(&mp->port, tty, filp);1079}1080 1081static ssize_t capinc_tty_write(struct tty_struct *tty, const u8 *buf,1082				size_t count)1083{1084	struct capiminor *mp = tty->driver_data;1085	struct sk_buff *skb;1086 1087	pr_debug("capinc_tty_write(count=%zu)\n", count);1088 1089	spin_lock_bh(&mp->outlock);1090	skb = mp->outskb;1091	if (skb) {1092		mp->outskb = NULL;1093		__skb_queue_tail(&mp->outqueue, skb);1094		mp->outbytes += skb->len;1095	}1096 1097	skb = alloc_skb(CAPI_DATA_B3_REQ_LEN + count, GFP_ATOMIC);1098	if (!skb) {1099		printk(KERN_ERR "capinc_tty_write: alloc_skb failed\n");1100		spin_unlock_bh(&mp->outlock);1101		return -ENOMEM;1102	}1103 1104	skb_reserve(skb, CAPI_DATA_B3_REQ_LEN);1105	skb_put_data(skb, buf, count);1106 1107	__skb_queue_tail(&mp->outqueue, skb);1108	mp->outbytes += skb->len;1109	spin_unlock_bh(&mp->outlock);1110 1111	handle_minor_send(mp);1112 1113	return count;1114}1115 1116static int capinc_tty_put_char(struct tty_struct *tty, u8 ch)1117{1118	struct capiminor *mp = tty->driver_data;1119	bool invoke_send = false;1120	struct sk_buff *skb;1121	int ret = 1;1122 1123	pr_debug("capinc_put_char(%u)\n", ch);1124 1125	spin_lock_bh(&mp->outlock);1126	skb = mp->outskb;1127	if (skb) {1128		if (skb_tailroom(skb) > 0) {1129			skb_put_u8(skb, ch);1130			goto unlock_out;1131		}1132		mp->outskb = NULL;1133		__skb_queue_tail(&mp->outqueue, skb);1134		mp->outbytes += skb->len;1135		invoke_send = true;1136	}1137 1138	skb = alloc_skb(CAPI_DATA_B3_REQ_LEN + CAPI_MAX_BLKSIZE, GFP_ATOMIC);1139	if (skb) {1140		skb_reserve(skb, CAPI_DATA_B3_REQ_LEN);1141		skb_put_u8(skb, ch);1142		mp->outskb = skb;1143	} else {1144		printk(KERN_ERR "capinc_put_char: char %u lost\n", ch);1145		ret = 0;1146	}1147 1148unlock_out:1149	spin_unlock_bh(&mp->outlock);1150 1151	if (invoke_send)1152		handle_minor_send(mp);1153 1154	return ret;1155}1156 1157static void capinc_tty_flush_chars(struct tty_struct *tty)1158{1159	struct capiminor *mp = tty->driver_data;1160	struct sk_buff *skb;1161 1162	spin_lock_bh(&mp->outlock);1163	skb = mp->outskb;1164	if (skb) {1165		mp->outskb = NULL;1166		__skb_queue_tail(&mp->outqueue, skb);1167		mp->outbytes += skb->len;1168		spin_unlock_bh(&mp->outlock);1169 1170		handle_minor_send(mp);1171	} else1172		spin_unlock_bh(&mp->outlock);1173 1174	handle_minor_recv(mp);1175}1176 1177static unsigned int capinc_tty_write_room(struct tty_struct *tty)1178{1179	struct capiminor *mp = tty->driver_data;1180	unsigned int room;1181 1182	room = CAPINC_MAX_SENDQUEUE-skb_queue_len(&mp->outqueue);1183	room *= CAPI_MAX_BLKSIZE;1184	pr_debug("capinc_tty_write_room = %u\n", room);1185	return room;1186}1187 1188static unsigned int capinc_tty_chars_in_buffer(struct tty_struct *tty)1189{1190	struct capiminor *mp = tty->driver_data;1191 1192	pr_debug("capinc_tty_chars_in_buffer = %d nack=%d sq=%d rq=%d\n",1193		 mp->outbytes, mp->nack,1194		 skb_queue_len(&mp->outqueue),1195		 skb_queue_len(&mp->inqueue));1196	return mp->outbytes;1197}1198 1199static void capinc_tty_throttle(struct tty_struct *tty)1200{1201	struct capiminor *mp = tty->driver_data;1202	mp->ttyinstop = 1;1203}1204 1205static void capinc_tty_unthrottle(struct tty_struct *tty)1206{1207	struct capiminor *mp = tty->driver_data;1208 1209	mp->ttyinstop = 0;1210	handle_minor_recv(mp);1211}1212 1213static void capinc_tty_stop(struct tty_struct *tty)1214{1215	struct capiminor *mp = tty->driver_data;1216 1217	mp->ttyoutstop = 1;1218}1219 1220static void capinc_tty_start(struct tty_struct *tty)1221{1222	struct capiminor *mp = tty->driver_data;1223 1224	mp->ttyoutstop = 0;1225	handle_minor_send(mp);1226}1227 1228static void capinc_tty_hangup(struct tty_struct *tty)1229{1230	struct capiminor *mp = tty->driver_data;1231 1232	tty_port_hangup(&mp->port);1233}1234 1235static void capinc_tty_send_xchar(struct tty_struct *tty, u8 ch)1236{1237	pr_debug("capinc_tty_send_xchar(%u)\n", ch);1238}1239 1240static const struct tty_operations capinc_ops = {1241	.open = capinc_tty_open,1242	.close = capinc_tty_close,1243	.write = capinc_tty_write,1244	.put_char = capinc_tty_put_char,1245	.flush_chars = capinc_tty_flush_chars,1246	.write_room = capinc_tty_write_room,1247	.chars_in_buffer = capinc_tty_chars_in_buffer,1248	.throttle = capinc_tty_throttle,1249	.unthrottle = capinc_tty_unthrottle,1250	.stop = capinc_tty_stop,1251	.start = capinc_tty_start,1252	.hangup = capinc_tty_hangup,1253	.send_xchar = capinc_tty_send_xchar,1254	.install = capinc_tty_install,1255	.cleanup = capinc_tty_cleanup,1256};1257 1258static int __init capinc_tty_init(void)1259{1260	struct tty_driver *drv;1261	int err;1262 1263	if (capi_ttyminors > CAPINC_MAX_PORTS)1264		capi_ttyminors = CAPINC_MAX_PORTS;1265	if (capi_ttyminors <= 0)1266		capi_ttyminors = CAPINC_NR_PORTS;1267 1268	capiminors = kcalloc(capi_ttyminors, sizeof(struct capiminor *),1269			     GFP_KERNEL);1270	if (!capiminors)1271		return -ENOMEM;1272 1273	drv = tty_alloc_driver(capi_ttyminors, TTY_DRIVER_REAL_RAW |1274			TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_DYNAMIC_DEV);1275	if (IS_ERR(drv)) {1276		kfree(capiminors);1277		return PTR_ERR(drv);1278	}1279	drv->driver_name = "capi_nc";1280	drv->name = "capi!";1281	drv->major = 0;1282	drv->minor_start = 0;1283	drv->type = TTY_DRIVER_TYPE_SERIAL;1284	drv->subtype = SERIAL_TYPE_NORMAL;1285	drv->init_termios = tty_std_termios;1286	drv->init_termios.c_iflag = ICRNL;1287	drv->init_termios.c_oflag = OPOST | ONLCR;1288	drv->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;1289	drv->init_termios.c_lflag = 0;1290	tty_set_operations(drv, &capinc_ops);1291 1292	err = tty_register_driver(drv);1293	if (err) {1294		tty_driver_kref_put(drv);1295		kfree(capiminors);1296		printk(KERN_ERR "Couldn't register capi_nc driver\n");1297		return err;1298	}1299	capinc_tty_driver = drv;1300	return 0;1301}1302 1303static void __exit capinc_tty_exit(void)1304{1305	tty_unregister_driver(capinc_tty_driver);1306	tty_driver_kref_put(capinc_tty_driver);1307	kfree(capiminors);1308}1309 1310#else /* !CONFIG_ISDN_CAPI_MIDDLEWARE */1311 1312static inline int capinc_tty_init(void)1313{1314	return 0;1315}1316 1317static inline void capinc_tty_exit(void) { }1318 1319#endif /* !CONFIG_ISDN_CAPI_MIDDLEWARE */1320 1321/* -------- /proc functions ----------------------------------------- */1322 1323/*1324 * /proc/capi/capi20:1325 *  minor applid nrecvctlpkt nrecvdatapkt nsendctlpkt nsenddatapkt1326 */1327static int __maybe_unused capi20_proc_show(struct seq_file *m, void *v)1328{1329	struct capidev *cdev;1330	struct list_head *l;1331 1332	mutex_lock(&capidev_list_lock);1333	list_for_each(l, &capidev_list) {1334		cdev = list_entry(l, struct capidev, list);1335		seq_printf(m, "0 %d %lu %lu %lu %lu\n",1336			   cdev->ap.applid,1337			   cdev->ap.nrecvctlpkt,1338			   cdev->ap.nrecvdatapkt,1339			   cdev->ap.nsentctlpkt,1340			   cdev->ap.nsentdatapkt);1341	}1342	mutex_unlock(&capidev_list_lock);1343	return 0;1344}1345 1346/*1347 * /proc/capi/capi20ncci:1348 *  applid ncci1349 */1350static int __maybe_unused capi20ncci_proc_show(struct seq_file *m, void *v)1351{1352	struct capidev *cdev;1353	struct capincci *np;1354 1355	mutex_lock(&capidev_list_lock);1356	list_for_each_entry(cdev, &capidev_list, list) {1357		mutex_lock(&cdev->lock);1358		list_for_each_entry(np, &cdev->nccis, list)1359			seq_printf(m, "%d 0x%x\n", cdev->ap.applid, np->ncci);1360		mutex_unlock(&cdev->lock);1361	}1362	mutex_unlock(&capidev_list_lock);1363	return 0;1364}1365 1366static void __init proc_init(void)1367{1368	proc_create_single("capi/capi20", 0, NULL, capi20_proc_show);1369	proc_create_single("capi/capi20ncci", 0, NULL, capi20ncci_proc_show);1370}1371 1372static void __exit proc_exit(void)1373{1374	remove_proc_entry("capi/capi20", NULL);1375	remove_proc_entry("capi/capi20ncci", NULL);1376}1377 1378/* -------- init function and module interface ---------------------- */1379 1380 1381static int __init capi_init(void)1382{1383	const char *compileinfo;1384	int major_ret;1385	int ret;1386 1387	ret = kcapi_init();1388	if (ret)1389		return ret;1390 1391	major_ret = register_chrdev(capi_major, "capi20", &capi_fops);1392	if (major_ret < 0) {1393		printk(KERN_ERR "capi20: unable to get major %d\n", capi_major);1394		kcapi_exit();1395		return major_ret;1396	}1397 1398	ret = class_register(&capi_class);1399	if (ret) {1400		unregister_chrdev(capi_major, "capi20");1401		kcapi_exit();1402		return ret;1403	}1404 1405	device_create(&capi_class, NULL, MKDEV(capi_major, 0), NULL, "capi20");1406 1407	if (capinc_tty_init() < 0) {1408		device_destroy(&capi_class, MKDEV(capi_major, 0));1409		class_unregister(&capi_class);1410		unregister_chrdev(capi_major, "capi20");1411		kcapi_exit();1412		return -ENOMEM;1413	}1414 1415	proc_init();1416 1417#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE1418	compileinfo = " (middleware)";1419#else1420	compileinfo = " (no middleware)";1421#endif1422	printk(KERN_NOTICE "CAPI 2.0 started up with major %d%s\n",1423	       capi_major, compileinfo);1424 1425	return 0;1426}1427 1428static void __exit capi_exit(void)1429{1430	proc_exit();1431 1432	device_destroy(&capi_class, MKDEV(capi_major, 0));1433	class_unregister(&capi_class);1434	unregister_chrdev(capi_major, "capi20");1435 1436	capinc_tty_exit();1437 1438	kcapi_exit();1439}1440 1441module_init(capi_init);1442module_exit(capi_exit);1443