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

📄 irlan_client.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/********************************************************************* * * Filename:      irlan_client.c * Version:       0.9 * Description:   IrDA LAN Access Protocol (IrLAN) Client * Status:        Experimental. * Author:        Dag Brattli <dagb@cs.uit.no> * Created at:    Sun Aug 31 20:14:37 1997 * Modified at:   Tue Dec 14 15:47:02 1999 * Modified by:   Dag Brattli <dagb@cs.uit.no> * Sources:       skeleton.c by Donald Becker <becker@CESDIS.gsfc.nasa.gov> *                slip.c by Laurence Culhane, <loz@holmes.demon.co.uk> *                          Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org> * *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, *     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. * *     Neither Dag Brattli nor University of Tromsø admit liability nor *     provide warranty for any of this software. This material is *     provided "AS-IS" and at no charge. * ********************************************************************/#include <linux/kernel.h>#include <linux/string.h>#include <linux/errno.h>#include <linux/init.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/if_arp.h>#include <linux/bitops.h>#include <net/arp.h>#include <asm/system.h>#include <asm/byteorder.h>#include <net/irda/irda.h>#include <net/irda/irttp.h>#include <net/irda/irlmp.h>#include <net/irda/irias_object.h>#include <net/irda/iriap.h>#include <net/irda/timer.h>#include <net/irda/irlan_common.h>#include <net/irda/irlan_event.h>#include <net/irda/irlan_eth.h>#include <net/irda/irlan_provider.h>#include <net/irda/irlan_client.h>#undef CONFIG_IRLAN_GRATUITOUS_ARPstatic void irlan_client_ctrl_disconnect_indication(void *instance, void *sap,						    LM_REASON reason,						    struct sk_buff *);static int irlan_client_ctrl_data_indication(void *instance, void *sap,					     struct sk_buff *skb);static void irlan_client_ctrl_connect_confirm(void *instance, void *sap,					      struct qos_info *qos,					      __u32 max_sdu_size,					      __u8 max_header_size,					      struct sk_buff *);static void irlan_check_response_param(struct irlan_cb *self, char *param,				       char *value, int val_len);static void irlan_client_open_ctrl_tsap(struct irlan_cb *self);static void irlan_client_kick_timer_expired(void *data){	struct irlan_cb *self = (struct irlan_cb *) data;	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );	IRDA_ASSERT(self != NULL, return;);	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);	/*	 * If we are in peer mode, the client may not have got the discovery	 * indication it needs to make progress. If the client is still in	 * IDLE state, we must kick it to, but only if the provider is not IDLE	 */	if ((self->provider.access_type == ACCESS_PEER) &&	    (self->client.state == IRLAN_IDLE) &&	    (self->provider.state != IRLAN_IDLE)) {		irlan_client_wakeup(self, self->saddr, self->daddr);	}}static void irlan_client_start_kick_timer(struct irlan_cb *self, int timeout){	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );	irda_start_timer(&self->client.kick_timer, timeout, (void *) self,			 irlan_client_kick_timer_expired);}/* * Function irlan_client_wakeup (self, saddr, daddr) * *    Wake up client * */void irlan_client_wakeup(struct irlan_cb *self, __u32 saddr, __u32 daddr){	IRDA_DEBUG(1, "%s()\n", __FUNCTION__ );	IRDA_ASSERT(self != NULL, return;);	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);	/*	 * Check if we are already awake, or if we are a provider in direct	 * mode (in that case we must leave the client idle	 */	if ((self->client.state != IRLAN_IDLE) ||	    (self->provider.access_type == ACCESS_DIRECT))	{			IRDA_DEBUG(0, "%s(), already awake!\n", __FUNCTION__ );			return;	}	/* Addresses may have changed! */	self->saddr = saddr;	self->daddr = daddr;	if (self->disconnect_reason == LM_USER_REQUEST) {			IRDA_DEBUG(0, "%s(), still stopped by user\n", __FUNCTION__ );			return;	}	/* Open TSAPs */	irlan_client_open_ctrl_tsap(self);	irlan_open_data_tsap(self);	irlan_do_client_event(self, IRLAN_DISCOVERY_INDICATION, NULL);	/* Start kick timer */	irlan_client_start_kick_timer(self, 2*HZ);}/* * Function irlan_discovery_indication (daddr) * *    Remote device with IrLAN server support discovered * */void irlan_client_discovery_indication(discinfo_t *discovery,				       DISCOVERY_MODE mode,				       void *priv){	struct irlan_cb *self;	__u32 saddr, daddr;	IRDA_DEBUG(1, "%s()\n", __FUNCTION__ );	IRDA_ASSERT(discovery != NULL, return;);	/*	 * I didn't check it, but I bet that IrLAN suffer from the same	 * deficiency as IrComm and doesn't handle two instances	 * simultaneously connecting to each other.	 * Same workaround, drop passive discoveries.	 * Jean II */	if(mode == DISCOVERY_PASSIVE)		return;	saddr = discovery->saddr;	daddr = discovery->daddr;	/* Find instance */	rcu_read_lock();	self = irlan_get_any();	if (self) {		IRDA_ASSERT(self->magic == IRLAN_MAGIC, goto out;);		IRDA_DEBUG(1, "%s(), Found instance (%08x)!\n", __FUNCTION__ ,		      daddr);		irlan_client_wakeup(self, saddr, daddr);	}IRDA_ASSERT_LABEL(out:)	rcu_read_unlock();}/* * Function irlan_client_data_indication (handle, skb) * *    This function gets the data that is received on the control channel * */static int irlan_client_ctrl_data_indication(void *instance, void *sap,					     struct sk_buff *skb){	struct irlan_cb *self;	IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );	self = (struct irlan_cb *) instance;	IRDA_ASSERT(self != NULL, return -1;);	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -1;);	IRDA_ASSERT(skb != NULL, return -1;);	irlan_do_client_event(self, IRLAN_DATA_INDICATION, skb);	/* Ready for a new command */	IRDA_DEBUG(2, "%s(), clearing tx_busy\n", __FUNCTION__ );	self->client.tx_busy = FALSE;	/* Check if we have some queued commands waiting to be sent */	irlan_run_ctrl_tx_queue(self);	return 0;}static void irlan_client_ctrl_disconnect_indication(void *instance, void *sap,						    LM_REASON reason,						    struct sk_buff *userdata){	struct irlan_cb *self;	struct tsap_cb *tsap;	struct sk_buff *skb;	IRDA_DEBUG(4, "%s(), reason=%d\n", __FUNCTION__ , reason);	self = (struct irlan_cb *) instance;	tsap = (struct tsap_cb *) sap;	IRDA_ASSERT(self != NULL, return;);	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);	IRDA_ASSERT(tsap != NULL, return;);	IRDA_ASSERT(tsap->magic == TTP_TSAP_MAGIC, return;);	IRDA_ASSERT(tsap == self->client.tsap_ctrl, return;);	/* Remove frames queued on the control channel */	while ((skb = skb_dequeue(&self->client.txq)) != NULL) {		dev_kfree_skb(skb);	}	self->client.tx_busy = FALSE;	irlan_do_client_event(self, IRLAN_LMP_DISCONNECT, NULL);}/* * Function irlan_client_open_tsaps (self) * *    Initialize callbacks and open IrTTP TSAPs * */static void irlan_client_open_ctrl_tsap(struct irlan_cb *self){	struct tsap_cb *tsap;	notify_t notify;	IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );	IRDA_ASSERT(self != NULL, return;);	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);	/* Check if already open */	if (self->client.tsap_ctrl)		return;	irda_notify_init(&notify);	/* Set up callbacks */	notify.data_indication       = irlan_client_ctrl_data_indication;	notify.connect_confirm       = irlan_client_ctrl_connect_confirm;	notify.disconnect_indication = irlan_client_ctrl_disconnect_indication;	notify.instance = self;	strlcpy(notify.name, "IrLAN ctrl (c)", sizeof(notify.name));	tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT, &notify);	if (!tsap) {		IRDA_DEBUG(2, "%s(), Got no tsap!\n", __FUNCTION__ );		return;	}	self->client.tsap_ctrl = tsap;}/* * Function irlan_client_connect_confirm (handle, skb) * *    Connection to peer IrLAN laye confirmed * */

⌨️ 快捷键说明

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