⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 capi.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
				retval = copy_to_user((void *) arg,				      (void *) &data.profile.ncontroller,				       sizeof(data.profile.ncontroller));			} else {				cdev->errcode = (*capifuncs->capi_get_profile) (data.contr, &data.profile);				if (cdev->errcode)					return -EIO;				retval = copy_to_user((void *) arg,						  (void *) &data.profile,						   sizeof(data.profile));			}			if (retval)				return -EFAULT;		}		return 0;	case CAPI_GET_MANUFACTURER:		{			retval = copy_from_user((void *) &data.contr,						(void *) arg,						sizeof(data.contr));			if (retval)				return -EFAULT;			cdev->errcode = (*capifuncs->capi_get_manufacturer) (data.contr, data.manufacturer);			if (cdev->errcode)				return -EIO;			retval = copy_to_user((void *) arg, (void *) data.manufacturer,					      sizeof(data.manufacturer));			if (retval)				return -EFAULT;		}		return 0;	case CAPI_GET_ERRCODE:		data.errcode = cdev->errcode;		cdev->errcode = CAPI_NOERROR;		if (arg) {			retval = copy_to_user((void *) arg,					      (void *) &data.errcode,					      sizeof(data.errcode));			if (retval)				return -EFAULT;		}		return data.errcode;	case CAPI_INSTALLED:		if ((*capifuncs->capi_isinstalled)() == CAPI_NOERROR)			return 0;		return -ENXIO;	case CAPI_MANUFACTURER_CMD:		{			struct capi_manufacturer_cmd mcmd;			if (!capable(CAP_SYS_ADMIN))				return -EPERM;			retval = copy_from_user((void *) &mcmd, (void *) arg,						sizeof(mcmd));			if (retval)				return -EFAULT;			return (*capifuncs->capi_manufacturer) (mcmd.cmd, mcmd.data);		}		return 0;	case CAPI_SET_FLAGS:	case CAPI_CLR_FLAGS:		{			unsigned userflags;			retval = copy_from_user((void *) &userflags,						(void *) arg,						sizeof(userflags));			if (retval)				return -EFAULT;			if (cmd == CAPI_SET_FLAGS)				cdev->userflags |= userflags;			else				cdev->userflags &= ~userflags;		}		return 0;	case CAPI_GET_FLAGS:		{			retval = copy_to_user((void *) arg,					      (void *) &cdev->userflags,					      sizeof(cdev->userflags));			if (retval)				return -EFAULT;		}		return 0;	case CAPI_NCCI_OPENCOUNT:		{			struct capincci *nccip;#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE			struct capiminor *mp;#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */			unsigned ncci;			int count = 0;			retval = copy_from_user((void *) &ncci,						(void *) arg,						sizeof(ncci));			if (retval)				return -EFAULT;			nccip = capincci_find(cdev, (__u32) ncci);			if (!nccip)				return 0;#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE			if ((mp = nccip->minorp) != 0) {				count += atomic_read(&mp->ttyopencount);				if (mp->file)					count++;			}#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */			return count;		}		return 0;#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE	case CAPI_NCCI_GETUNIT:		{			struct capincci *nccip;			struct capiminor *mp;			unsigned ncci;			retval = copy_from_user((void *) &ncci,						(void *) arg,						sizeof(ncci));			if (retval)				return -EFAULT;			nccip = capincci_find(cdev, (__u32) ncci);			if (!nccip || (mp = nccip->minorp) == 0)				return -ESRCH;			return mp->minor;		}		return 0;#endif /* CONFIG_ISDN_CAPI_MIDDLEWARE */	}	return -EINVAL;}static intcapi_open(struct inode *inode, struct file *file){	if (file->private_data)		return -EEXIST;	if ((file->private_data = capidev_alloc(file)) == 0)		return -ENOMEM;	MOD_INC_USE_COUNT;#ifdef _DEBUG_REFCOUNT	printk(KERN_DEBUG "capi_open %d\n", GET_USE_COUNT(THIS_MODULE));#endif	return 0;}static intcapi_release(struct inode *inode, struct file *file){	struct capidev *cdev = (struct capidev *)file->private_data;	lock_kernel();	capincci_free(cdev, 0xffffffff);	capidev_free(cdev);	file->private_data = NULL;		MOD_DEC_USE_COUNT;#ifdef _DEBUG_REFCOUNT	printk(KERN_DEBUG "capi_release %d\n", GET_USE_COUNT(THIS_MODULE));#endif	unlock_kernel();	return 0;}static struct file_operations capi_fops ={	owner:		THIS_MODULE,	llseek:		capi_llseek,	read:		capi_read,	write:		capi_write,	poll:		capi_poll,	ioctl:		capi_ioctl,	open:		capi_open,	release:	capi_release,};#ifdef CONFIG_ISDN_CAPI_MIDDLEWARE/* -------- file_operations for capincci ---------------------------- */static intcapinc_raw_open(struct inode *inode, struct file *file){	struct capiminor *mp;	if (file->private_data)		return -EEXIST;	if ((mp = capiminor_find(MINOR(file->f_dentry->d_inode->i_rdev))) == 0)		return -ENXIO;	if (mp->nccip == 0)		return -ENXIO;	if (mp->file)		return -EBUSY;#ifdef _DEBUG_REFCOUNT	printk(KERN_DEBUG "capi_raw_open %d\n", GET_USE_COUNT(THIS_MODULE));#endif	mp->datahandle = 0;	mp->file = file;	file->private_data = (void *)mp;	handle_minor_recv(mp);	return 0;}static loff_tcapinc_raw_llseek(struct file *file, loff_t offset, int origin){	return -ESPIPE;}static ssize_tcapinc_raw_read(struct file *file, char *buf, size_t count, loff_t *ppos){	struct capiminor *mp = (struct capiminor *)file->private_data;	struct sk_buff *skb;	int retval;	size_t copied = 0;        if (ppos != &file->f_pos)		return -ESPIPE;	if (!mp || !mp->nccip)		return -EINVAL;	if ((skb = skb_dequeue(&mp->recvqueue)) == 0) {		if (file->f_flags & O_NONBLOCK)			return -EAGAIN;		for (;;) {			interruptible_sleep_on(&mp->recvwait);			if (mp->nccip == 0)				return 0;			if ((skb = skb_dequeue(&mp->recvqueue)) != 0)				break;			if (signal_pending(current))				break;		}		if (skb == 0)			return -ERESTARTNOHAND;	}	do {		if (count < skb->len) {			retval = copy_to_user(buf, skb->data, count);			if (retval) {				skb_queue_head(&mp->recvqueue, skb);				return retval;			}			skb_pull(skb, count);			skb_queue_head(&mp->recvqueue, skb);			copied += count;			return copied;		} else {			retval = copy_to_user(buf, skb->data, skb->len);			if (retval) {				skb_queue_head(&mp->recvqueue, skb);				return copied;			}			copied += skb->len;			count -= skb->len;			buf += skb->len;			kfree_skb(skb);		}	} while ((skb = skb_dequeue(&mp->recvqueue)) != 0);	return copied;}static ssize_tcapinc_raw_write(struct file *file, const char *buf, size_t count, loff_t *ppos){	struct capiminor *mp = (struct capiminor *)file->private_data;	struct sk_buff *skb;	int retval;        if (ppos != &file->f_pos)		return -ESPIPE;	if (!mp || !mp->nccip)		return -EINVAL;	skb = alloc_skb(CAPI_DATA_B3_REQ_LEN+count, GFP_USER);	skb_reserve(skb, CAPI_DATA_B3_REQ_LEN);	if ((retval = copy_from_user(skb_put(skb, count), buf, count))) {		kfree_skb(skb);		return retval;	}	while (skb_queue_len(&mp->outqueue) > CAPINC_MAX_SENDQUEUE) {		if (file->f_flags & O_NONBLOCK)			return -EAGAIN;		interruptible_sleep_on(&mp->sendwait);		if (mp->nccip == 0) {			kfree_skb(skb);			return -EIO;		}		if (signal_pending(current))			return -ERESTARTNOHAND;	}	skb_queue_tail(&mp->outqueue, skb);	mp->outbytes += skb->len;	(void)handle_minor_send(mp);	return count;}static unsigned intcapinc_raw_poll(struct file *file, poll_table * wait){	struct capiminor *mp = (struct capiminor *)file->private_data;	unsigned int mask = 0;	if (!mp || !mp->nccip)		return POLLERR|POLLHUP;	poll_wait(file, &(mp->recvwait), wait);	if (!skb_queue_empty(&mp->recvqueue))		mask |= POLLIN | POLLRDNORM;	poll_wait(file, &(mp->sendwait), wait);	if (skb_queue_len(&mp->outqueue) > CAPINC_MAX_SENDQUEUE)		mask = POLLOUT | POLLWRNORM;	return mask;}static intcapinc_raw_ioctl(struct inode *inode, struct file *file,		      unsigned int cmd, unsigned long arg){	struct capiminor *mp = (struct capiminor *)file->private_data;	if (!mp || !mp->nccip)		return -EINVAL;	switch (cmd) {	}	return -EINVAL;}static intcapinc_raw_release(struct inode *inode, struct file *file){	struct capiminor *mp = (struct capiminor *)file->private_data;	if (mp) {		lock_kernel();		mp->file = 0;		if (mp->nccip == 0) {			capiminor_free(mp);			file->private_data = NULL;		}		unlock_kernel();	}#ifdef _DEBUG_REFCOUNT	printk(KERN_DEBUG "capinc_raw_release %d\n", GET_USE_COUNT(THIS_MODULE));#endif	return 0;}static struct file_operations capinc_raw_fops ={	owner:		THIS_MODULE,	llseek:		capinc_raw_llseek,	read:		capinc_raw_read,	write:		capinc_raw_write,	poll:		capinc_raw_poll,	ioctl:		capinc_raw_ioctl,	open:		capinc_raw_open,	release:	capinc_raw_release,};/* -------- tty_operations for capincci ----------------------------- */int capinc_tty_open(struct tty_struct * tty, struct file * file){	struct capiminor *mp;	if ((mp = capiminor_find(MINOR(file->f_dentry->d_inode->i_rdev))) == 0)		return -ENXIO;	if (mp->nccip == 0)		return -ENXIO;	if (mp->file)		return -EBUSY;	skb_queue_head_init(&mp->recvqueue);	init_waitqueue_head(&mp->recvwait);	init_waitqueue_head(&mp->sendwait);	tty->driver_data = (void *)mp;#ifdef _DEBUG_REFCOUNT	printk(KERN_DEBUG "capi_tty_open %d\n", GET_USE_COUNT(THIS_MODULE));#endif	if (atomic_read(&mp->ttyopencount) == 0)		mp->tty = tty;	atomic_inc(&mp->ttyopencount);#ifdef _DEBUG_REFCOUNT	printk(KERN_DEBUG "capinc_tty_open ocount=%d\n", atomic_read(&mp->ttyopencount));#endif	handle_minor_recv(mp);	return 0;}void capinc_tty_close(struct tty_struct * tty, struct file * file){	struct capiminor *mp;	mp = (struct capiminor *)tty->driver_data;	if (mp)	{		if (atomic_dec_and_test(&mp->ttyopencount)) {#ifdef _DEBUG_REFCOUNT			printk(KERN_DEBUG "capinc_tty_close lastclose\n");#endif			tty->driver_data = (void *)0;			mp->tty = 0;		}#ifdef _DEBUG_REFCOUNT		printk(KERN_DEBUG "capinc_tty_close ocount=%d\n", atomic_read(&mp->ttyopencount));#endif		if (mp->nccip == 0)			capiminor_free(mp);	}#ifdef _DEBUG_REFCOUNT	printk(KERN_DEBUG "capinc_tty_close\n");#endif}int capinc_tty_write(struct tty_struct * tty, int from_user,		      const unsigned char *buf, int count){	struct capiminor *mp = (struct capiminor *)tty->driver_data;	struct sk_buff *skb;	int retval;#ifdef _DEBUG_TTYFUNCS	printk(KERN_DEBUG "capinc_tty_write(from_user=%d,count=%d)\n",				from_user, count);#endif	if (!mp || !mp->nccip) {#ifdef _DEBUG_TTYFUNCS		printk(KERN_DEBUG "capinc_tty_write: mp or mp->ncci NULL\n");#endif		return 0;	}	skb = mp->ttyskb;	if (skb) {		mp->ttyskb = 0;		skb_queue_tail(&mp->outqueue, skb);		mp->outbytes += skb->len;	}	skb = alloc_skb(CAPI_DATA_B3_REQ_LEN+count, GFP_ATOMIC);	if (!skb) {		printk(KERN_ERR "capinc_tty_write: alloc_skb failed\n");		return -ENOMEM;	}	skb_reserve(skb, CAPI_DATA_B3_REQ_LEN);	if (from_user) {		if ((retval = copy_from_user(skb_put(skb, count), buf, count))) {			kfree_skb(skb);#ifdef _DEBUG_TTYFUNCS			printk(KERN_DEBUG "capinc_tty_write: copy_from_user=%d\n", retval);#endif			return retval;		}	} else {		memcpy(skb_put(skb, count), buf, count);	}	skb_queue_tail(&mp->outqueue, skb);	mp->outbytes += skb->len;	(void)handle_minor_send(mp);	(void)handle_minor_recv(mp);	return count;}void capinc_tty_put_char(struct tty_struct *tty, unsigned char ch){	struct capiminor *mp = (struct capiminor *)tty->driver_data;	struct sk_buff *skb;#ifdef _DEBUG_TTYFUNCS	printk(KERN_DEBUG "capinc_put_char(%u)\n", ch);#endif	if (!mp || !mp->nccip) {#ifdef _DEBUG_TTYFUNCS		printk(KERN_DEBUG "capinc_tty_put_char: mp or mp->ncci NULL\n");#endif		return;	}	skb = mp->ttyskb;	if (skb) {		if (skb_tailroom(skb) > 0) {			*(skb_put(skb, 1)) = ch;			return;		}		mp->ttyskb = 0;		skb_queue_tail(&mp->outqueue, skb);		mp->outbytes += skb->len;		(void)handle_minor_send(mp);	}	skb = alloc_skb(CAPI_DATA_B3_REQ_LEN+CAPI_MAX_BLKSIZE, GFP_ATOMIC);	if (skb) {		skb_reserve(skb, CAPI_DATA_B3_REQ_LEN);		*(skb_put(skb, 1)) = ch;		mp->ttyskb = skb;	} else {		printk(KERN_ERR "capinc_put_char: char %u lost\n", ch);	}}void capinc_tty_flush_chars(struct tty_struct *tty){	struct capiminor *mp = (struct capiminor *)tty->driver_data;	struct sk_buff *skb;#ifdef _DEBUG_TTYFUNCS	printk(KERN_DEBUG "capinc_tty_flush_chars\n");#endif	if (!mp || !mp->nccip) {#ifdef _DEBUG_TTYFUNCS		printk(KERN_DEBUG "capinc_tty_flush_chars: mp or mp->ncci NULL\n");#endif		return;	}	skb = mp->ttyskb;	if (skb) {		mp->ttyskb = 0;		skb_queue_tail(&mp->outqueue, skb);		mp->outbytes += skb->len;		(void)handle_minor_send(mp);	}	(void)handle_minor_recv(mp);}int capinc_tty_write_room(struct tty_struct *tty){

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -