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

📄 irlap.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/********************************************************************* *                 * Filename:      irlap.c * Version:       1.0 * Description:   IrLAP implementation for Linux * Status:        Stable * Author:        Dag Brattli <dagb@cs.uit.no> * Created at:    Mon Aug  4 20:40:53 1997 * Modified at:   Tue Dec 14 09:26:44 1999 * Modified by:   Dag Brattli <dagb@cs.uit.no> *  *     Copyright (c) 1998-1999 Dag Brattli, All Rights Reserved. *      *     This program is free software; you can redistribute it and/or  *     modify it under the terms of the GNU General Public License as  *     published by the Free Software Foundation; either version 2 of  *     the License, or (at your option) any later version. *  *     This program is distributed in the hope that it will be useful, *     but WITHOUT ANY WARRANTY; without even the implied warranty of *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *     GNU General Public License for more details. *  *     You should have received a copy of the GNU General Public License  *     along with this program; if not, write to the Free Software  *     Foundation, Inc., 59 Temple Place, Suite 330, Boston,  *     MA 02111-1307 USA *      ********************************************************************/#include <linux/config.h>#include <linux/malloc.h>#include <linux/string.h>#include <linux/skbuff.h>#include <linux/delay.h>#include <linux/proc_fs.h>#include <linux/init.h>#include <linux/random.h>#include <net/irda/irda.h>#include <net/irda/irda_device.h>#include <net/irda/irqueue.h>#include <net/irda/irlmp.h>#include <net/irda/irlmp_frame.h>#include <net/irda/irlap_frame.h>#include <net/irda/irlap.h>#include <net/irda/timer.h>#include <net/irda/qos.h>#include <net/irda/irlap_comp.h>hashbin_t *irlap = NULL;int sysctl_slot_timeout = SLOT_TIMEOUT * 1000 / HZ;static void __irlap_close(struct irlap_cb *self);static char *lap_reasons[] = {	"ERROR, NOT USED",	"LAP_DISC_INDICATION",	"LAP_NO_RESPONSE",	"LAP_RESET_INDICATION",	"LAP_FOUND_NONE",	"LAP_MEDIA_BUSY",	"LAP_PRIMARY_CONFLICT",	"ERROR, NOT USED",};#ifdef CONFIG_PROC_FSint irlap_proc_read(char *, char **, off_t, int);#endif /* CONFIG_PROC_FS */int __init irlap_init(void){	/* Allocate master array */	irlap = hashbin_new(HB_LOCAL);	if (irlap == NULL) {	        ERROR(__FUNCTION__ "(), can't allocate irlap hashbin!\n");		return -ENOMEM;	}#ifdef CONFIG_IRDA_COMPRESSION	irlap_compressors = hashbin_new(HB_LOCAL);	if (irlap_compressors == NULL) {		WARNING(__FUNCTION__ 			"(), can't allocate compressors hashbin!\n");		return -ENOMEM;	}#endif	return 0;}void irlap_cleanup(void){	ASSERT(irlap != NULL, return;);	hashbin_delete(irlap, (FREE_FUNC) __irlap_close);#ifdef CONFIG_IRDA_COMPRESSION	hashbin_delete(irlap_compressors, (FREE_FUNC) kfree);#endif}/* * Function irlap_open (driver) * *    Initialize IrLAP layer * */struct irlap_cb *irlap_open(struct net_device *dev, struct qos_info *qos){	struct irlap_cb *self;	IRDA_DEBUG(4, __FUNCTION__ "()\n");		/* Initialize the irlap structure. */	self = kmalloc(sizeof(struct irlap_cb), GFP_KERNEL);	if (self == NULL)		return NULL;		memset(self, 0, sizeof(struct irlap_cb));	self->magic = LAP_MAGIC;	/* Make a binding between the layers */	self->netdev = dev;	self->qos_dev = qos;	/* FIXME: should we get our own field? */	dev->atalk_ptr = self;	irlap_next_state(self, LAP_OFFLINE);	/* Initialize transmit queue */	skb_queue_head_init(&self->txq);	skb_queue_head_init(&self->txq_ultra);	skb_queue_head_init(&self->wx_list);	/* My unique IrLAP device address! */	get_random_bytes(&self->saddr, sizeof(self->saddr));	memcpy(dev->dev_addr, &self->saddr, 4);	init_timer(&self->slot_timer);	init_timer(&self->query_timer);	init_timer(&self->discovery_timer);	init_timer(&self->final_timer);			init_timer(&self->poll_timer);	init_timer(&self->wd_timer);	init_timer(&self->backoff_timer);	init_timer(&self->media_busy_timer);		irlap_apply_default_connection_parameters(self);	self->N3 = 3; /* # connections attemts to try before giving up */		irlap_next_state(self, LAP_NDM);	hashbin_insert(irlap, (irda_queue_t *) self, self->saddr, NULL);	irlmp_register_link(self, self->saddr, &self->notify);		return self;}/* * Function __irlap_close (self) * *    Remove IrLAP and all allocated memory. Stop any pending timers. * */static void __irlap_close(struct irlap_cb *self){	ASSERT(self != NULL, return;);	ASSERT(self->magic == LAP_MAGIC, return;);	/* Stop timers */	del_timer(&self->slot_timer);	del_timer(&self->query_timer);	del_timer(&self->discovery_timer);	del_timer(&self->final_timer);			del_timer(&self->poll_timer);	del_timer(&self->wd_timer);	del_timer(&self->backoff_timer);	del_timer(&self->media_busy_timer);	irlap_flush_all_queues(self);       	self->magic = 0;		kfree(self);}/* * Function irlap_close (self) * *    Remove IrLAP instance * */void irlap_close(struct irlap_cb *self) {	struct irlap_cb *lap;	IRDA_DEBUG(4, __FUNCTION__ "()\n");		ASSERT(self != NULL, return;);	ASSERT(self->magic == LAP_MAGIC, return;);	irlap_disconnect_indication(self, LAP_DISC_INDICATION);	irlmp_unregister_link(self->saddr);	self->notify.instance = NULL;	/* Be sure that we manage to remove ourself from the hash */	lap = hashbin_remove(irlap, self->saddr, NULL);	if (!lap) {		IRDA_DEBUG(1, __FUNCTION__ "(), Didn't find myself!\n");		return;	}	__irlap_close(lap);}/* * Function irlap_connect_indication (self, skb) * *    Another device is attempting to make a connection * */void irlap_connect_indication(struct irlap_cb *self, struct sk_buff *skb) {	IRDA_DEBUG(4, __FUNCTION__ "()\n");	ASSERT(self != NULL, return;);	ASSERT(self->magic == LAP_MAGIC, return;);	irlap_init_qos_capabilities(self, NULL); /* No user QoS! */	skb_get(skb); /*LEVEL4*/	irlmp_link_connect_indication(self->notify.instance, self->saddr, 				      self->daddr, &self->qos_tx, skb);}/* * Function irlap_connect_response (self, skb) * *    Service user has accepted incomming connection * */void irlap_connect_response(struct irlap_cb *self, struct sk_buff *skb) {	IRDA_DEBUG(4, __FUNCTION__ "()\n");		irlap_do_event(self, CONNECT_RESPONSE, skb, NULL);	kfree_skb(skb);}/* * Function irlap_connect_request (self, daddr, qos_user, sniff) * *    Request connection with another device, sniffing is not implemented  *    yet. * */void irlap_connect_request(struct irlap_cb *self, __u32 daddr, 			   struct qos_info *qos_user, int sniff) {	IRDA_DEBUG(3, __FUNCTION__ "(), daddr=0x%08x\n", daddr);	ASSERT(self != NULL, return;);	ASSERT(self->magic == LAP_MAGIC, return;); 	self->daddr = daddr;		/*	 *  If the service user specifies QoS values for this connection, 	 *  then use them	 */	irlap_init_qos_capabilities(self, qos_user);		if ((self->state == LAP_NDM) && !self->media_busy)		irlap_do_event(self, CONNECT_REQUEST, NULL, NULL);	else		self->connect_pending = TRUE;}/* * Function irlap_connect_confirm (self, skb) * *    Connection request has been accepted * */void irlap_connect_confirm(struct irlap_cb *self, struct sk_buff *skb){	IRDA_DEBUG(4, __FUNCTION__ "()\n");	ASSERT(self != NULL, return;);	ASSERT(self->magic == LAP_MAGIC, return;);	skb_get(skb); /*LEVEL4*/	irlmp_link_connect_confirm(self->notify.instance, &self->qos_tx, skb);}/* * Function irlap_data_indication (self, skb) * *    Received data frames from IR-port, so we just pass them up to  *    IrLMP for further processing * */void irlap_data_indication(struct irlap_cb *self, struct sk_buff *skb,			   int unreliable) {	/* Hide LAP header from IrLMP layer */	skb_pull(skb, LAP_ADDR_HEADER+LAP_CTRL_HEADER);#ifdef CONFIG_IRDA_COMPRESSION	if (self->qos_tx.compression.value) {		skb_get(skb); /*LEVEL4*/		skb = irlap_decompress_frame(self, skb);		if (!skb) {			IRDA_DEBUG(1, __FUNCTION__ "(), Decompress error!\n");			return;		}	}#endif	skb_get(skb); /*LEVEL4*/	irlmp_link_data_indication(self->notify.instance, skb, unreliable);}/* * Function irlap_data_request (self, skb) * *    Queue data for transmission, must wait until XMIT state * */void irlap_data_request(struct irlap_cb *self, struct sk_buff *skb, 			int unreliable){	ASSERT(self != NULL, return;);	ASSERT(self->magic == LAP_MAGIC, return;);	IRDA_DEBUG(3, __FUNCTION__ "()\n");#ifdef CONFIG_IRDA_COMPRESSION	if (self->qos_tx.compression.value) {		skb = irlap_compress_frame(self, skb);		if (!skb) {			IRDA_DEBUG(1, __FUNCTION__ "(), Compress error!\n");			return;		}	}#endif	ASSERT(skb_headroom(skb) >= (LAP_ADDR_HEADER+LAP_CTRL_HEADER), 	       return;);	skb_push(skb, LAP_ADDR_HEADER+LAP_CTRL_HEADER);	/*  	 *  Must set frame format now so that the rest of the code knows 	 *  if its dealing with an I or an UI frame	 */	if (unreliable)		skb->data[1] = UI_FRAME;	else		skb->data[1] = I_FRAME;	/* 	 *  Send event if this frame only if we are in the right state 	 *  FIXME: udata should be sent first! (skb_queue_head?)	 */  	if ((self->state == LAP_XMIT_P) || (self->state == LAP_XMIT_S)) {		/*		 *  Check if the transmit queue contains some unsent frames,		 *  and if so, make sure they are sent first		 */		if (!skb_queue_empty(&self->txq)) {			skb_queue_tail(&self->txq, skb);			skb = skb_dequeue(&self->txq);						ASSERT(skb != NULL, return;);		}		irlap_do_event(self, SEND_I_CMD, skb, NULL);		kfree_skb(skb);	} else		skb_queue_tail(&self->txq, skb);}/* * Function irlap_unitdata_request (self, skb) * *    Send Ultra data. This is data that must be sent outside any connection * */#ifdef CONFIG_IRDA_ULTRAvoid irlap_unitdata_request(struct irlap_cb *self, struct sk_buff *skb){	ASSERT(self != NULL, return;);	ASSERT(self->magic == LAP_MAGIC, return;);	IRDA_DEBUG(3, __FUNCTION__ "()\n");	ASSERT(skb_headroom(skb) >= (LAP_ADDR_HEADER+LAP_CTRL_HEADER), 	       return;);	skb_push(skb, LAP_ADDR_HEADER+LAP_CTRL_HEADER);	skb->data[0] = CBROADCAST;	skb->data[1] = UI_FRAME;	skb_queue_tail(&self->txq_ultra, skb);	irlap_do_event(self, SEND_UI_FRAME, NULL, NULL);}#endif /*CONFIG_IRDA_ULTRA *//* * Function irlap_udata_indication (self, skb) * *    Receive Ultra data. This is data that is received outside any connection * */

⌨️ 快捷键说明

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