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

📄 af_irda.c

📁 sparc硬件平台上的红外协议
💻 C
📖 第 1 页 / 共 2 页
字号:
/*********************************************************************** Filename:      af_irda.c* Version:       0.9* Description:   IrDA sockets implementation* Status:        Stable* Author:        Dag Brattli <dagb@cs.uit.no>* Created at:    Sun May 31 10:12:43 1998* Modified at:   Sat Dec 25 21:10:23 1999* Modified by:   Dag Brattli <dag@brattli.net>* Sources:       af_netroom.c, af_ax25.c, af_rose.c, af_x25.c etc.**     Copyright (c) 1999 Dag Brattli <dagb@cs.uit.no>*     Copyright (c) 1999-2003 Jean Tourrilhes <jt@hpl.hp.com>*     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 ofAAA*     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**     Linux-IrDA now supports four different types of IrDA sockets:**     o SOCK_STREAM:    TinyTP connections with SAR disabled. The*                       max SDU size is 0 for conn. of this type*     o SOCK_SEQPACKET: TinyTP connections with SAR enabled. TTP may*                       fragment the messages, but will preserve*                       the message boundaries*     o SOCK_DGRAM:     IRDAPROTO_UNITDATA: TinyTP connections with Unitdata*                       (unreliable) transfers*                       IRDAPROTO_ULTRA: Connectionless and unreliable data*********************************************************************/#include "types.h"#include "irda.h"#include "af_irda.h"#include <sys/time.h>#include <errno.h>#include "irlap.h"#ifdef EMMI_SPARC#include <fsu_pthread.h>#else#include <pthread.h>#endif#include "../../public/pub_emmi.h"#define IRDA_MAX_HEADER (TTP_MAX_HEADER)//	extern pthread_cond_t irda_discovery_cond;extern  pthread_mutex_t irda_status_mutex;extern pthread_cond_t irda_status_cond;struct irda_cb* irda_self = NULL;static pthread_mutex_t obex_rec_mutex;static pthread_cond_t obex_rec_cond;int iriap_connect( struct addr_irda *addr);int irda_ttp_connect(struct addr_irda *addr);int irda_create(void);int irda_getopt( int optname,void *optval, int  *len);static int irda_accept();/** Function irda_data_indication (instance, sap, skb)**    Received some data from TinyTP. Just queue it on the receive queue**/static int irda_data_indication(void *instance, void *sap, struct sk_buff *skb){	struct irda_cb *self;	IRDA_DEBUG(4, "%s()\n", __FUNCTION__);		self = instance;	skb_queue_head(&self->sk_receive_queue,skb);		pthread_mutex_lock(&obex_rec_mutex);	pthread_cond_signal(&obex_rec_cond);	pthread_mutex_unlock(&obex_rec_mutex);		return 0;}/** Function irda_disconnect_indication (instance, sap, reason, skb)**    Connection has been closed. Check reason to find out why**/static void irda_disconnect_indication(void *instance, void *sap,									   LM_REASON reason, struct sk_buff *skb){	struct irda_cb *self;		self = instance;		IRDA_DEBUG(2, "%s(%p)\n", __FUNCTION__, self);		/* Don't care about it, but let's not leak it */	if(skb)		dev_kfree_skb(skb);			if (self == NULL) {		IRDA_DEBUG(0, "%s(%p) : BUG : self is NULL\n",			__FUNCTION__, self);		return;	}	/* Close our TSAP.	* If we leave it open, IrLMP put it back into the list of	* unconnected LSAPs. The problem is that any incoming request	* can then be matched to this socket (and it will be, because	* it is at the head of the list). This would prevent any	* listening socket waiting on the same TSAP to get those	* requests. Some apps forget to close sockets, or hang to it	* a bit too long, so we may stay in this dead state long	* enough to be noticed...	* Note : all socket function do check sk->sk_state, so we are	* safe...	* Jean II	*/	if (self->tsap) {		irttp_close_tsap(self->tsap);		self->tsap = NULL;			}}/** Function irda_connect_confirm (instance, sap, qos, max_sdu_size, skb)**    Connections has been confirmed by the remote device**/static void irda_connect_confirm(void *instance, void *sap,								 struct qos_info *qos,								 __u32 max_sdu_size, __u8 max_header_size,								 struct sk_buff *skb){	struct irda_cb *self;		self = instance;	IRDA_DEBUG(1, "%s(%p)\n", __FUNCTION__, self);		if (self == NULL) {		dev_kfree_skb(skb);		return;	}		dev_kfree_skb(skb);		/* How much header space do we need to reserve */	self->max_header_size = max_header_size;		/* IrTTP max SDU size in transmit direction */	self->max_sdu_size_tx = max_sdu_size;		/* Find out what the largest chunk of data that we can transmit is */		if (max_sdu_size != 0) {		IRDA_ERROR("%s: max_sdu_size must be 0\n",			__FUNCTION__);		return;	}	self->max_data_size = irttp_get_max_seg_size(self->tsap);	memcpy(&self->qos_tx, qos, sizeof(struct qos_info));}/** Function irda_connect_indication(instance, sap, qos, max_sdu_size, userdata)**    Incoming connection**/static void irda_connect_indication(void *instance, void *sap,									struct qos_info *qos, __u32 max_sdu_size,									__u8 max_header_size, struct sk_buff *skb){	struct irda_cb *self;		self = instance;		IRDA_DEBUG(1, "%s(%p)\n", __FUNCTION__, self);		/* How much header space do we need to reserve */	self->max_header_size = max_header_size;		/* IrTTP max SDU size in transmit direction */	self->max_sdu_size_tx = max_sdu_size;		/* Find out what the largest chunk of data that we can transmit is */		if (max_sdu_size != 0) {		IRDA_ERROR("%s: max_sdu_size must be 0\n",			__FUNCTION__);		kfree_skb(skb);		return;	}	self->max_data_size = irttp_get_max_seg_size(self->tsap);		memcpy(&self->qos_tx, qos, sizeof(struct qos_info));	irda_accept();}/** Function irda_connect_response (handle)**    Accept incoming connection**/static void irda_connect_response(void){	struct sk_buff *skb;	struct irda_cb* self = irda_self;	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);		skb = skb_alloc(TTP_MAX_HEADER + TTP_SAR_HEADER);	if (skb == NULL) {		IRDA_ERROR("%s() Unable to allocate sk_buff!\n",			__FUNCTION__);		return;	}		/* Reserve space for MUX_CONTROL and LAP header */	skb_reserve(skb, IRDA_MAX_HEADER);		irttp_connect_response(self->tsap, self->max_sdu_size_rx, skb);}/** Function irda_flow_indication (instance, sap, flow)**    Used by TinyTP to tell us if it can accept more data or not**/static void irda_flow_indication(void *instance, void *sap, LOCAL_FLOW flow){	//struct irda_cb *self;	//This  function do not  to achieve for the time	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);}/** Function irda_getvalue_confirm (obj_id, value, priv)**    Got answer from remote LM-IAS, just pass object to requester...** Note : duplicate from above, but we need our own version that* doesn't touch the dtsap_sel and save the full value structure...*/static void irda_getvalue_confirm(int result, __u16 obj_id,								  struct ias_value *value, void *priv){	struct irda_cb *self;		self = (struct irda_cb *) priv;	if (!self) {		IRDA_WARNING("%s: lost myself!\n", __FUNCTION__);		return;	}		IRDA_DEBUG(2, "%s(%p)\n", __FUNCTION__, self);		/* We probably don't need to make any more queries */	iriap_close(self->iriap);	self->iriap = NULL;		/* Check if request succeeded */	if (result != IAS_SUCCESS) {		IRDA_DEBUG(1, "%s(), IAS query failed! (%d)\n", __FUNCTION__, result);				self->errorno = result;	/* We really need it later */				return;	}		/* Pass the object to the caller (so the caller must delete it) */	self->ias_result = value;	self->errorno = 0;	switch (self->ias_result->type) {	case IAS_INTEGER:		IRDA_DEBUG(1, "%s() int=%d\n",			__FUNCTION__, self->ias_result->t.integer);				if (self->ias_result->t.integer != -1)			self->dtsap_sel = self->ias_result->t.integer;		else			self->dtsap_sel = 0;		break;	default:		self->dtsap_sel = 0;		IRDA_DEBUG(0, "%s(), bad type!\n", __FUNCTION__);		break;	}	if (self->ias_result)		irias_delete_value(self->ias_result);		return;	/* Wake up any processes waiting for result */	//wake_up_interruptible(&self->query_wait);}/** Function irda_open_tsap (self)**    Open local Transport Service Access Point (TSAP)**/static int irda_open_tsap(struct irda_cb *self, __u8 tsap_sel, char *name){	notify_t notify;		if (self->tsap) {		IRDA_WARNING("%s: busy!\n", __FUNCTION__);		return -EBUSY;	}		/* Initialize callbacks to be used by the IrDA stack */	irda_notify_init(&notify);	notify.connect_confirm       = irda_connect_confirm;	notify.connect_indication    = irda_connect_indication;	notify.disconnect_indication = irda_disconnect_indication;	notify.data_indication       = irda_data_indication;	notify.flow_indication       = irda_flow_indication;	notify.instance = self;	strncpy(notify.name, name, NOTIFY_MAX_NAME);		self->tsap = irttp_open_tsap(tsap_sel, DEFAULT_INITIAL_CREDIT,		&notify);	if (self->tsap == NULL) {		IRDA_DEBUG(0, "%s(), Unable to allocate TSAP!\n",			__FUNCTION__);		return -ENOMEM;	}	/* Remember which TSAP selector we actually got */	self->stsap_sel = self->tsap->stsap_sel;		return 0;}/** Function irda_find_lsap_sel (self, name)**    Try to lookup LSAP selector in remote LM-IAS** Basically, we start a IAP query, and then go to sleep. When the query* return, irda_getvalue_confirm will wake us up, and we can examine the* result of the query...* Note that in some case, the query fail even before we go to sleep,* creating some races...*/static int irda_find_lsap_sel(struct irda_cb *self, char *name){	IRDA_DEBUG(1, "%s(%p, %s)\n", __FUNCTION__, self, name);		if (self->iriap) {		IRDA_WARNING("%s(): busy with a previous query\n",			__FUNCTION__);		return -EBUSY;	}		self->iriap = iriap_open(LSAP_ANY, IAS_CLIENT, self,		irda_getvalue_confirm);	if(self->iriap == NULL)		return -ENOMEM;		/* Treat unexpected wakeup as disconnect */	self->errorno = -EHOSTUNREACH;		/* Query remote LM-IAS */	iriap_getvaluebyclass_request(self->iriap, self->saddr, self->daddr,		name, "IrDA:TinyTP:LsapSel");			return 0;}/** Function irda_bind (sock, uaddr, addr_len)**    Used by servers to register their well known TSAP**/int irda_bind( struct addr_irda* addr ){		struct irda_cb *self =NULL;	self = irda_self;	int err;		IRDA_DEBUG(4, "%s(%p)\n", __FUNCTION__, self);			err = irda_open_tsap(self, addr->sir_lsap_sel, addr->sir_name);	if (err < 0)		return err;	struct timeval time_s;	gettimeofday(&time_s,NULL);	/*  Register with LM-IAS */	self->ias_obj = irias_new_object(addr->sir_name, time_s.tv_sec);	irias_add_integer_attrib(self->ias_obj, "IrDA:TinyTP:LsapSel",		self->stsap_sel, IAS_KERNEL_ATTR);	irias_insert_object(self->ias_obj);		return 0;}/** Function  irda_accept(void)**    Wait for incoming connection**/static int irda_accept(){	IRDA_DEBUG(2, "%s()\n", __FUNCTION__);		irda_connect_response();		return 0;}void af_irda_init(){    pthread_mutex_init(&obex_rec_mutex,NULL);    pthread_cond_init(&obex_rec_cond,NULL);    struct irda_cb *self = irda_self;    skb_queue_head_init(&self->sk_receive_queue);	}int get_mtu_size(obex_t *obex){		int mtu;	int len = sizeof(int);	if (irda_getopt(IRTTP_MAX_SDU_SIZE, (void *) &mtu, 		&len)) 	{		return -1;	}		obex->trans.mtu = mtu;		return 0;}/** Function irda_connect (sock, uaddr, addr_len, flags)**    Connect to a IrDA device** The main difference with a "standard" connect is that with IrDA we need* to resolve the service name into a TSAP selector (in TCP, port number* doesn't have to be resolved).* Because of this service name resoltion, we can offer "auto-connect",* where we connect to a service without specifying a destination address.** Note : by consulting "errno", the user space caller may learn the cause

⌨️ 快捷键说明

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