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

📄 wireless.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 3 页
字号:
{	if (v == SEQ_START_TOKEN)		seq_printf(seq, "Inter-| sta-|   Quality        |   Discarded "				"packets               | Missed | WE\n"				" face | tus | link level noise |  nwid  "				"crypt   frag  retry   misc | beacon | %d\n",			   WIRELESS_EXT);	else		wireless_seq_printf_stats(seq, v);	return 0;}extern void *dev_seq_start(struct seq_file *seq, loff_t *pos);extern void *dev_seq_next(struct seq_file *seq, void *v, loff_t *pos);extern void dev_seq_stop(struct seq_file *seq, void *v);static struct seq_operations wireless_seq_ops = {	.start = dev_seq_start,	.next  = dev_seq_next,	.stop  = dev_seq_stop,	.show  = wireless_seq_show,};static int wireless_seq_open(struct inode *inode, struct file *file){	return seq_open(file, &wireless_seq_ops);}static struct file_operations wireless_seq_fops = {	.owner	 = THIS_MODULE,	.open    = wireless_seq_open,	.read    = seq_read,	.llseek  = seq_lseek,	.release = seq_release,};int __init wireless_proc_init(void){	if (!proc_net_fops_create("wireless", S_IRUGO, &wireless_seq_fops))		return -ENOMEM;	return 0;}#endif	/* CONFIG_PROC_FS *//************************** IOCTL SUPPORT **************************//* * The original user space API to configure all those Wireless Extensions * is through IOCTLs. * In there, we check if we need to call the new driver API (iw_handler) * or just call the driver ioctl handler. *//* ---------------------------------------------------------------- *//* *	Allow programatic access to /proc/net/wireless even if /proc *	doesn't exist... Also more efficient... */static inline int dev_iwstats(struct net_device *dev, struct ifreq *ifr){	/* Get stats from the driver */	struct iw_statistics *stats;	stats = get_wireless_stats(dev);	if (stats != (struct iw_statistics *) NULL) {		struct iwreq *	wrq = (struct iwreq *)ifr;		/* Copy statistics to the user buffer */		if(copy_to_user(wrq->u.data.pointer, stats,				sizeof(struct iw_statistics)))			return -EFAULT;		/* Check if we need to clear the update flag */		if(wrq->u.data.flags != 0)			stats->qual.updated = 0;		return 0;	} else		return -EOPNOTSUPP;}/* ---------------------------------------------------------------- *//* * Export the driver private handler definition * They will be picked up by tools like iwpriv... */static inline int ioctl_export_private(struct net_device *	dev,				       struct ifreq *		ifr){	struct iwreq *				iwr = (struct iwreq *) ifr;	/* Check if the driver has something to export */	if((dev->wireless_handlers->num_private_args == 0) ||	   (dev->wireless_handlers->private_args == NULL))		return -EOPNOTSUPP;	/* Check NULL pointer */	if(iwr->u.data.pointer == NULL)		return -EFAULT;#ifdef WE_STRICT_WRITE	/* Check if there is enough buffer up there */	if(iwr->u.data.length < dev->wireless_handlers->num_private_args) {		printk(KERN_ERR "%s (WE) : Buffer for request SIOCGIWPRIV too small (%d<%d)\n", dev->name, iwr->u.data.length, dev->wireless_handlers->num_private_args);		return -E2BIG;	}#endif	/* WE_STRICT_WRITE */	/* Set the number of available ioctls. */	iwr->u.data.length = dev->wireless_handlers->num_private_args;	/* Copy structure to the user buffer. */	if (copy_to_user(iwr->u.data.pointer,			 dev->wireless_handlers->private_args,			 sizeof(struct iw_priv_args) * iwr->u.data.length))		return -EFAULT;	return 0;}/* ---------------------------------------------------------------- *//* * Wrapper to call a standard Wireless Extension handler. * We do various checks and also take care of moving data between * user space and kernel space. */static inline int ioctl_standard_call(struct net_device *	dev,				      struct ifreq *		ifr,				      unsigned int		cmd,				      iw_handler		handler){	struct iwreq *				iwr = (struct iwreq *) ifr;	const struct iw_ioctl_description *	descr;	struct iw_request_info			info;	int					ret = -EINVAL;	int					user_size = 0;	/* Get the description of the IOCTL */	if((cmd - SIOCIWFIRST) >= standard_ioctl_num)		return -EOPNOTSUPP;	descr = &(standard_ioctl[cmd - SIOCIWFIRST]);#ifdef WE_IOCTL_DEBUG	printk(KERN_DEBUG "%s (WE) : Found standard handler for 0x%04X\n",	       ifr->ifr_name, cmd);	printk(KERN_DEBUG "%s (WE) : Header type : %d, Token type : %d, size : %d, token : %d\n", dev->name, descr->header_type, descr->token_type, descr->token_size, descr->max_tokens);#endif	/* WE_IOCTL_DEBUG */	/* Prepare the call */	info.cmd = cmd;	info.flags = 0;	/* Check if we have a pointer to user space data or not */	if(descr->header_type != IW_HEADER_TYPE_POINT) {		/* No extra arguments. Trivial to handle */		ret = handler(dev, &info, &(iwr->u), NULL);#ifdef WE_SET_EVENT		/* Generate an event to notify listeners of the change */		if((descr->flags & IW_DESCR_FLAG_EVENT) &&		   ((ret == 0) || (ret == -EIWCOMMIT)))			wireless_send_event(dev, cmd, &(iwr->u), NULL);#endif	/* WE_SET_EVENT */	} else {		char *	extra;		int	err;		/* Check what user space is giving us */		if(IW_IS_SET(cmd)) {			/* Check NULL pointer */			if((iwr->u.data.pointer == NULL) &&			   (iwr->u.data.length != 0))				return -EFAULT;			/* Check if number of token fits within bounds */			if(iwr->u.data.length > descr->max_tokens)				return -E2BIG;			if(iwr->u.data.length < descr->min_tokens)				return -EINVAL;		} else {			/* Check NULL pointer */			if(iwr->u.data.pointer == NULL)				return -EFAULT;			/* Save user space buffer size for checking */			user_size = iwr->u.data.length;		}#ifdef WE_IOCTL_DEBUG		printk(KERN_DEBUG "%s (WE) : Malloc %d bytes\n",		       dev->name, descr->max_tokens * descr->token_size);#endif	/* WE_IOCTL_DEBUG */		/* Always allocate for max space. Easier, and won't last		 * long... */		extra = kmalloc(descr->max_tokens * descr->token_size,				GFP_KERNEL);		if (extra == NULL) {			return -ENOMEM;		}		/* If it is a SET, get all the extra data in here */		if(IW_IS_SET(cmd) && (iwr->u.data.length != 0)) {			err = copy_from_user(extra, iwr->u.data.pointer,					     iwr->u.data.length *					     descr->token_size);			if (err) {				kfree(extra);				return -EFAULT;			}#ifdef WE_IOCTL_DEBUG			printk(KERN_DEBUG "%s (WE) : Got %d bytes\n",			       dev->name,			       iwr->u.data.length * descr->token_size);#endif	/* WE_IOCTL_DEBUG */		}		/* Call the handler */		ret = handler(dev, &info, &(iwr->u), extra);		/* If we have something to return to the user */		if (!ret && IW_IS_GET(cmd)) {#ifdef WE_STRICT_WRITE			/* Check if there is enough buffer up there */			if(user_size < iwr->u.data.length) {				printk(KERN_ERR "%s (WE) : Buffer for request %04X too small (%d<%d)\n", dev->name, cmd, user_size, iwr->u.data.length);				kfree(extra);				return -E2BIG;			}#endif	/* WE_STRICT_WRITE */			err = copy_to_user(iwr->u.data.pointer, extra,					   iwr->u.data.length *					   descr->token_size);			if (err)				ret =  -EFAULT;				   #ifdef WE_IOCTL_DEBUG			printk(KERN_DEBUG "%s (WE) : Wrote %d bytes\n",			       dev->name,			       iwr->u.data.length * descr->token_size);#endif	/* WE_IOCTL_DEBUG */		}#ifdef WE_SET_EVENT		/* Generate an event to notify listeners of the change */		if((descr->flags & IW_DESCR_FLAG_EVENT) &&		   ((ret == 0) || (ret == -EIWCOMMIT))) {			if(descr->flags & IW_DESCR_FLAG_RESTRICT)				/* If the event is restricted, don't				 * export the payload */				wireless_send_event(dev, cmd, &(iwr->u), NULL);			else				wireless_send_event(dev, cmd, &(iwr->u),						    extra);		}#endif	/* WE_SET_EVENT */		/* Cleanup - I told you it wasn't that long ;-) */		kfree(extra);	}	/* Call commit handler if needed and defined */	if(ret == -EIWCOMMIT)		ret = call_commit_handler(dev);	/* Here, we will generate the appropriate event if needed */	return ret;}/* ---------------------------------------------------------------- *//* * Wrapper to call a private Wireless Extension handler. * We do various checks and also take care of moving data between * user space and kernel space. * It's not as nice and slimline as the standard wrapper. The cause * is struct iw_priv_args, which was not really designed for the * job we are going here. * * IMPORTANT : This function prevent to set and get data on the same * IOCTL and enforce the SET/GET convention. Not doing it would be * far too hairy... * If you need to set and get data at the same time, please don't use * a iw_handler but process it in your ioctl handler (i.e. use the * old driver API). */static inline int ioctl_private_call(struct net_device *	dev,				     struct ifreq *		ifr,				     unsigned int		cmd,				     iw_handler		handler){	struct iwreq *			iwr = (struct iwreq *) ifr;	struct iw_priv_args *		descr = NULL;	struct iw_request_info		info;	int				extra_size = 0;	int				i;	int				ret = -EINVAL;	/* Get the description of the IOCTL */	for(i = 0; i < dev->wireless_handlers->num_private_args; i++)		if(cmd == dev->wireless_handlers->private_args[i].cmd) {			descr = &(dev->wireless_handlers->private_args[i]);			break;		}#ifdef WE_IOCTL_DEBUG	printk(KERN_DEBUG "%s (WE) : Found private handler for 0x%04X\n",	       ifr->ifr_name, cmd);	if(descr) {		printk(KERN_DEBUG "%s (WE) : Name %s, set %X, get %X\n",		       dev->name, descr->name,		       descr->set_args, descr->get_args);	}#endif	/* WE_IOCTL_DEBUG */	/* Compute the size of the set/get arguments */	if(descr != NULL) {		if(IW_IS_SET(cmd)) {			int	offset = 0;	/* For sub-ioctls */			/* Check for sub-ioctl handler */			if(descr->name[0] == '\0')				/* Reserve one int for sub-ioctl index */				offset = sizeof(__u32);			/* Size of set arguments */			extra_size = get_priv_size(descr->set_args);			/* Does it fits in iwr ? */			if((descr->set_args & IW_PRIV_SIZE_FIXED) &&			   ((extra_size + offset) <= IFNAMSIZ))				extra_size = 0;		} else {			/* Size of set arguments */			extra_size = get_priv_size(descr->get_args);			/* Does it fits in iwr ? */			if((descr->get_args & IW_PRIV_SIZE_FIXED) &&			   (extra_size <= IFNAMSIZ))				extra_size = 0;		}	}	/* Prepare the call */	info.cmd = cmd;	info.flags = 0;	/* Check if we have a pointer to user space data or not. */	if(extra_size == 0) {		/* No extra arguments. Trivial to handle */		ret = handler(dev, &info, &(iwr->u), (char *) &(iwr->u));	} else {		char *	extra;		int	err;		/* Check what user space is giving us */		if(IW_IS_SET(cmd)) {			/* Check NULL pointer */			if((iwr->u.data.pointer == NULL) &&			   (iwr->u.data.length != 0))				return -EFAULT;			/* Does it fits within bounds ? */			if(iwr->u.data.length > (descr->set_args &						 IW_PRIV_SIZE_MASK))				return -E2BIG;		} else {			/* Check NULL pointer */			if(iwr->u.data.pointer == NULL)				return -EFAULT;		}#ifdef WE_IOCTL_DEBUG		printk(KERN_DEBUG "%s (WE) : Malloc %d bytes\n",		       dev->name, extra_size);#endif	/* WE_IOCTL_DEBUG */		/* Always allocate for max space. Easier, and won't last		 * long... */		extra = kmalloc(extra_size, GFP_KERNEL);		if (extra == NULL) {			return -ENOMEM;		}		/* If it is a SET, get all the extra data in here */		if(IW_IS_SET(cmd) && (iwr->u.data.length != 0)) {			err = copy_from_user(extra, iwr->u.data.pointer,					     extra_size);			if (err) {				kfree(extra);				return -EFAULT;			}#ifdef WE_IOCTL_DEBUG			printk(KERN_DEBUG "%s (WE) : Got %d elem\n",			       dev->name, iwr->u.data.length);#endif	/* WE_IOCTL_DEBUG */		}		/* Call the handler */		ret = handler(dev, &info, &(iwr->u), extra);		/* If we have something to return to the user */		if (!ret && IW_IS_GET(cmd)) {			err = copy_to_user(iwr->u.data.pointer, extra,					   extra_size);			if (err)				ret =  -EFAULT;				   #ifdef WE_IOCTL_DEBUG			printk(KERN_DEBUG "%s (WE) : Wrote %d elem\n",			       dev->name, iwr->u.data.length);#endif	/* WE_IOCTL_DEBUG */		}		/* Cleanup - I told you it wasn't that long ;-) */		kfree(extra);	}	/* Call commit handler if needed and defined */	if(ret == -EIWCOMMIT)		ret = call_commit_handler(dev);	return ret;}/* ---------------------------------------------------------------- *//* * Main IOCTl dispatcher. Called from the main networking code * (dev_ioctl() in net/core/dev.c). * Check the type of IOCTL and call the appropriate wrapper... */int wireless_process_ioctl(struct ifreq *ifr, unsigned int cmd){	struct net_device *dev;	iw_handler	handler;	/* Permissions are already checked in dev_ioctl() before calling us.	 * The copy_to/from_user() of ifr is also dealt with in there */	/* Make sure the device exist */	if ((dev = __dev_get_by_name(ifr->ifr_name)) == NULL)		return -ENODEV;	/* A bunch of special cases, then the generic case...	 * Note that 'cmd' is already filtered in dev_ioctl() with	 * (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) */	switch(cmd) 	{		case SIOCGIWSTATS:			/* Get Wireless Stats */			return dev_iwstats(dev, ifr);		case SIOCGIWPRIV:			/* Check if we have some wireless handlers defined */			if(dev->wireless_handlers != NULL) {				/* We export to user space the definition of				 * the private handler ourselves */				return ioctl_export_private(dev, ifr);			}			// ## Fall-through for old API ##		default:			/* Generic IOCTL */			/* Basic check */

⌨️ 快捷键说明

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