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

📄 at76c503.c

📁 这是atmel公司的无线网卡驱动, 基于linux的驱动源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		break;	case REASSOCIATING:		if (dev->retries-- >= 0)			reassoc_req(dev, dev->curr_bss, dev->new_bss);		else {			/* we disassociate from the curr_bss and			   scan again ... */			NEW_STATE(dev,DISASSOCIATING);			dev->retries = DISASSOC_RETRIES;			disassoc_req(dev, dev->curr_bss);		}		mod_timer(&dev->mgmt_timer, jiffies+HZ);		break;	case DISASSOCIATING:		if (dev->retries-- >= 0) {			disassoc_req(dev, dev->curr_bss);			mod_timer(&dev->mgmt_timer,jiffies+HZ);		} else {			/* we scan again ... */			NEW_STATE(dev,SCANNING);			defer_kevent(dev,KEVENT_SCAN);		}		break;	case INIT:		break;	default:		assert(0);	} /* switch (dev->istate) */}/* handle_mgmt_timeout *//* calc. the padding from txbuf->wlength (which excludes the USB TX header)    guess this is needed to compensate a flaw in the AT76C503A USB part ... */static inlineint calc_padding(int wlen){	/* add the USB TX header */	wlen += AT76C503_TX_HDRLEN;	wlen = wlen % 64;	if (wlen < 50)		return 50 - wlen;	if (wlen >=61)		return 64 + 50 - wlen;	return 0;}/* send a management frame on bulk-out.   txbuf->wlength must be set (in LE format !) */staticint send_mgmt_bulk(struct at76c503 *dev, struct at76c503_tx_buffer *txbuf){	unsigned long flags;	char obuf[3*64+1] __attribute__ ((unused));	int ret = 0;	int urb_status;	void *oldbuf = NULL;	netif_carrier_off(dev->netdev); /* disable running netdev watchdog */	netif_stop_queue(dev->netdev); /* stop tx data packets */	spin_lock_irqsave(&dev->mgmt_spinlock, flags);	if ((urb_status=dev->write_urb->status) == USB_ST_URB_PENDING) {		oldbuf=dev->next_mgmt_bulk; /* to kfree below */		dev->next_mgmt_bulk = txbuf;		txbuf = NULL;	}	spin_unlock_irqrestore(&dev->mgmt_spinlock, flags);	if (oldbuf) {		/* a data/mgmt tx is already pending in the URB -		   if this is no error in some situations we must		   implement a queue or silently modify the old msg */		err("%s: %s removed pending mgmt buffer %s",		    dev->netdev->name, __FUNCTION__,		    hex2str(obuf, (u8 *)dev->next_mgmt_bulk, 64,' '));		kfree(dev->next_mgmt_bulk);	}	if (txbuf) {		txbuf->tx_rate = 0;//		txbuf->padding = 0;		txbuf->padding = 		   cpu_to_le16(calc_padding(le16_to_cpu(txbuf->wlength)));		if (dev->next_mgmt_bulk) {			err("%s: %s URB status %d, but mgmt is pending",			    dev->netdev->name, __FUNCTION__, urb_status);		}		dbg(DBG_TX_MGMT, "%s: tx mgmt: wlen %d tx_rate %d pad %d %s",		    dev->netdev->name, le16_to_cpu(txbuf->wlength),		    txbuf->tx_rate, le16_to_cpu(txbuf->padding),		    hex2str(obuf,txbuf->packet,			    min((sizeof(obuf)-1)/2,				(size_t)le16_to_cpu(txbuf->wlength)),'\0'));		/* txbuf was not consumed above -> send mgmt msg immediately */		memcpy(dev->bulk_out_buffer, txbuf,		       le16_to_cpu(txbuf->wlength) + AT76C503_TX_HDRLEN);		FILL_BULK_URB(dev->write_urb, dev->udev,			      usb_sndbulkpipe(dev->udev, 					      dev->bulk_out_endpointAddr),			      dev->bulk_out_buffer,			      le16_to_cpu(txbuf->wlength) + 			      le16_to_cpu(txbuf->padding) +			      AT76C503_TX_HDRLEN,			      at76c503_write_bulk_callback, dev);		ret = usb_submit_urb(dev->write_urb);		if (ret) {			err("%s: %s error in tx submit urb: %d",			    dev->netdev->name, __FUNCTION__, ret);		}		kfree(txbuf);	} /* if (txbuf) */	return ret;} /* send_mgmt_bulk */staticint disassoc_req(struct at76c503 *dev, struct bss_info *bss){	struct at76c503_tx_buffer *tx_buffer;	struct ieee802_11_mgmt *mgmt;	struct ieee802_11_disassoc_frame *req;	assert(bss != NULL);	if (bss == NULL)		return -EFAULT;	tx_buffer = kmalloc(DISASSOC_FRAME_SIZE + MAX_PADDING_SIZE,			    GFP_ATOMIC);	if (!tx_buffer)		return -ENOMEM;	mgmt = (struct ieee802_11_mgmt *)&(tx_buffer->packet);	req  = (struct ieee802_11_disassoc_frame *)&(mgmt->data);	/* make wireless header */	mgmt->frame_ctl = cpu_to_le16(IEEE802_11_FTYPE_MGMT|IEEE802_11_STYPE_AUTH);	mgmt->duration_id = cpu_to_le16(0x8000);	memcpy(mgmt->addr1, bss->bssid, ETH_ALEN);	memcpy(mgmt->addr2, dev->netdev->dev_addr, ETH_ALEN);	memcpy(mgmt->addr3, bss->bssid, ETH_ALEN);	mgmt->seq_ctl = cpu_to_le16(0);	req->reason = 0;	/* init. at76c503 tx header */	tx_buffer->wlength = cpu_to_le16(DISASSOC_FRAME_SIZE -		AT76C503_TX_HDRLEN);		dbg(DBG_TX_MGMT, "%s: DisAssocReq bssid %s",	    dev->netdev->name, mac2str(mgmt->addr3));	/* either send immediately (if no data tx is pending	   or put it in pending list */	return send_mgmt_bulk(dev, tx_buffer); } /* disassoc_req *//* challenge is the challenge string (in TLV format)    we got with seq_nr 2 for shared secret authentication only and   send in seq_nr 3 WEP encrypted to prove we have the correct WEP key;   otherwise it is NULL */staticint auth_req(struct at76c503 *dev, struct bss_info *bss, int seq_nr, u8 *challenge){	struct at76c503_tx_buffer *tx_buffer;	struct ieee802_11_mgmt *mgmt;	struct ieee802_11_auth_frame *req;		int buf_len = (seq_nr != 3 ? AUTH_FRAME_SIZE : 		       AUTH_FRAME_SIZE + 1 + 1 + challenge[1]);	assert(bss != NULL);	assert(seq_nr != 3 || challenge != NULL);		tx_buffer = kmalloc(buf_len + MAX_PADDING_SIZE, GFP_ATOMIC);	if (!tx_buffer)		return -ENOMEM;	mgmt = (struct ieee802_11_mgmt *)&(tx_buffer->packet);	req  = (struct ieee802_11_auth_frame *)&(mgmt->data);	/* make wireless header */	/* first auth msg is not encrypted, only the second (seq_nr == 3) */	mgmt->frame_ctl = cpu_to_le16(IEEE802_11_FTYPE_MGMT | IEEE802_11_STYPE_AUTH |		(seq_nr == 3 ? IEEE802_11_FCTL_WEP : 0));	mgmt->duration_id = cpu_to_le16(0x8000);	memcpy(mgmt->addr1, bss->bssid, ETH_ALEN);	memcpy(mgmt->addr2, dev->netdev->dev_addr, ETH_ALEN);	memcpy(mgmt->addr3, bss->bssid, ETH_ALEN);	mgmt->seq_ctl = cpu_to_le16(0);	req->algorithm = cpu_to_le16(dev->auth_mode);	req->seq_nr = cpu_to_le16(seq_nr);	req->status = cpu_to_le16(0);	if (seq_nr == 3)		memcpy(req->challenge, challenge, 1+1+challenge[1]);	/* init. at76c503 tx header */	tx_buffer->wlength = cpu_to_le16(buf_len - AT76C503_TX_HDRLEN);		dbg(DBG_TX_MGMT, "%s: AuthReq bssid %s alg %d seq_nr %d",	    dev->netdev->name, mac2str(mgmt->addr3),	    le16_to_cpu(req->algorithm), le16_to_cpu(req->seq_nr));	if (seq_nr == 3) {		char obuf[18*3] __attribute__ ((unused));		dbg(DBG_TX_MGMT, "%s: AuthReq challenge: %s ...",		    dev->netdev->name,		    hex2str(obuf, req->challenge, sizeof(obuf)/3,' '));	}	/* either send immediately (if no data tx is pending	   or put it in pending list */	return send_mgmt_bulk(dev, tx_buffer); } /* auth_req */staticint assoc_req(struct at76c503 *dev, struct bss_info *bss){	struct at76c503_tx_buffer *tx_buffer;	struct ieee802_11_mgmt *mgmt;	struct ieee802_11_assoc_req *req;	u8 *tlv;	assert(bss != NULL);	tx_buffer = kmalloc(ASSOCREQ_MAX_SIZE + MAX_PADDING_SIZE,			    GFP_ATOMIC);	if (!tx_buffer)		return -ENOMEM;	mgmt = (struct ieee802_11_mgmt *)&(tx_buffer->packet);	req  = (struct ieee802_11_assoc_req *)&(mgmt->data);	tlv = req->data;	/* make wireless header */	mgmt->frame_ctl = cpu_to_le16(IEEE802_11_FTYPE_MGMT|IEEE802_11_STYPE_ASSOC_REQ);	mgmt->duration_id = cpu_to_le16(0x8000);	memcpy(mgmt->addr1, bss->bssid, ETH_ALEN);	memcpy(mgmt->addr2, dev->netdev->dev_addr, ETH_ALEN);	memcpy(mgmt->addr3, bss->bssid, ETH_ALEN);	mgmt->seq_ctl = cpu_to_le16(0);	/* we must set the Privacy bit in the capabilites to assure an	   Agere-based AP with optional WEP transmits encrypted frames	   to us.  AP only set the Privacy bit in their capabilities	   if WEP is mandatory in the BSS! */	req->capability = cpu_to_le16(bss->capa | 				      (dev->wep_enabled ? IEEE802_11_CAPA_PRIVACY : 0) |				      (dev->preamble_type == PREAMBLE_TYPE_SHORT ?				       IEEE802_11_CAPA_SHORT_PREAMBLE : 0));	req->listen_interval = cpu_to_le16(2 * bss->beacon_interval);		/* write TLV data elements */	*tlv++ = IE_ID_SSID;	*tlv++ = bss->ssid_len;	memcpy(tlv, bss->ssid, bss->ssid_len);	tlv += bss->ssid_len;	*tlv++ = IE_ID_SUPPORTED_RATES;	*tlv++ = sizeof(hw_rates);	memcpy(tlv, hw_rates, sizeof(hw_rates));	tlv += sizeof(hw_rates); /* tlv points behind the supp_rates field */	/* init. at76c503 tx header */	tx_buffer->wlength = cpu_to_le16(tlv-(u8 *)mgmt);		{		/* output buffer for ssid and rates */		char ossid[IW_ESSID_MAX_SIZE+1] __attribute__ ((unused));		char orates[4*2+1] __attribute__ ((unused));		int len;		tlv = req->data;		len = min(sizeof(ossid)-1,(size_t)*(tlv+1));		memcpy(ossid, tlv+2, len);		ossid[len] = '\0';		tlv += (1 + 1 + *(tlv+1)); /* points to IE of rates now */		dbg(DBG_TX_MGMT, "%s: AssocReq bssid %s capa x%04x ssid %s rates %s",		    dev->netdev->name, mac2str(mgmt->addr3),		    le16_to_cpu(req->capability), ossid,		    hex2str(orates,tlv+2,min((sizeof(orates)-1)/2,(size_t)*(tlv+1)),			    '\0'));	}	/* either send immediately (if no data tx is pending	   or put it in pending list */	return send_mgmt_bulk(dev, tx_buffer); } /* assoc_req *//* we are currently associated to curr_bss and   want to reassoc to new_bss */staticint reassoc_req(struct at76c503 *dev, struct bss_info *curr_bss,		struct bss_info *new_bss){	struct at76c503_tx_buffer *tx_buffer;	struct ieee802_11_mgmt *mgmt;	struct ieee802_11_reassoc_req *req;		u8 *tlv;	assert(curr_bss != NULL);	assert(new_bss != NULL);	if (curr_bss == NULL || new_bss == NULL)		return -EFAULT;	tx_buffer = kmalloc(REASSOCREQ_MAX_SIZE + MAX_PADDING_SIZE,			    GFP_ATOMIC);	if (!tx_buffer)		return -ENOMEM;	mgmt = (struct ieee802_11_mgmt *)&(tx_buffer->packet);	req  = (struct ieee802_11_reassoc_req *)&(mgmt->data);	tlv = req->data;	/* make wireless header */	/* jal: encrypt this packet if wep_enabled is TRUE ??? */	mgmt->frame_ctl = cpu_to_le16(IEEE802_11_FTYPE_MGMT|IEEE802_11_STYPE_REASSOC_REQ);	mgmt->duration_id = cpu_to_le16(0x8000);	memcpy(mgmt->addr1, new_bss->bssid, ETH_ALEN);	memcpy(mgmt->addr2, dev->netdev->dev_addr, ETH_ALEN);	memcpy(mgmt->addr3, new_bss->bssid, ETH_ALEN);	mgmt->seq_ctl = cpu_to_le16(0);	/* we must set the Privacy bit in the capabilites to assure an	   Agere-based AP with optional WEP transmits encrypted frames	   to us.  AP only set the Privacy bit in their capabilities	   if WEP is mandatory in the BSS! */	req->capability = cpu_to_le16(new_bss->capa | 				      (dev->wep_enabled ? IEEE802_11_CAPA_PRIVACY : 0) |				      (dev->preamble_type == PREAMBLE_TYPE_SHORT ?				       IEEE802_11_CAPA_SHORT_PREAMBLE : 0));	req->listen_interval = cpu_to_le16(2 * new_bss->beacon_interval);		memcpy(req->curr_ap, curr_bss->bssid, ETH_ALEN);	/* write TLV data elements */	*tlv++ = IE_ID_SSID;	*tlv++ = new_bss->ssid_len;	memcpy(tlv,new_bss->ssid, new_bss->ssid_len);	tlv += new_bss->ssid_len;	*tlv++ = IE_ID_SUPPORTED_RATES;	*tlv++ = sizeof(hw_rates);	memcpy(tlv, hw_rates, sizeof(hw_rates));	tlv += sizeof(hw_rates); /* tlv points behind the supp_rates field */	/* init. at76c503 tx header */	tx_buffer->wlength = cpu_to_le16(tlv-(u8 *)mgmt);		{		/* output buffer for ssid and rates */		char ossid[IW_ESSID_MAX_SIZE+1] __attribute__ ((unused));		char orates[4*2+1] __attribute__ ((unused));		char ocurr[6*3+1] __attribute__ ((unused));		tlv = req->data;		memcpy(ossid, tlv+2, min(sizeof(ossid),(size_t)*(tlv+1)));		ossid[sizeof(ossid)-1] = '\0';		tlv += (1 + 1 + *(tlv+1)); /* points to IE of rates now */		dbg(DBG_TX_MGMT, "%s: ReAssocReq curr %s new %s capa x%04x ssid %s rates %s",		    dev->netdev->name,		    hex2str(ocurr, req->curr_ap, ETH_ALEN, ':'),		    mac2str(mgmt->addr3), le16_to_cpu(req->capability), ossid,		    hex2str(orates,tlv+2,min((sizeof(orates)-1)/2,(size_t)*(tlv+1)),			    '\0'));	}	/* either send immediately (if no data tx is pending	   or put it in pending list */	return send_mgmt_bulk(dev, tx_buffer); } /* reassoc_req *//* shamelessly copied from usbnet.c (oku) */static void defer_kevent (struct at76c503 *dev, int flag){	set_bit (flag, &dev->kevent_flags);	if (!schedule_task (&dev->kevent))		dbg(DBG_KEVENT, "%s: kevent %d may have been dropped",		     dev->netdev->name, flag);	else		dbg(DBG_KEVENT, "%s: kevent %d scheduled",		    dev->netdev->name, flag);}static voidkevent(void *data){	struct at76c503 *dev = data;	int ret;	unsigned long flags;	/* on errors, bits aren't cleared, but no reschedule	   is done. So work will be done next time something	   else has to be done. This is ugly. TODO! (oku) */	dbg(DBG_KEVENT, "%s: kevent entry flags=x%x", dev->netdev->name,	    dev->kevent_flags);	down(&dev->sem);	if(test_bit(KEVENT_CTRL_HALT, &dev->kevent_flags)){		/* this never worked... but it seems		   that it's rarely necessary, if at all (oku) */		ret = usb_clear_halt(dev->udev,				     usb_sndctrlpipe (dev->udev, 0));		if(ret < 0)			err("usb_clear_halt() failed: %d", ret);		else{			clear_bit(KEVENT_CTRL_HALT, &dev->kevent_flags);			info("usb_clear_halt() succesful");		}	}	if(test_bit(KEVENT_NEW_BSS, &dev->kevent_flags)){		struct net_device *netdev = dev->netdev;		struct mib_mac_mgmt *mac_mgmt = kmalloc(sizeof(struct mib_mac_mgmt), GFP_KERNEL);		struct set_mib_buffer mib_buf;		ret = get_mib(dev->udev, MIB_MAC_MGMT, (u8*)mac_mgmt,			      sizeof(struct mib_mac_mgmt));		if(ret < 0){			err("%s: get_mib failed: %d", netdev->name, ret);			goto new_bss_clean;		}		//    usb_debug_data(__FUNCTION__, (unsigned char *)mac_mgmt, sizeof(struct mib_mac_mgmt));		dbg(DBG_PROGRESS, "ibss_change = 0x%2x", mac_mgmt->ibss_change);

⌨️ 快捷键说明

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