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

📄 af_irda.c

📁 sparc硬件平台上的红外协议
💻 C
📖 第 1 页 / 共 2 页
字号:
* of the failure. Most of them are visible in the function, others may come* from subroutines called and are listed here :*	o EBUSY : already processing a connect*	o EHOSTUNREACH : bad addr->sir_addr argument*	o EADDRNOTAVAIL : bad addr->sir_name argument*	o ENOTUNIQ : more than one node has addr->sir_name (auto-connect)*	o ENETUNREACH : no node found on the network (auto-connect)*/int iriap_connect( struct addr_irda *addr){	struct irda_cb *self = irda_self;		IRDA_DEBUG(2, "%s(%p)\n", __FUNCTION__, self);		/* Check if user supplied any destination device address */	if ((!addr->sir_addr) || (addr->sir_addr == DEV_ADDR_ANY)) {		/* Try to find one suitable */		IRDA_ERROR("NO ADDR %s()\n", __FUNCTION__);			} else {		/* Use the one provided by the user */		self->daddr = addr->sir_addr;		IRDA_DEBUG(1, "%s(), daddr = %08x\n", __FUNCTION__, self->daddr);				/* If we don't have a valid service name, we assume the		* user want to connect on a specific LSAP. Prevent		* the use of invalid LSAPs (IrLMP 1.1 p10). Jean II */		if((addr->sir_name[0] != '\0') ||			(addr->sir_lsap_sel >= 0x70)) {			/* Query remote LM-IAS using service name */			irda_find_lsap_sel(self, addr->sir_name);					} else {		/* Directly connect to the remote LSAP		* specified by the sir_lsap field.		* Please use with caution, in IrDA LSAPs are			* dynamic and there is no "well-known" LSAP. */			self->dtsap_sel = addr->sir_lsap_sel;		}	}	return 0;	}int irda_ttp_connect(struct addr_irda *addr){	struct irda_cb *self = irda_self;	int err;		/* Check if we have opened a local TSAP */	if (!self->tsap)		irda_open_tsap(self, LSAP_ANY, addr->sir_name);		/* Connect to remote device */	err = irttp_connect_request(self->tsap, self->dtsap_sel,				    self->saddr, self->daddr, NULL,					self->max_sdu_size_rx, NULL);	if (err) {		IRDA_DEBUG(0, "%s(), connect failed!\n", __FUNCTION__);		return err;	}		self->saddr = irttp_get_saddr(self->tsap);		return 0;}/** Function irda_create (sock, protocol)**    Create IrDA socket**/int irda_create(void){	struct irda_cb *self;		IRDA_DEBUG(2, "%s()\n", __FUNCTION__);		/* Allocate networking socket */	irda_self = (struct irda_cb*)malloc(sizeof(struct irda_cb));	if (irda_self == NULL)	{			IRDA_ERROR("%s() can not allocate memory\n",__FUNCTION__);				return -ENOMEM;	}       memset(irda_self,0,sizeof(struct irda_cb));	self = irda_self;	IRDA_DEBUG(2, "%s() : self is %p\n", __FUNCTION__, self);		self->max_sdu_size_rx = TTP_SAR_DISABLE;		/* Register as a client with IrLMP */	self->ckey = irlmp_register_client(0, NULL, NULL, NULL);	self->mask.word = 0xffff;	self->rx_flow = self->tx_flow = FLOW_START;	self->nslots = DISCOVERY_DEFAULT_SLOTS;	self->daddr = DEV_ADDR_ANY;	/* Until we get connected */	self->saddr = 0x0;		/* so IrLMP assign us any link */	return 0;}/** Function irda_destroy_socket (self)**    Destroy socket**/static void irda_destroy(struct irda_cb *self){	IRDA_DEBUG(4, "%s(%p)\n", __FUNCTION__, self);		/* Unregister with IrLMP */	irlmp_unregister_client(self->ckey);	irlmp_unregister_service(self->skey);	pthread_mutex_destroy(&obex_rec_mutex);	pthread_cond_destroy(&obex_rec_cond);	/* Unregister with LM-IAS */	if (self->ias_obj) {		irias_delete_object(self->ias_obj);		self->ias_obj = NULL;	}		if (self->iriap) {		iriap_close(self->iriap);		self->iriap = NULL;	}		if (self->tsap) {		irttp_disconnect_request(self->tsap, NULL, P_NORMAL);		irttp_close_tsap(self->tsap);		self->tsap = NULL;	}	}/** Function irda_release (sock)*/int irda_release(void){	struct irda_cb *self = irda_self;		IRDA_DEBUG(4, "%s()\n", __FUNCTION__);		if (self == NULL)		return 0;		/* Destroy IrDA socket */	irda_destroy(self);		/* Purge queues (see sock_init_data()) */	skb_queue_purge();	if (self != NULL)	{		free(self);			}	/* Destroy networking socket if we are the last reference on it,	* i.e. if(sk->sk_refcnt == 0) -> sk_free(sk) */			/* Notes on socket locking and deallocation... - Jean II	* In theory we should put pairs of sock_hold() / sock_put() to	* prevent the socket to be destroyed whenever there is an	* outstanding request or outstanding incoming packet or event.	*	* 1) This may include IAS request, both in connect and getsockopt.	* Unfortunately, the situation is a bit more messy than it looks,	* because we close iriap and kfree(self) above.	*	* 2) This may include selective discovery in getsockopt.	* Same stuff as above, irlmp registration and self are gone.	*	* Probably 1 and 2 may not matter, because it's all triggered	* by a process and the socket layer already prevent the	* socket to go away while a process is holding it, through	* sockfd_put() and fput()...	*	* 3) This may include deferred TSAP closure. In particular,	* we may receive a late irda_disconnect_indication()	* Fortunately, (tsap_cb *)->close_pend should protect us	* from that.	*	* I did some testing on SMP, and it looks solid. And the socket	* memory leak is now gone... - Jean II	*/		return 0;}/** Function irda_sendmsg (iocb, sock, msg, len)**    Send message down to TinyTP. This function is used for both STREAM and*    SEQPACK services. This is possible since it forces the client to*    fragment the message if necessary*/int irda_sendmsg(char  *obex_msg, size_t len){		struct irda_cb *self = irda_self;	struct sk_buff *skb;	int err;		 IRDA_DEBUG(4, "%s(), len=%d\n", __FUNCTION__, len);	   	   /* Check if IrTTP is wants us to slow down */	           	           	   /* Check that we don't send out too big frames */        	   if (len > self->max_data_size) {        		   IRDA_DEBUG(4, "%s(), Chopping frame from %zd to %d bytes!\n",        			   __FUNCTION__, len, self->max_data_size);        		   len = self->max_data_size;        	   }        	           	   skb = skb_alloc(self->max_header_size + 16+len);        	   if (!skb)        		   return -ENOBUFS;        	           	   skb_reserve(skb, self->max_header_size + 16);        	   skb_reset_transport_header(skb);        	   skb_put(skb, len);        	           	   memcpy(skb->data,(unsigned char*)obex_msg,len);        	   /*        	   * Just send the message to TinyTP, and let it deal with possible        	   * errors. No need to duplicate all that here        	   */        	           	           	   err = irttp_data_request(self->tsap, skb);        	   if (err) {        		   IRDA_DEBUG(0, "%s(), err=%d\n", __FUNCTION__, err);        		   return err;        	   }        	   /* Tell client how much data we actually sent */        	   return len;}/** Function irda_recvmsg_stream (iocb, sock, msg, size, flags)*/int irda_recvmsg_stream(char *obex_msg, size_t size){		struct irda_cb *self = irda_self;	struct sk_buff* sk_peek;	size_t copied = 0;		IRDA_DEBUG(4, "%s()\n", __FUNCTION__);		do {		int chunk;				while(1)		{			sk_peek = skb_peek(&self->sk_receive_queue);			if (sk_peek == NULL)			{								pthread_mutex_lock(&obex_rec_mutex);								pthread_cond_wait(&obex_rec_cond,&obex_rec_mutex);				pthread_mutex_unlock(&obex_rec_mutex);							}			else			{				break;			}		}		struct sk_buff *skb = skb_dequeue(&self->sk_receive_queue);				if (skb == NULL)		{			return 0;		}				chunk = skb->len> size?size:skb->len;				memcpy(obex_msg+copied, skb->data, chunk);				copied += chunk;		size -= chunk;				if (chunk < skb->len) {			skb_pull(skb, chunk);						/* put the skb back if we didn't use it up.. */			if (skb->len) {				IRDA_DEBUG(1, "%s(), back on q!\n",					__FUNCTION__);								skb_queue_head(&self->sk_receive_queue, skb);								break;			}		} 		else		{			kfree_skb(skb);		}			} while (size);		return copied;}/** Function irda_shutdown (sk, how)*/int irda_shutdown( int how){		struct irda_cb *self = irda_self;	IRDA_DEBUG(1, "%s(%p)\n", __FUNCTION__, self);		if (self->iriap) {		iriap_close(self->iriap);		self->iriap = NULL;	}		if (self->tsap) {		irttp_disconnect_request(self->tsap, NULL, P_NORMAL);		irttp_close_tsap(self->tsap);		self->tsap = NULL;	}			self->daddr = DEV_ADDR_ANY;	/* Until we get re-connected */	self->saddr = 0x0;		/* so IrLMP assign us any link */		return 0;}/** Function irda_setsockopt (sock, level, optname, optval, optlen)**    Set some options for the socket**/int irda_setopt( int level, int optname,				char  *optval, int optlen){		struct irda_cb *self = irda_self;		int opt=0;		IRDA_DEBUG(2, "%s(%p)\n", __FUNCTION__, self);		if (level != SOL_IRLMP)		return -ENOPROTOOPT;		switch (optname) {			case IRLMP_HINTS_SET:		if (optlen < sizeof(int))			return -EINVAL;						/* Unregister any old registration */		if (self->skey)			irlmp_unregister_service(self->skey);		self->skey = irlmp_register_service(*((__u16*) optval));		break;	case IRLMP_HINT_MASK_SET:	/* As opposed to the previous case which set the hint bits	* that we advertise, this one set the filter we use when	* making a discovery (nodes which don't match any hint	* bit in the mask are not reported).		*/		if (optlen < sizeof(int))			return -EINVAL;				self->mask.word =  *((__u16*)optval);		/* Mask out extension bits */		self->mask.word &= 0x7f7f;		/* Check if no bits */		if(!self->mask.word)			self->mask.word = 0xFFFF;				break;	default:		return -EINVAL;	}	return 0;}/** Function irda_getsockopt (sock, level, optname, optval, optlen)*/int irda_getopt( int optname,				void *optval, int  *len){		struct irda_cb *self;	struct irda_device_list list;	struct irda_device_info *discoveries;		int val = 0;	int err = 0;	int offset, total;	self = irda_self;	IRDA_DEBUG(1, "%s(%p)\n", __FUNCTION__, self);		switch (optname) {	case IRLMP_ENUMDEVICES:		/* Ask lmp for the current discovery log */		discoveries = irlmp_get_discoveries(&list.len, self->mask.word,			self->nslots);		/* Check if the we got some results */		if (discoveries == NULL)		{			return -EAGAIN;		}		/* Didn't find any devices */				if (list.len > 2048)		{			err = -EINVAL;			goto bed;		}		*((__u32*)(optval)) = list.len; 		offset = sizeof(struct irda_device_list) -			sizeof(struct irda_device_info);		total = offset + (list.len * sizeof(struct irda_device_info));		if (total > len)		{			total = len;		}			memcpy(optval+offset,discoveries,total-offset);		*len = total;bed:		free(discoveries);		if (err)		{						return err;		}				break;	case IRLMP_MAX_SDU_SIZE:		*((int*)optval )= self->max_data_size;		*len = sizeof(int);		break;			default:		return -ENOPROTOOPT;	}		return 0;}

⌨️ 快捷键说明

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