p80211req.c

来自「Linux的无线局域网方案是一个Linux设备驱动程序和子系统 一揽子方案的用」· C语言 代码 · 共 438 行

C
438
字号
/* src/p80211/p80211req.c** Request/Indication/MacMgmt interface handling functions** Copyright (C) 1999 AbsoluteValue Systems, Inc.  All Rights Reserved.* --------------------------------------------------------------------** linux-wlan**   The contents of this file are subject to the Mozilla Public*   License Version 1.1 (the "License"); you may not use this file*   except in compliance with the License. You may obtain a copy of*   the License at http://www.mozilla.org/MPL/**   Software distributed under the License is distributed on an "AS*   IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or*   implied. See the License for the specific language governing*   rights and limitations under the License.**   Alternatively, the contents of this file may be used under the*   terms of the GNU Public License version 2 (the "GPL"), in which*   case the provisions of the GPL are applicable instead of the*   above.  If you wish to allow the use of your version of this file*   only under the terms of the GPL and not to allow others to use*   your version of this file under the MPL, indicate your decision*   by deleting the provisions above and replace them with the notice*   and other provisions required by the GPL.  If you do not delete*   the provisions above, a recipient may use your version of this*   file under either the MPL or the GPL.** --------------------------------------------------------------------** Inquiries regarding the linux-wlan Open Source project can be* made directly to:** AbsoluteValue Systems Inc.* info@linux-wlan.com* http://www.linux-wlan.com** --------------------------------------------------------------------** Portions of the development of this software were funded by * Intersil Corporation as part of PRISM(R) chipset product development.** --------------------------------------------------------------------** This file contains the functions, types, and macros to support the* MLME request interface that's implemented via the device ioctls.* * --------------------------------------------------------------------*//*================================================================*//* System Includes */#define __NO_VERSION__		/* prevent the static definition */#include <linux/config.h>#include <linux/version.h>#include <wlan/wlan_compat.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/types.h>#include <linux/skbuff.h>#include <linux/slab.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <net/sock.h>#include <linux/netlink.h>/*================================================================*//* Project Includes */#include <wlan/version.h>#include <wlan/p80211types.h>#include <wlan/p80211hdr.h>#include <wlan/p80211mgmt.h>#include <wlan/p80211conv.h>#include <wlan/p80211msg.h>#include <wlan/p80211netdev.h>#include <wlan/p80211ioctl.h>#include <wlan/p80211metadef.h>/*================================================================*//* Local Constants *//* Maximum amount of time we'll wait for a request to complete */#define P80211REQ_MAXTIME	3*HZ	/* 3 seconds *//*================================================================*//* Local Macros *//*================================================================*//* Local Types */typedef void (*timerfunc_t)(unsigned long);/*================================================================*//* Local Static Definitions *//* Netlink interface(s) */static struct sock	*nl_indicate = NULL;/*================================================================*//* Local Function Declarations */static void p80211req_timerfunc(wlandevice_t *wlandev);static void p80211req_handlemsg( wlandevice_t *wlandev, p80211msg_t *msg);#ifdef CONFIG_NETLINKstatic void p80211ind_rx(struct sock *sk, int len);#endif/*================================================================*//* Function Definitions *//*----------------------------------------------------------------* p80211req_dorequest** Handles an MLME reqest/confirm message.* * Arguments:*	wlandev		WLAN device struct*	msgbuf		Buffer containing a request message** Returns: *	0 on success, an errno otherwise*	* Call context:*	Potentially blocks the caller, so it's a good idea to *	not call this function from an interrupt context.----------------------------------------------------------------*/int p80211req_dorequest( wlandevice_t *wlandev, UINT8 *msgbuf){	int		result = 0;	int		retval;	p80211msg_t	*msg = (p80211msg_t*)msgbuf;	DBFENTER;	/* Check to make sure the MSD is running */	if ( 	!((wlandev->msdstate == WLAN_MSD_HWPRESENT &&	msg->msgcode == DIDmsg_lnxreq_ifstate) ||	wlandev->msdstate == WLAN_MSD_RUNNING || 	wlandev->msdstate == WLAN_MSD_FWLOAD) ) {		return -ENODEV;	}	/* Check for busy status */	if ( test_and_set_bit(1, &(wlandev->request_pending))) {		return -EBUSY;	}	wlandev->curr_msg = msg;	/* Allow p80211 to look at msg and handle if desired. */	/* So far, all p80211 msgs are immediate, no waitq/timer necessary */	/* This may change. */	p80211req_handlemsg(wlandev, msg);	/* Pass it down to wlandev via wlandev->mlmerequest */	if ( wlandev->mlmerequest != NULL ) {		retval = (*(wlandev->mlmerequest))(wlandev, msg);		if (retval < 0) {			/* wlandev is still chewing on it, time to block */			/* set up wait_q and timeout */			init_timer(&wlandev->reqtimer);			wlandev->reqtimer.data = (unsigned long)wlandev;			wlandev->reqtimer.function = 				(timerfunc_t)p80211req_timerfunc;			wlandev->reqtimer.expires = jiffies + P80211REQ_MAXTIME;			add_timer(&wlandev->reqtimer);			/* Now, do an interruptible_sleep, */			/* we'll be awakened by: a signal to the process, */			/* cmdtimerfunc (timeout), or p80211req_confirm */			interruptible_sleep_on(&(wlandev->reqwq));			/* If sleep return is via signal */			if ( signal_pending(current) ) {				WLAN_LOG_DEBUG0(2,"req unblocked via signal\n");				/* stop request, clean up */				del_timer(&wlandev->reqtimer);				result = -EINTR;			} else {				/* If timeout */				if ( wlandev->reqtimer.expires == 0 )				{					WLAN_LOG_DEBUG0(2,						"req unblocked via timeout\n");					/* stop request, clean up request */					result = -ETIME;				} else {					/* Success, clean up timer */					del_timer(&wlandev->reqtimer);					wlandev->reqtimer.expires=0;					result = 0;				}			}		} else {			result = -retval;  /* retval shld be a positive errno */		}	}	wlandev->curr_msg = NULL;	clear_bit( 1, &(wlandev->request_pending));	DBFEXIT;	return result;	/* if result==0, msg->status still may contain an err */}/*----------------------------------------------------------------* p80211req_timerfunc** Timer function for request timeouts.* * Arguments:*	wlandev		WLAN device struct** Returns: *	nothing*	* Call context:*	Timer interrupt----------------------------------------------------------------*/void p80211req_timerfunc(wlandevice_t *wlandev){	wlandev->reqtimer.expires = 0;	if (wlandev->request_pending != 0) {		wake_up_interruptible(&(wlandev->reqwq));	}}/*----------------------------------------------------------------* p80211req_handlemsg** p80211 message handler.  Primarily looks for messages that* belong to p80211 and then dispatches the appropriate response.* TODO: we don't do anything yet.  Once the linuxMIB is better*	defined we'll need a get/set handler.  * * Arguments:*	wlandev		WLAN device struct*	msg		message structure** Returns: *	nothing (any results are set in the status field of the msg)*	* Call context:*	Process thread----------------------------------------------------------------*/void p80211req_handlemsg( wlandevice_t *wlandev, p80211msg_t *msg){	return;}/*----------------------------------------------------------------* p80211req_confirm** Called by the MSD when an asynch request is finished.  Our* primary job here is to unblock the _dorequest function above.* * Arguments:*	wlandev		WLAN device struct** Returns: *	nothing*	* Call context:*	Any----------------------------------------------------------------*/void	p80211req_confirm(wlandevice_t *wlandev){	DBFENTER;	if ( wlandev->request_pending != 0 ){		wake_up_interruptible(&(wlandev->reqwq));	}	DBFEXIT;	return;}#ifdef CONFIG_NETLINK/*----------------------------------------------------------------* p80211indicate_init** Called during the p80211 startup to set up the netlink interfaces* for sniffing and indication messages.* * Arguments:*	none** Returns: *	nothing*	* Call context:*	Any----------------------------------------------------------------*/void p80211indicate_init(void){	DBFENTER;	nl_indicate = 		netlink_kernel_create( P80211_NL_SOCK_IND, &p80211ind_rx);	if ( nl_indicate == NULL ) {		WLAN_LOG_DEBUG0(2,"Failed to create indicate netlink i/f.\n");	}	DBFEXIT;	return;}/*----------------------------------------------------------------* p80211indicate_shutdown** Called during the p80211 unload to get rid of our netlink * interface.* * Arguments:*	none** Returns: *	nothing*	* Call context:*	Any----------------------------------------------------------------*/void p80211indicate_shutdown(void){	struct sock	*nl;	DBFENTER;	nl = nl_indicate;	nl_indicate = NULL;	if ( nl != NULL && nl->socket != NULL) {		sock_release(nl->socket);	}	DBFEXIT;	return;}/*----------------------------------------------------------------* p80211ind_rx** Called by netlink when a message comes down.  We currently don't* support message from userland via netlink, so this is a empty* function.* * Arguments:*	sk		netlink sock*	len		msg len** Returns: *	nothing*	* Call context:*	Any----------------------------------------------------------------*/void p80211ind_rx(struct sock *sk, int len){	return;}/*----------------------------------------------------------------* p80211ind_mlme** Called by the MSD to deliver an mlme type indication message.* * Arguments:*	wlandev		WLAN device struct*	skb		skb containing message to deliver** Returns: *	nothing*	* Call context:*	Any----------------------------------------------------------------*/void p80211ind_mlme( wlandevice_t *wlandev, struct sk_buff *skb){	DBFENTER;	if ( nl_indicate != NULL ) {/* TODO: Look at queuing mlme indications when requests are pending. */		netlink_broadcast(nl_indicate, 			skb, 0, P80211_NL_MCAST_GRP_MLME, GFP_ATOMIC);	} else {		WLAN_LOG_DEBUG0(2,"Can't send indicate msg, no netlink i/f\n");	}	DBFEXIT;	return;}/*----------------------------------------------------------------* p80211ind_distribution** Called by the MSD to deliver a distribution system type * indication message.* * Arguments:*	wlandev		WLAN device struct*	skb		skb containing message to deliver** Returns: *	nothing*	* Call context:*	Any----------------------------------------------------------------*/void p80211ind_distribution( wlandevice_t *wlandev, struct sk_buff *skb){	DBFENTER;	if ( nl_indicate != NULL ) {/*		skb = alloc_skb(len, GFP_ATOMIC);		skb_put(skb, len);		memcpy(skb->data, msg, len);*/		netlink_broadcast(nl_indicate, 			skb, 0, P80211_NL_MCAST_GRP_DIST, GFP_ATOMIC);	} else {		WLAN_LOG_DEBUG0(2,"Can't send indicate msg, no netlink i/f\n");	}	DBFEXIT;	return;}#endif /* CONFIG_NETLINK */

⌨️ 快捷键说明

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