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

📄 am930llc.c

📁 Linux Wireless LAN Project 的目标是开发一个完整的
💻 C
📖 第 1 页 / 共 3 页
字号:
/* am930llc.c: Handles the Linux network interface*	--------------------------------------------------------------------**   Linux WLAN **   The contents of this file are subject to the Mozilla Public*   License Version 1.0 (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.**   The initial developer of the original code is Mark S. Mathews*   <mark@absoval.com>.  Portions created by Mark S. Mathews*   are Copyright (C) 1998 AbsoluteValue Software, Inc.  All Rights Reserved.*   *	--------------------------------------------------------------------**	The author may be reached as mark@absoval.com, or C/O AbsoluteValue*	Software Inc., P.O. Box 941149, Maitland, FL, 32794-1149**	Thanks to David Hinds, Donald Becker, and the rest of the Linux*	developers worldwide for making all of this possible.**	--------------------------------------------------------------------**	Seperate file isolating the functions that handle the Linux network*	interface. LLC may not be the appropriate name, but this code _does_*	sit on top of the MAC...**/#include <linux/config.h>#include <wlan/wlan_compat.h>/* The following prevents "kernel_version" from being set in this file. */#define __NO_VERSION__/* PCMCIA headers generated during PCMCIA package installation */#ifdef WLAN_PCMCIA#include <pcmcia/config.h>#include <pcmcia/k_compat.h>#endif/* Module related headers, non-module drivers should not include */#include <linux/version.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/sched.h>/* Ethernet and network includes */#include <linux/if_ether.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/skbuff.h>#include <linux/if_arp.h>#include <linux/ioport.h>#include <net/sock.h>#include <linux/netlink.h>/* Standard driver includes */#include <linux/delay.h>#include <linux/types.h>#include <linux/fcntl.h>#include <asm/system.h>#include <asm/bitops.h>#include <asm/io.h>#include <asm/uaccess.h>#include <linux/in.h>#include <linux/ptrace.h>#include <linux/interrupt.h>#include <linux/in.h>#include <linux/malloc.h>#include <linux/string.h>#include <linux/timer.h>#include <linux/errno.h>/* Card and Driver services includes */#ifdef WLAN_PCMCIA#include <pcmcia/version.h>#include <pcmcia/cs_types.h>#include <pcmcia/cs.h>#include <pcmcia/cistpl.h>#include <pcmcia/ds.h>#include <pcmcia/cisreg.h>#endif/* Local Includes */#include <wlan/version.h>#include <wlan/wlan_compat.h>#include <wlan/am930mib.h>#include <wlan/wlan_ioctl.h>#ifdef WLAN_PCMCIA#include "am930di.h"#endif#include "am930llc.h"#include "am930mac.h"#include "am930hw.h"#include "am930mgr.h"/*================================================================*//* Local Macros  */#define WLAN_DEVNAME_LEN	9/*================================================================*//* Local Types  */#if LINUX_VERSION_CODE <= 0x20139typedef struct enet_statistics	enet_stats_t;#elsetypedef struct net_device_stats	enet_stats_t;#endiftypedef struct devpriv{	enet_stats_t	stats;	am930llc_t*		llc;} devpriv_t;typedef int (*do_ioctl_t)(device_t *dev, struct ifreq *ifr, int cmd);typedef void (*timerfunc_t)(unsigned long);/*================================================================*//* Local Functions  */static int am930llc_devinit(device_t *dev);static int am930llc_devopen(device_t *dev);static int am930llc_devstop(device_t *dev);static int am930llc_devhard_start_xmit( struct sk_buff *skb, device_t *dev);static enet_stats_t* am930llc_devgetstats(device_t *dev);static void am930llc_devset_multicast_list(device_t *dev);static int am930llc_devdo_ioctl(device_t *dev, wlan_req_t *req, int cmd);void am930llc_timerfunc(am930llc_t *llc);void am930llc_cmdtimerfunc(am930llc_t *llc);void am930llc_nlfunc(struct sock *sk, int len);/*================================================================*//* Static variables  */UINT8	oui_rfc1042[] = {0x00, 0x00, 0x00};UINT8	oui_8021h[] = {0x00, 0x00, 0xf8};/*================================================================*//*----------------------------------------------------------------*	am930llc_construct**	returns: addr. of the lnd object if successful, NULL otherwise----------------------------------------------------------------*/am930llc_t *am930llc_construct(am930mac_t *mac, am930mgr_t *mgr){	am930llc_t *llc;	DBFENTER;	llc = kmalloc( sizeof(am930llc_t), GFP_KERNEL);	if ( llc != NULL )	{		memset( llc, 0, sizeof(am930llc_t));		llc->mac = mac;		llc->mgr = mgr;		llc->ethconv = WLAN_ETHCONV_ENCAP;	/* set by user later */		/* lets begin the initialization of the linux device */		llc->dev = kmalloc( sizeof(device_t), GFP_KERNEL);		if ( llc->dev == NULL )		{			kfree_s(llc, sizeof(am930llc_t));			return NULL;		}		memset( llc->dev, 0, sizeof(device_t));		llc->dev->priv = kmalloc( sizeof(devpriv_t), GFP_KERNEL);		if ( llc->dev->priv == NULL )		{		 	kfree_s(llc->dev, sizeof(device_t));			kfree_s(llc, sizeof(am930llc_t));			return NULL;		}		memset( llc->dev->priv, 0, sizeof(devpriv_t));		/* the dev name field will point to the same memory used by the 			node_t field of the pcmcia di object */		#ifdef WLAN_PCMCIA		llc->dev->name = ((dev_link_t*)(llc->mac->di))->dev->dev_name;		#else		llc->dev->name = kmalloc(WLAN_DEVNAME_LEN, GFP_KERNEL);		if ( llc->dev->name == NULL )		{			WLAN_LOG_ERROR0("Failed to alloc device name space.\n");			kfree_s( llc->dev->priv, sizeof(devpriv_t));			kfree_s( llc->dev, sizeof(device_t));			kfree_s( llc, sizeof(am930llc_t));			return NULL;		}		llc->dev->name[0] = '\0';		#endif		/* set the private data to point back at the llc */		V2P(llc->dev->priv)->llc = llc;		/* set the hardware address */		am930mgr_mibgetitem( llc->mgr, ADDR_MAC_ADDR, llc->dev->dev_addr, 6);		/* set the method pointers */		llc->dev->init					= am930llc_devinit;		llc->dev->open					= am930llc_devopen;		llc->dev->stop					= am930llc_devstop;		llc->dev->hard_start_xmit 		= am930llc_devhard_start_xmit;		llc->dev->get_stats				= am930llc_devgetstats;		llc->dev->set_multicast_list	= am930llc_devset_multicast_list;		llc->dev->do_ioctl				= (do_ioctl_t)am930llc_devdo_ioctl;		ether_setup( llc->dev );		if ( register_netdev(llc->dev) != 0 )		{			WLAN_LOG_ERROR0("register_netdev failed!\n");			kfree( llc->dev );			llc->dev = NULL;			am930llc_destruct( llc );			llc = NULL;		}		WLAN_LOG_INFO1("Device %s registered\n", llc->dev->name);#if 0		/* now set up the kernel timer */		init_timer(&llc->timer);		llc->timer.data = (unsigned long)llc;		llc->timer.function = (timerfunc_t)am930llc_timerfunc;		llc->timer.expires = jiffies + (HZ / 10);		add_timer(&llc->timer);#endif		/* set up the netlink i/f for a potential sniffer */		llc->nlsk = netlink_kernel_create( NETLINK_USERSOCK, am930llc_nlfunc);		if ( llc->nlsk == NULL )		{			WLAN_LOG_WARNING0("Failed to create netlink i/f.\n");		}	}	DBFEXIT    return llc;} /*----------------------------------------------------------------*	am930llc_cmdtimerfunc*	One shot timer func called when an ioctl command has timed out.**	returns: nothing----------------------------------------------------------------*/void am930llc_cmdtimerfunc(am930llc_t *llc){	DBFENTER;	/* clear the expires field as a flag that we've timed out */	llc->timer.expires = 0;	/* Assume the timer was set up to watch us while an ioctl's in */	/*  the wait queue.  Check for NULL and if not, wake it */	if ( llc->cmdwq != NULL ){		wake_up_interruptible(&(llc->cmdwq));	}	DBFEXIT;	return;}/*----------------------------------------------------------------*	am930llc_timerfunc*	Called 10 times per second.  Calls any timer functions*	established by the other components.**	returns: nothing----------------------------------------------------------------*/void am930llc_timerfunc(am930llc_t *llc){	DBFENTER;	if ( llc->mac != NULL && llc->mac->timerfunc != NULL )	{		(*llc->mac->timerfunc)(llc->mac);		if ( llc->mac->hw != NULL && llc->mac->hw->timerfunc != NULL )		{			(*llc->mac->hw->timerfunc)(llc->mac->hw);		}	}	if ( llc->mgr != NULL && llc->mgr->timerfunc != NULL )	{		(*llc->mgr->timerfunc)(llc->mgr);	}	init_timer(&llc->timer);	llc->timer.data = (unsigned long)llc;	llc->timer.function = (timerfunc_t)am930llc_timerfunc;	llc->timer.expires = jiffies + (HZ / 10);	add_timer(&llc->timer);	DBFEXIT;}/*----------------------------------------------------------------*	am930llc_destruct**	returns: nothing----------------------------------------------------------------*/void am930llc_destruct( am930llc_t *llc){	DBFENTER;	if ( llc->dev != NULL )	{		del_timer(&llc->timer);		llc->dev->start = 0;		unregister_netdev( llc->dev );		kfree(llc->dev);		llc->dev = NULL;	}	kfree_s( llc, sizeof(am930llc_t));	DBFEXIT;	return;}/*----------------------------------------------------------------*	am930llc_devinit*	init method for the linux net device. Called by *	register_netdevice. For this driver, it doesn't have to do*	anything.**	returns: zero----------------------------------------------------------------*/int am930llc_devinit(device_t *dev){	int result = 0;	DBFENTER;	DBFEXIT;	return result;}/*----------------------------------------------------------------*	am930llc_cmdcomplete*	Called by mgr whenever one of our asynch commands *	(scan, auth,assoc,etc.)	finishes.  Our primary responsibility*	here is to wake up any waiting process (blocked in ioctl).*	See also: cmdtimerfunc**	returns: nothing----------------------------------------------------------------*/void am930llc_cmdcomplete(am930llc_t *llc, UINT status){	DBFENTER;		if ( llc->cmdwq != NULL ){		llc->cmdstatus = status;		wake_up_interruptible(&(llc->cmdwq));	}	DBFEXIT;	return;}/*----------------------------------------------------------------*	am930llc_devdo_ioctl*	do_ioctl method for the linux net device. Private ioctl handler*	for the net device. Used here to pass commands to the mgr*	object.*	TODO: Define the interface between the mgr object and user*			mode utilities. **	returns: zero----------------------------------------------------------------*/int am930llc_devdo_ioctl(device_t *dev, wlan_req_t *req, int cmd){	int 		result = 0;	am930llc_t	*llc = V2P(dev->priv)->llc;	DBFENTER;	/* According to Alan, we're supposed to check the req ptr and data area */	/* here, but aside from a NULL check, I'm not quite sure how. */	/* Now that we have the blocks and timers, etc. We should sync access */	if ( req == NULL ) {		result = -EFAULT;	} else {		if ( test_and_set_bit( 0, (void*)&(llc->cmdbusy))) {			return -EBUSY;		}		llc->currcmd = cmd;		switch( cmd )		{			case WLAN_TEST:				req->result = 0xf0f0;				break;			case WLAN_SCAN:			{				wlan_scan_t	cmd;				UINT32		timeout = HZ;	/* default 1 second */				UINT32		scanticks = 0;								if ( copy_from_user( &cmd, req->data, sizeof(cmd)) ) {					result = -EFAULT;					break;				}								/* Call mgr to begin the scan */				req->result = am930mgr_scanbegin( llc->mgr,										cmd.scantype,	/*active/passive*/										cmd.bsstype,	/*ind./infra./both*/										cmd.bssid,		/*bcast/specific*/										cmd.startch,											cmd.endch,										cmd.timech,	/*time per ch.*/										(wlan_ie_ssid_t*)cmd.ssid); 				/* Set a timer for (timech * nchannels + slop) to make */				/*  sure we  return */				scanticks = wlan_tu2ticks(((cmd.endch-cmd.startch)*cmd.timech));				scanticks += (HZ/5);  /* a little extra for slop */				if ( scanticks > timeout ) {					timeout = scanticks;				}				init_timer(&llc->cmdtimer);				llc->cmdtimer.data = (unsigned long)llc;				llc->cmdtimer.function = (timerfunc_t)am930llc_cmdtimerfunc;				llc->cmdtimer.expires = jiffies + timeout;				add_timer(&llc->cmdtimer);				/* Now, do an interruptible_sleep, we'll be awakened by: */				/*  a signal the process, cmdtimerfunc (timeout), or llc_scancomplete */				interruptible_sleep_on(&(llc->cmdwq));				llc->cmdwq = NULL;				/* If sleep return is via signal */				if ( signal_pending(current) ) {					WLAN_LOG_DEBUG0(2,"Scan unblocked via signal\n");					/* stop scan, clean up scan and timer */					am930mgr_scanstop(llc->mgr);					del_timer(&llc->cmdtimer);					result = -EINTR;				} else {					/* If timeout */					if ( llc->cmdtimer.expires == 0 )					{						WLAN_LOG_DEBUG0(2,"Scan unblocked via timeout\n");						/* stop scan, clean up scan */						am930mgr_scanstop(llc->mgr);						result = -ETIME;					} else {						/* Success */						/* clean up timer */						del_timer(&llc->cmdtimer);						llc->cmdtimer.expires=0;						req->result = llc->cmdstatus;						/* return success */						result = 0;					}				}				break;			}			case WLAN_NETLIST_LEN:			{					wlan_netlist_len_t cmd;				knownbss_t		*curr;				int				i;				am930mgr_t*		mgr = llc->mgr;				i = 0;				for( curr = mgr->bsslist; curr != NULL; curr = curr->next) {					i++;				}				cmd.nitems = i;				if ( copy_to_user( req->data, &cmd, sizeof(cmd)) ) {					result = -EFAULT;				}				req->result = 0;				break;			}			case WLAN_NETLIST:			{				wlan_netlist_t 	*cmd;				wlan_netlist_t 	tmp;				knownbss_t		*curr;				wlan_ie_ssid_t	*ie;				int				i;				am930mgr_t*		mgr = llc->mgr;				if ( copy_from_user( &tmp, req->data, sizeof(tmp)) ) {					result = -EFAULT;					break;				}				cmd = kmalloc(sizeof(wlan_netlist_t) + 						(tmp.nitems * sizeof(netitem_t)), GFP_ATOMIC);				if ( cmd == NULL ) {					result = -ENOMEM;					break;				}				cmd->nitems = tmp.nitems;				i = 0;				for( curr = mgr->bsslist; curr != NULL; curr = curr->next)				{					cmd->netlist[i].channel = curr->channel;					cmd->netlist[i].bcn_int = curr->bcn_int;					cmd->netlist[i].cap_info = curr->cap_info;					memcpy(cmd->netlist[i].bssid, curr->bssid, 6);					ie = (wlan_ie_ssid_t*)curr->ssid;					memcpy(cmd->netlist[i].ssid, ie, ie->len + 2);					i++;				}				if ( copy_to_user( req->data, cmd, 						sizeof(wlan_netlist_t) + 						(cmd->nitems * sizeof(netitem_t))) ) {					result = -EFAULT;				}				kfree_s(cmd, sizeof(wlan_netlist_t)+(tmp.nitems*sizeof(netitem_t)));				break;			}			case WLAN_BSSCREATE:			{				wlan_bsscreate_t cmd;				if (copy_from_user( &cmd, req->data, sizeof(cmd))) {					result = -EFAULT;					break;				}				req->result = am930mgr_createbss( llc->mgr, 									cmd.channel, 

⌨️ 快捷键说明

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