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

📄 sm_drv.c

📁 cx3110 drivers for linux 2.6 (基于SPI)
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * src/sm_drv.c * * Copyright (C) 2003 Conexant Americas Inc. All Rights Reserved. * Copyright (C) 2004, 2005, 2006 Nokia Corporation * Author: Samuel Ortiz <samuel.ortiz@nokia.com> * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * */#define __KERNEL_SYSCALLS__#include <linux/version.h>#ifdef MODULE#ifdef MODVERSIONS#include <linux/modversions.h>#endif#include <linux/module.h>#else#define MOD_INC_USE_COUNT#define MOD_DEC_USE_COUNT#endif#include <linux/init.h>#include <linux/types.h>#include <linux/sched.h>#include <linux/unistd.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/if_arp.h>#include <linux/string.h>#include <linux/poll.h>#include <linux/platform_device.h>#include <asm/uaccess.h>#include "sm_drv.h"#include "sm_drv_ioctl.h"#include "sm_drv_sysfs.h"extern char driver_name[64];/* for linux/unistd.h */int errno;DECLARE_COMPLETION(softmac_init_comp);extern struct net_device *root_sm_drv_device;/* Timers */void driver_timer_expired(unsigned long handle){	struct net_device *dev = (struct net_device *) handle;	struct net_local *lp = dev->priv;	int32_t callb_mask;		spin_lock_bh(&lp->sm_lock);		callb_mask = prism_softmac_service(lp->sm_context);	spin_unlock_bh(&lp->sm_lock);		if(callb_mask < 0)		printk(KERN_INFO "timer_expired: sm_service returned error %d\n", callb_mask);	else {		handle_sm_callback(dev, callb_mask);	}	}void sm_drv_disassociate(struct net_device *dev){	struct obj_ssid essid;	struct net_local *lp = dev->priv;	lp->link_state = DOT11_STATE_NONE;	/* 	 * By setting a new essid, UMAC will diassociates from the current	 * AP. If this is the broadcast SSID, it won't try to reconnect	 * to another AP.	 */	memset(essid.octets, 0, 33);	essid.length = 0;		sm_drv_oid_set(dev, DOT11_OID_SSID, (void*)&essid, sizeof(struct obj_ssid));}/****************************************************************************** *   SoftMAC Callback ******************************************************************************/static const char nokia_wireless_biz_oui[3] = {0x00, 0xe0, 0x03};static int32_t handle_sm_trap(struct net_device *dev, struct s_sm_conf *trap){	struct net_local *lp = dev->priv;	int32_t result = SM_ENONE, ret;	struct obj_mlme *mlme = (struct obj_mlme*)trap->data;	struct obj_sta *sta = (struct obj_sta*)trap->data;	uint8_t state = DOT11_STATE_ASSOCING;	uint8_t null_mac[ETH_ALEN] = {0x0,0x0,0x0,0x0,0x0,0x0};	uint32_t scan_mode = SCAN_MODE_ACTIVE, scan = -1;	switch(trap->oid) {	case GEN_OID_MACADDRESS:		DEBUG(DBG_ALL, "%s: MAC address %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",		      driver_name,		      trap->data[0], trap->data[1], trap->data[2],		      trap->data[3], trap->data[4], trap->data[5]);		if (!memcmp(dev->dev_addr, null_mac, ETH_ALEN))			memcpy(dev->dev_addr, trap->data, ETH_ALEN);		else			/* If we set the MAC address before booting, let's not copy the PDA one */			result = sm_drv_oid_set(dev, GEN_OID_MACADDRESS, (void*)dev->dev_addr, ETH_ALEN);				/* If we got the MAC address, this means the device has finished booting */		wake_up(&lp->conf_waitq);		if(lp->device_state == DEVSTATE_ACTIVE || lp->device_state == DEVSTATE_BOOTING)			lp->device_state = DEVSTATE_ACTIVE;		break;			case GEN_OID_LINKSTATE:		link_changed(dev, *((uint32_t*)trap->data));		break;		case DOT11_OID_AUTHENTICATE:		state = DOT11_STATE_AUTHING;		/* Intended */			case DOT11_OID_ASSOCIATE:	case DOT11_OID_REASSOCIATE:		if(lp->sm_mode == SM_MODE_CLIENT &&		   mlme->state != lp->link_state) {						DEBUG(DBG_TRACE, "Authenticate/(Re)Associate trap: state %d\n", mlme->state);						lp->link_state = mlme->state;			if (mlme->state == DOT11_STATE_ASSOC) {				lp->ext = mlme->ext;				sm_drv_parse_bssid(dev, mlme->address, DOT11_STATE_ASSOC, NULL);			}						/* This is the association request. We get the IE from the beacon */			if ((trap->oid == DOT11_OID_REASSOCIATE || trap->oid == DOT11_OID_ASSOCIATE) 			    && (mlme->state == DOT11_STATE_ASSOCING)) {				/* 				 * UGLY hack to workaround Nokia's AP bug:				 * When we set short slots in the capability field of the association request, 				 * A032 thinks that we can _only_ do short.				 * However, according to 802.11 standard, short slot bit set in the capability				 * bitfield implies that the device can do _both_ long and short. A032 doesn't				 * get that.				 * On the other hand, if we specifically set short slots, we will have trouble				 * with 11g devices, so we have to lamely check the AP MAC and see if this is				 * a Nokia one...Sorry.				 */				if (!memcmp(mlme->address, nokia_wireless_biz_oui, 3)) {					uint32_t profile = DOT11_PROFILE_B_WIFI;					if (sm_drv_oid_set(dev, DOT11_OID_PROFILES, (void*)&profile, sizeof(uint32_t)) < 0) {						result = -1;						break;					}				}				sm_drv_process_bss_data(dev, dev->dev_addr,							mlme->data, mlme->size, trap->oid);			}		}		break;			case DOT11_OID_SCAN:		DEBUG(DBG_ALL, "Scan complete, scanned %d channels\n", *((uint16_t*)trap->data));		/* We got the trap, we stop the scan timer.*/		del_timer_sync(&lp->scan_timer);		send_scan_complete(dev);		break;	case DOT11_OID_MICFAILURE:		DEBUG(DBG_ALL, "**** MIC FAILURE ****\n");		send_mic_failure(dev, sta);		break;	case DOT11_OID_DEAUTHENTICATE:		DEBUG(DBG_ALL,"DEAUTHENTICATE trap\n");		if (lp->link_state == DOT11_STATE_ASSOC) {						DEBUG(DBG_ALL,"Active scanning on >%s<\n", lp->ssid.octets);						ret = sm_drv_oid_set(dev, DOT11_OID_SCANMODE, (void*)&scan_mode, sizeof(uint32_t));			if (ret < 0)				DEBUG(DBG_ALL, "Couldn't set SCANMODE: %d\n", ret);						ret = sm_drv_oid_set(dev, DOT11_OID_SCANSSID, (void*)&lp->ssid, sizeof(struct obj_ssid));			if (ret < 0)				DEBUG(DBG_ALL, "Couldn't set SSID: %d\n", ret);						ret = sm_drv_oid_set(dev, DOT11_OID_SCAN, (void*)&scan, sizeof(int16_t));			if (ret < 0)				DEBUG(DBG_ALL, "Couldn't start scan: %d\n", ret);					}		break;	case DOT11_OID_DISASSOCIATE:		DEBUG(DBG_ALL,"DISASSOCIATE trap\n");		break;	default:		/* do nothing */		DEBUG(DBG_ALL, "Unhandled trap: 0x%x\n", trap->oid);		break;	}		return result; }static void sm_print_callback_mask(int32_t mask){	DEBUG(DBG_TRACE, "SoftMAC Mask: ");	if (mask & SM_TRAP)		DEBUG(DBG_TRACE, "SM_TRAP ");	if (mask & SM_FRAMETXDONE)		DEBUG(DBG_TRACE, "SM_FRAMETXDONE ");	if (mask & SM_FRAMERX)		DEBUG(DBG_TRACE, "SM_FRAMERX ");	if (mask & SM_IC)		DEBUG(DBG_TRACE, "SM_IC ");	DEBUG(DBG_TRACE, "\n");}static inline int sm_monitor_rx(struct net_device *dev, struct sk_buff **skb){	/* We get a 802.11 frame with a PPE sniffer header*/        struct sm_promisc_header *hdr = (struct sm_promisc_header *) (*skb)->data;	if (dev->type == ARPHRD_IEEE80211_PRISM) {		struct avs_80211_1_header *avs;		skb_pull(*skb, sizeof (struct sm_promisc_header));		if (skb_headroom(*skb) < sizeof (struct avs_80211_1_header)) {			struct sk_buff *newskb = skb_copy_expand(*skb,								 sizeof (struct									 avs_80211_1_header),								 0, GFP_ATOMIC);			if (newskb) {                                dev_kfree_skb_irq(*skb);                                *skb = newskb;			} else				return -1;			/* This behavior is not very subtile... */		}				/* make room for the new header and fill it. */		avs = (struct avs_80211_1_header *) skb_push(*skb,							     sizeof (struct avs_80211_1_header));				avs->version = cpu_to_be32(P80211CAPTURE_VERSION);		avs->length = cpu_to_be32(sizeof (struct avs_80211_1_header));		avs->mactime = cpu_to_be64(le64_to_cpu(hdr->clock));		avs->hosttime = cpu_to_be64(jiffies);		avs->phytype = cpu_to_be32(6);	/*OFDM: 6 for (g), 8 for (a) */		avs->channel = cpu_to_be32(0);//channel_of_freq(freq));		avs->datarate = cpu_to_be32(hdr->rate * 5);		avs->antenna = cpu_to_be32(0);	/*unknown */		avs->priority = cpu_to_be32(0);	/*unknown */		avs->ssi_type = cpu_to_be32(3);	/*2: dBm, 3: raw RSSI */		avs->ssi_signal = cpu_to_be32(hdr->rssi & 0x7f);		avs->ssi_noise = cpu_to_be32(0);//priv->local_iwstatistics.qual.noise);	/*better than 'undefined', I assume */		avs->preamble = cpu_to_be32(0);	/*unknown */		avs->encoding = cpu_to_be32(0);	/*unknown */	} else		skb_pull(*skb, sizeof (struct sm_promisc_header));		(*skb)->protocol = ETH_P_802_2;//htons(ETH_P_802_2);	(*skb)->mac.raw = (*skb)->data;        (*skb)->pkt_type = PACKET_OTHERHOST;        return 0;}void handle_sm_callback(struct net_device *dev, int32_t mask){	struct net_local *lp = dev->priv;	struct spi_hif_local_data *hif_lp = HIF_LP(lp);	struct s_sm_frame *frame;	struct sk_buff *skb;	int32_t new_mask, tx_dropped = 0;	while(mask) {		DEBUG(DBG_TRACE, "%s: callback mask 0x%x\n", driver_name, mask);		sm_print_callback_mask(mask);				if(mask & SM_FRAMETXDONE) {			spin_lock_bh(&lp->sm_lock);			new_mask = prism_softmac_frame_tx_done( lp->sm_context, &frame );			spin_unlock_bh(&lp->sm_lock);			if( new_mask < 0 ) {				printk(KERN_WARNING "handle_sm_callback: sm_frame_tx_done returned error %d\n", new_mask);			} else {				mask = new_mask;			}						if(frame != NULL) {				if( frame->flags & SM_FRAME_TXDROPPED ) {					printk("TX dropped\n");					lp->stats.tx_errors++;					lp->stats.tx_dropped++;					tx_dropped = 1;				} else if(frame->flags & SM_FRAME_TXFAILED) {					lp->stats.tx_errors++;					tx_dropped = 0;				} else {					lp->stats.tx_packets++;					hif_lp->initial_packets++;					lp->stats.tx_bytes += frame->length;					tx_dropped = 0;				}								/* Free the frame and SKB frame in done */				frame_skb_free(dev, frame);								/* We have transmitted a frame, so we can wake the queue again */				if(netif_queue_stopped(dev))					netif_wake_queue(dev);			} else {				mask &= ~SM_FRAMETXDONE;			}		}				if( mask & SM_FRAMERX ) {			spin_lock_bh(&lp->sm_lock);			new_mask = prism_softmac_frame_rx(lp->sm_context, &frame);			spin_unlock_bh(&lp->sm_lock);						if( new_mask < 0 ) {				printk(KERN_WARNING "handle_sm_callback: sm_frame_rx returned error %d\n", new_mask);			} else {				mask = new_mask;			}						if( frame != NULL ) {				if( frame->flags & SM_FRAME_RXFAILED ) {					printk("RX failed\n");					lp->stats.rx_errors++;				} else {					lp->stats.rx_packets++;					lp->stats.rx_bytes += frame->length;				}				/* get the skb from the frame */				skb = frame_to_skb(dev, frame);				skb->dev = dev;								if(skb) {										if(unlikely(lp->sm_mode == SM_MODE_PROMISCUOUS))						sm_monitor_rx(dev, &skb);										/* set minimal skb parameters and deliver the network packet */					skb->protocol = eth_type_trans(skb, dev);					skb->ip_summed = CHECKSUM_NONE;										netif_rx(skb);				}							} else {

⌨️ 快捷键说明

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