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

📄 af_irda.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		       ias_value->t.string, ias_value->len);		/* NULL terminate the string (avoid troubles) */		ias_opt->attribute.irda_attrib_string.string[ias_value->len] = '\0';		break;	case IAS_MISSING:	default :		return -EINVAL;	}		/* Copy type over */	ias_opt->irda_attrib_type = ias_value->type;		return 0;}/* * Function irda_getsockopt (sock, level, optname, optval, optlen) * *     * */static int irda_getsockopt(struct socket *sock, int level, int optname, 			   char *optval, int *optlen){	struct sock *sk = sock->sk;	struct irda_sock *self;	struct irda_device_list list;	struct irda_device_info *discoveries;	struct irda_ias_set	ias_opt;	/* IAS get/query params */	struct ias_object *	ias_obj;	/* Object in IAS */	struct ias_attrib *	ias_attr;	/* Attribute in IAS object */	int daddr = DEV_ADDR_ANY;	/* Dest address for IAS queries */	int val = 0;	int len = 0;	int err;	int offset, total;	self = sk->protinfo.irda;	if (level != SOL_IRLMP)		return -ENOPROTOOPT;	if (get_user(len, optlen))		return -EFAULT;	switch (optname) {	case IRLMP_ENUMDEVICES:		/* Ask lmp for the current discovery log */		discoveries = irlmp_get_discoveries(&list.len, self->mask);		/* Check if the we got some results */		if (discoveries == NULL)			return -EAGAIN;		/* Didn't find any devices */		err = 0;		/* Write total list length back to client */		if (copy_to_user(optval, &list, 				 sizeof(struct irda_device_list) -				 sizeof(struct irda_device_info)))			err = -EFAULT;		/* Offset to first device entry */		offset = sizeof(struct irda_device_list) - 			sizeof(struct irda_device_info);		/* Copy the list itself */		total = offset + (list.len * sizeof(struct irda_device_info));		if (total > len)			total = len;		if (copy_to_user(optval+offset, discoveries, total - offset))			err = -EFAULT;		/* Write total number of bytes used back to client */		if (put_user(total, optlen))			err = -EFAULT;		/* Free up our buffer */		kfree(discoveries);		if (err)			return err;		break;	case IRLMP_MAX_SDU_SIZE:		val = self->max_data_size;		len = sizeof(int);		if (put_user(len, optlen))			return -EFAULT;				if (copy_to_user(optval, &val, len))			return -EFAULT;		break;	case IRLMP_IAS_GET:		/* The user want an object from our local IAS database.		 * We just need to query the IAS and return the value		 * that we found */		/* Check that the user has allocated the right space for us */		if (len != sizeof(ias_opt))			return -EINVAL;		/* Copy query to the driver. */		if (copy_from_user((char *) &ias_opt, (char *)optval, len))		  	return -EFAULT;		/* Find the object we target */		ias_obj = irias_find_object(ias_opt.irda_class_name);		if(ias_obj == (struct ias_object *) NULL)			return -EINVAL;		/* Find the attribute (in the object) we target */		ias_attr = irias_find_attrib(ias_obj,					     ias_opt.irda_attrib_name); 		if(ias_attr == (struct ias_attrib *) NULL)			return -EINVAL;		/* Translate from internal to user structure */		err = irda_extract_ias_value(&ias_opt, ias_attr->value);		if(err)			return err;		/* Copy reply to the user */		if (copy_to_user((char *)optval, (char *) &ias_opt,				 sizeof(ias_opt)))		  	return -EFAULT;		/* Note : don't need to put optlen, we checked it */		break;	case IRLMP_IAS_QUERY:		/* The user want an object from a remote IAS database.		 * We need to use IAP to query the remote database and		 * then wait for the answer to come back. */		/* Check that the user has allocated the right space for us */		if (len != sizeof(ias_opt))			return -EINVAL;		/* Copy query to the driver. */		if (copy_from_user((char *) &ias_opt, (char *)optval, len))		  	return -EFAULT;		/* At this point, there are two cases...		 * 1) the socket is connected - that's the easy case, we		 *	just query the device we are connected to...		 * 2) the socket is not connected - the user doesn't want		 *	to connect and/or may not have a valid service name		 *	(so can't create a fake connection). In this case,		 *	we assume that the user pass us a valid destination		 *	address in the requesting structure...		 */		if(self->daddr != DEV_ADDR_ANY) {			/* We are connected - reuse known daddr */			daddr = self->daddr;		} else {			/* We are not connected, we must specify a valid			 * destination address */			daddr = ias_opt.daddr;			if((!daddr) || (daddr == DEV_ADDR_ANY))				return -EINVAL;		}		/* Check that we can proceed with IAP */		if (self->iriap) {			WARNING(__FUNCTION__				"(), busy with a previous query\n");			return -EBUSY;		}		self->iriap = iriap_open(LSAP_ANY, IAS_CLIENT, self,					 irda_getvalue_confirm);		/* Treat unexpected signals as disconnect */		self->errno = -EHOSTUNREACH;		/* Query remote LM-IAS */		iriap_getvaluebyclass_request(self->iriap,					      self->saddr, daddr,					      ias_opt.irda_class_name,					      ias_opt.irda_attrib_name);		/* Wait for answer (if not already failed) */		if(self->iriap != NULL)			interruptible_sleep_on(&self->query_wait);		/* Check what happened */		if (self->errno)		{			/* Requested object/attribute doesn't exist */			if((self->errno == IAS_CLASS_UNKNOWN) ||			   (self->errno == IAS_ATTRIB_UNKNOWN))				return (-EADDRNOTAVAIL);			else				return (-EHOSTUNREACH);		}		/* Translate from internal to user structure */		err = irda_extract_ias_value(&ias_opt, self->ias_result);		if (self->ias_result)			irias_delete_value(self->ias_result);		if (err)			return err;		/* Copy reply to the user */		if (copy_to_user((char *)optval, (char *) &ias_opt,				 sizeof(ias_opt)))		  	return -EFAULT;		/* Note : don't need to put optlen, we checked it */		break;	case IRLMP_WAITDEVICE:		/* This function is just another way of seeing life ;-)		 * IRLMP_ENUMDEVICES assumes that you have a static network,		 * and that you just want to pick one of the devices present.		 * On the other hand, in here we assume that no device is		 * present and that at some point in the future a device will		 * come into range. When this device arrive, we just wake		 * up the caller, so that he has time to connect to it before		 * the device goes away...		 * Note : once the node has been discovered for more than a		 * few second, it won't trigger this function, unless it		 * goes away and come back changes its hint bits (so we		 * might call it IRLMP_WAITNEWDEVICE).		 */		/* Check that the user is passing us an int */		if (len != sizeof(int))			return -EINVAL;		/* Get timeout in ms (max time we block the caller) */		if (get_user(val, (int *)optval))			return -EFAULT;		/* Tell IrLMP we want to be notified */		irlmp_update_client(self->ckey, self->mask,				    irda_selective_discovery_indication,				    NULL, (void *) self);				/* Do some discovery (and also return cached results) */		irlmp_discovery_request(self->nslots);				/* Wait until a node is discovered */		if (!self->cachediscovery) {			IRDA_DEBUG(1, __FUNCTION__ 				   "(), nothing discovered yet, going to sleep...\n");			/* Set watchdog timer to expire in <val> ms. */			self->watchdog.function = irda_discovery_timeout;			self->watchdog.data = (unsigned long) self;			self->watchdog.expires = jiffies + (val * HZ/1000);			add_timer(&(self->watchdog));			/* Wait for IR-LMP to call us back */			interruptible_sleep_on(&self->query_wait);			/* If watchdog is still activated, kill it! */			if(timer_pending(&(self->watchdog)))				del_timer(&(self->watchdog));			IRDA_DEBUG(1, __FUNCTION__ 				   "(), ...waking up !\n");		}		else			IRDA_DEBUG(1, __FUNCTION__ 				   "(), found immediately !\n");		/* Tell IrLMP that we have been notified */		irlmp_update_client(self->ckey, self->mask, NULL, NULL, NULL);		/* Check if the we got some results */		if (!self->cachediscovery)			return -EAGAIN;		/* Didn't find any devices */		/* Cleanup */		self->cachediscovery = NULL;		/* Note : We don't return anything to the user.		 * We could return the device that triggered the wake up,		 * but it's probably better to force the user to query		 * the whole discovery log and let him pick one device...		 */		break;	default:		return -ENOPROTOOPT;	}		return 0;}static struct net_proto_family irda_family_ops ={	PF_IRDA,	irda_create};static struct proto_ops SOCKOPS_WRAPPED(irda_stream_ops) = {	family:		PF_IRDA,		release:	irda_release,	bind:		irda_bind,	connect:	irda_connect,	socketpair:	sock_no_socketpair,	accept:		irda_accept,	getname:	irda_getname,	poll:		irda_poll,	ioctl:		irda_ioctl,	listen:		irda_listen,	shutdown:	irda_shutdown,	setsockopt:	irda_setsockopt,	getsockopt:	irda_getsockopt,	sendmsg:	irda_sendmsg,	recvmsg:	irda_recvmsg_stream,	mmap:		sock_no_mmap,};static struct proto_ops SOCKOPS_WRAPPED(irda_seqpacket_ops) = {	family:		PF_IRDA,		release:	irda_release,	bind:		irda_bind,	connect:	irda_connect,	socketpair:	sock_no_socketpair,	accept:		irda_accept,	getname:	irda_getname,	poll:		datagram_poll,	ioctl:		irda_ioctl,	listen:		irda_listen,	shutdown:	irda_shutdown,	setsockopt:	irda_setsockopt,	getsockopt:	irda_getsockopt,	sendmsg:	irda_sendmsg,	recvmsg:	irda_recvmsg_dgram,	mmap:		sock_no_mmap,};static struct proto_ops SOCKOPS_WRAPPED(irda_dgram_ops) = {	family:		PF_IRDA,       	release:	irda_release,	bind:		irda_bind,	connect:	irda_connect,	socketpair:	sock_no_socketpair,	accept:		irda_accept,	getname:	irda_getname,	poll:		datagram_poll,	ioctl:		irda_ioctl,	listen:		irda_listen,	shutdown:	irda_shutdown,	setsockopt:	irda_setsockopt,	getsockopt:	irda_getsockopt,	sendmsg:	irda_sendmsg_dgram,	recvmsg:	irda_recvmsg_dgram,	mmap:		sock_no_mmap,};#ifdef CONFIG_IRDA_ULTRAstatic struct proto_ops SOCKOPS_WRAPPED(irda_ultra_ops) = {	family:		PF_IRDA,       	release:	irda_release,	bind:		irda_bind,	connect:	sock_no_connect,	socketpair:	sock_no_socketpair,	accept:		sock_no_accept,	getname:	irda_getname,	poll:		datagram_poll,	ioctl:		irda_ioctl,	listen:		sock_no_listen,	shutdown:	irda_shutdown,	setsockopt:	irda_setsockopt,	getsockopt:	irda_getsockopt,	sendmsg:	irda_sendmsg_ultra,	recvmsg:	irda_recvmsg_dgram,	mmap:		sock_no_mmap,};#endif /* CONFIG_IRDA_ULTRA */#include <linux/smp_lock.h>SOCKOPS_WRAP(irda_stream, PF_IRDA);SOCKOPS_WRAP(irda_seqpacket, PF_IRDA);SOCKOPS_WRAP(irda_dgram, PF_IRDA);/* * Function irda_device_event (this, event, ptr) * *    Called when a device is taken up or down * */static int irda_device_event(struct notifier_block *this, unsigned long event,			     void *ptr){	struct net_device *dev = (struct net_device *) ptr;	        /* Reject non IrDA devices */	if (dev->type != ARPHRD_IRDA) 		return NOTIFY_DONE;	        switch (event) {	case NETDEV_UP:		IRDA_DEBUG(3, __FUNCTION__ "(), NETDEV_UP\n");		/* irda_dev_device_up(dev); */		break;	case NETDEV_DOWN:		IRDA_DEBUG(3, __FUNCTION__ "(), NETDEV_DOWN\n");		/* irda_kill_by_device(dev); */		/* irda_rt_device_down(dev); */		/* irda_dev_device_down(dev); */		break;	default:		break;        }        return NOTIFY_DONE;}static struct packet_type irda_packet_type = {	0,	/* MUTTER ntohs(ETH_P_IRDA),*/	NULL,	irlap_driver_rcv,	NULL,	NULL,};static struct notifier_block irda_dev_notifier = {	irda_device_event,	NULL,	0};/* * Function irda_proc_modcount (inode, fill) * *    Use by the proc file system functions to prevent the irda module *    being removed while the use is standing in the net/irda directory */void irda_proc_modcount(struct inode *inode, int fill){#ifdef MODULE#ifdef CONFIG_PROC_FS	if (fill)		MOD_INC_USE_COUNT;	else		MOD_DEC_USE_COUNT;#endif /* CONFIG_PROC_FS */#endif /* MODULE */}/* * Function irda_proto_init (pro) * *    Initialize IrDA protocol layer * */int __init irda_proto_init(void){	sock_register(&irda_family_ops);	irda_packet_type.type = htons(ETH_P_IRDA);        dev_add_pack(&irda_packet_type);	register_netdevice_notifier(&irda_dev_notifier);	irda_init();#ifdef MODULE 	irda_device_init();  /* Called by init/main.c when non-modular */#endif	return 0;}/* * Function irda_proto_cleanup (void) * *    Remove IrDA protocol layer * */#ifdef MODULEvoid irda_proto_cleanup(void){	irda_packet_type.type = htons(ETH_P_IRDA);        dev_remove_pack(&irda_packet_type);        unregister_netdevice_notifier(&irda_dev_notifier);		sock_unregister(PF_IRDA);	irda_cleanup();	        return;}module_init(irda_proto_init);module_exit(irda_proto_cleanup); MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");MODULE_DESCRIPTION("The Linux IrDA Protocol Subsystem"); MODULE_PARM(irda_debug, "1l");#endif /* MODULE */

⌨️ 快捷键说明

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