534 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			534 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*********************************************************************
 | |
|  *
 | |
|  * Filename:      irlan_client_event.c
 | |
|  * Version:       0.9
 | |
|  * Description:   IrLAN client state machine
 | |
|  * Status:        Experimental.
 | |
|  * Author:        Dag Brattli <dagb@cs.uit.no>
 | |
|  * Created at:    Sun Aug 31 20:14:37 1997
 | |
|  * Modified at:   Sun Dec 26 21:52:24 1999
 | |
|  * Modified by:   Dag Brattli <dagb@cs.uit.no>
 | |
|  *
 | |
|  *     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/skbuff.h>
 | |
| 
 | |
| #include <net/irda/irda.h>
 | |
| #include <net/irda/timer.h>
 | |
| #include <net/irda/irmod.h>
 | |
| #include <net/irda/iriap.h>
 | |
| #include <net/irda/irlmp.h>
 | |
| #include <net/irda/irttp.h>
 | |
| 
 | |
| #include <net/irda/irlan_common.h>
 | |
| #include <net/irda/irlan_client.h>
 | |
| #include <net/irda/irlan_event.h>
 | |
| 
 | |
| static int irlan_client_state_idle (struct irlan_cb *self, IRLAN_EVENT event,
 | |
| 				    struct sk_buff *skb);
 | |
| static int irlan_client_state_query(struct irlan_cb *self, IRLAN_EVENT event,
 | |
| 				    struct sk_buff *skb);
 | |
| static int irlan_client_state_conn (struct irlan_cb *self, IRLAN_EVENT event,
 | |
| 				    struct sk_buff *skb);
 | |
| static int irlan_client_state_info (struct irlan_cb *self, IRLAN_EVENT event,
 | |
| 				    struct sk_buff *skb);
 | |
| static int irlan_client_state_media(struct irlan_cb *self, IRLAN_EVENT event,
 | |
| 				    struct sk_buff *skb);
 | |
| static int irlan_client_state_open (struct irlan_cb *self, IRLAN_EVENT event,
 | |
| 				    struct sk_buff *skb);
 | |
| static int irlan_client_state_wait (struct irlan_cb *self, IRLAN_EVENT event,
 | |
| 				    struct sk_buff *skb);
 | |
| static int irlan_client_state_arb  (struct irlan_cb *self, IRLAN_EVENT event,
 | |
| 				    struct sk_buff *skb);
 | |
| static int irlan_client_state_data (struct irlan_cb *self, IRLAN_EVENT event,
 | |
| 				    struct sk_buff *skb);
 | |
| static int irlan_client_state_close(struct irlan_cb *self, IRLAN_EVENT event,
 | |
| 				    struct sk_buff *skb);
 | |
| static int irlan_client_state_sync (struct irlan_cb *self, IRLAN_EVENT event,
 | |
| 				    struct sk_buff *skb);
 | |
| 
 | |
| static int (*state[])(struct irlan_cb *, IRLAN_EVENT event, struct sk_buff *) =
 | |
| {
 | |
| 	irlan_client_state_idle,
 | |
| 	irlan_client_state_query,
 | |
| 	irlan_client_state_conn,
 | |
| 	irlan_client_state_info,
 | |
| 	irlan_client_state_media,
 | |
| 	irlan_client_state_open,
 | |
| 	irlan_client_state_wait,
 | |
| 	irlan_client_state_arb,
 | |
| 	irlan_client_state_data,
 | |
| 	irlan_client_state_close,
 | |
| 	irlan_client_state_sync
 | |
| };
 | |
| 
 | |
| void irlan_do_client_event(struct irlan_cb *self, IRLAN_EVENT event,
 | |
| 			   struct sk_buff *skb)
 | |
| {
 | |
| 	IRDA_ASSERT(self != NULL, return;);
 | |
| 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
 | |
| 
 | |
| 	(*state[ self->client.state]) (self, event, skb);
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Function irlan_client_state_idle (event, skb, info)
 | |
|  *
 | |
|  *    IDLE, We are waiting for an indication that there is a provider
 | |
|  *    available.
 | |
|  */
 | |
| static int irlan_client_state_idle(struct irlan_cb *self, IRLAN_EVENT event,
 | |
| 				   struct sk_buff *skb)
 | |
| {
 | |
| 	IRDA_DEBUG(4, "%s()\n", __func__ );
 | |
| 
 | |
| 	IRDA_ASSERT(self != NULL, return -1;);
 | |
| 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -1;);
 | |
| 
 | |
| 	switch (event) {
 | |
| 	case IRLAN_DISCOVERY_INDICATION:
 | |
| 		if (self->client.iriap) {
 | |
| 			IRDA_WARNING("%s(), busy with a previous query\n",
 | |
| 				     __func__);
 | |
| 			return -EBUSY;
 | |
| 		}
 | |
| 
 | |
| 		self->client.iriap = iriap_open(LSAP_ANY, IAS_CLIENT, self,
 | |
| 						irlan_client_get_value_confirm);
 | |
| 		/* Get some values from peer IAS */
 | |
| 		irlan_next_client_state(self, IRLAN_QUERY);
 | |
| 		iriap_getvaluebyclass_request(self->client.iriap,
 | |
| 					      self->saddr, self->daddr,
 | |
| 					      "IrLAN", "IrDA:TinyTP:LsapSel");
 | |
| 		break;
 | |
| 	case IRLAN_WATCHDOG_TIMEOUT:
 | |
| 		IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __func__ );
 | |
| 		break;
 | |
| 	default:
 | |
| 		IRDA_DEBUG(4, "%s(), Unknown event %d\n", __func__ , event);
 | |
| 		break;
 | |
| 	}
 | |
| 	if (skb)
 | |
| 		dev_kfree_skb(skb);
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Function irlan_client_state_query (event, skb, info)
 | |
|  *
 | |
|  *    QUERY, We have queryed the remote IAS and is ready to connect
 | |
|  *    to provider, just waiting for the confirm.
 | |
|  *
 | |
|  */
 | |
| static int irlan_client_state_query(struct irlan_cb *self, IRLAN_EVENT event,
 | |
| 				    struct sk_buff *skb)
 | |
| {
 | |
| 	IRDA_DEBUG(4, "%s()\n", __func__ );
 | |
| 
 | |
| 	IRDA_ASSERT(self != NULL, return -1;);
 | |
| 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -1;);
 | |
| 
 | |
| 	switch(event) {
 | |
| 	case IRLAN_IAS_PROVIDER_AVAIL:
 | |
| 		IRDA_ASSERT(self->dtsap_sel_ctrl != 0, return -1;);
 | |
| 
 | |
| 		self->client.open_retries = 0;
 | |
| 
 | |
| 		irttp_connect_request(self->client.tsap_ctrl,
 | |
| 				      self->dtsap_sel_ctrl,
 | |
| 				      self->saddr, self->daddr, NULL,
 | |
| 				      IRLAN_MTU, NULL);
 | |
| 		irlan_next_client_state(self, IRLAN_CONN);
 | |
| 		break;
 | |
| 	case IRLAN_IAS_PROVIDER_NOT_AVAIL:
 | |
| 		IRDA_DEBUG(2, "%s(), IAS_PROVIDER_NOT_AVAIL\n", __func__ );
 | |
| 		irlan_next_client_state(self, IRLAN_IDLE);
 | |
| 
 | |
| 		/* Give the client a kick! */
 | |
| 		if ((self->provider.access_type == ACCESS_PEER) &&
 | |
| 		    (self->provider.state != IRLAN_IDLE))
 | |
| 			irlan_client_wakeup(self, self->saddr, self->daddr);
 | |
| 		break;
 | |
| 	case IRLAN_LMP_DISCONNECT:
 | |
| 	case IRLAN_LAP_DISCONNECT:
 | |
| 		irlan_next_client_state(self, IRLAN_IDLE);
 | |
| 		break;
 | |
| 	case IRLAN_WATCHDOG_TIMEOUT:
 | |
| 		IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __func__ );
 | |
| 		break;
 | |
| 	default:
 | |
| 		IRDA_DEBUG(2, "%s(), Unknown event %d\n", __func__ , event);
 | |
| 		break;
 | |
| 	}
 | |
| 	if (skb)
 | |
| 		dev_kfree_skb(skb);
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Function irlan_client_state_conn (event, skb, info)
 | |
|  *
 | |
|  *    CONN, We have connected to a provider but has not issued any
 | |
|  *    commands yet.
 | |
|  *
 | |
|  */
 | |
| static int irlan_client_state_conn(struct irlan_cb *self, IRLAN_EVENT event,
 | |
| 				   struct sk_buff *skb)
 | |
| {
 | |
| 	IRDA_DEBUG(4, "%s()\n", __func__ );
 | |
| 
 | |
| 	IRDA_ASSERT(self != NULL, return -1;);
 | |
| 
 | |
| 	switch (event) {
 | |
| 	case IRLAN_CONNECT_COMPLETE:
 | |
| 		/* Send getinfo cmd */
 | |
| 		irlan_get_provider_info(self);
 | |
| 		irlan_next_client_state(self, IRLAN_INFO);
 | |
| 		break;
 | |
| 	case IRLAN_LMP_DISCONNECT:
 | |
| 	case IRLAN_LAP_DISCONNECT:
 | |
| 		irlan_next_client_state(self, IRLAN_IDLE);
 | |
| 		break;
 | |
| 	case IRLAN_WATCHDOG_TIMEOUT:
 | |
| 		IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __func__ );
 | |
| 		break;
 | |
| 	default:
 | |
| 		IRDA_DEBUG(2, "%s(), Unknown event %d\n", __func__ , event);
 | |
| 		break;
 | |
| 	}
 | |
| 	if (skb)
 | |
| 		dev_kfree_skb(skb);
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Function irlan_client_state_info (self, event, skb, info)
 | |
|  *
 | |
|  *    INFO, We have issued a GetInfo command and is awaiting a reply.
 | |
|  */
 | |
| static int irlan_client_state_info(struct irlan_cb *self, IRLAN_EVENT event,
 | |
| 				   struct sk_buff *skb)
 | |
| {
 | |
| 	IRDA_DEBUG(4, "%s()\n", __func__ );
 | |
| 
 | |
| 	IRDA_ASSERT(self != NULL, return -1;);
 | |
| 
 | |
| 	switch (event) {
 | |
| 	case IRLAN_DATA_INDICATION:
 | |
| 		IRDA_ASSERT(skb != NULL, return -1;);
 | |
| 
 | |
| 		irlan_client_parse_response(self, skb);
 | |
| 
 | |
| 		irlan_next_client_state(self, IRLAN_MEDIA);
 | |
| 
 | |
| 		irlan_get_media_char(self);
 | |
| 		break;
 | |
| 
 | |
| 	case IRLAN_LMP_DISCONNECT:
 | |
| 	case IRLAN_LAP_DISCONNECT:
 | |
| 		irlan_next_client_state(self, IRLAN_IDLE);
 | |
| 		break;
 | |
| 	case IRLAN_WATCHDOG_TIMEOUT:
 | |
| 		IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __func__ );
 | |
| 		break;
 | |
| 	default:
 | |
| 		IRDA_DEBUG(2, "%s(), Unknown event %d\n", __func__ , event);
 | |
| 		break;
 | |
| 	}
 | |
| 	if (skb)
 | |
| 		dev_kfree_skb(skb);
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Function irlan_client_state_media (self, event, skb, info)
 | |
|  *
 | |
|  *    MEDIA, The irlan_client has issued a GetMedia command and is awaiting a
 | |
|  *    reply.
 | |
|  *
 | |
|  */
 | |
| static int irlan_client_state_media(struct irlan_cb *self, IRLAN_EVENT event,
 | |
| 				    struct sk_buff *skb)
 | |
| {
 | |
| 	IRDA_DEBUG(4, "%s()\n", __func__ );
 | |
| 
 | |
| 	IRDA_ASSERT(self != NULL, return -1;);
 | |
| 
 | |
| 	switch(event) {
 | |
| 	case IRLAN_DATA_INDICATION:
 | |
| 		irlan_client_parse_response(self, skb);
 | |
| 		irlan_open_data_channel(self);
 | |
| 		irlan_next_client_state(self, IRLAN_OPEN);
 | |
| 		break;
 | |
| 	case IRLAN_LMP_DISCONNECT:
 | |
| 	case IRLAN_LAP_DISCONNECT:
 | |
| 		irlan_next_client_state(self, IRLAN_IDLE);
 | |
| 		break;
 | |
| 	case IRLAN_WATCHDOG_TIMEOUT:
 | |
| 		IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __func__ );
 | |
| 		break;
 | |
| 	default:
 | |
| 		IRDA_DEBUG(2, "%s(), Unknown event %d\n", __func__ , event);
 | |
| 		break;
 | |
| 	}
 | |
| 	if (skb)
 | |
| 		dev_kfree_skb(skb);
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Function irlan_client_state_open (self, event, skb, info)
 | |
|  *
 | |
|  *    OPEN, The irlan_client has issued a OpenData command and is awaiting a
 | |
|  *    reply
 | |
|  *
 | |
|  */
 | |
| static int irlan_client_state_open(struct irlan_cb *self, IRLAN_EVENT event,
 | |
| 				   struct sk_buff *skb)
 | |
| {
 | |
| 	struct qos_info qos;
 | |
| 
 | |
| 	IRDA_DEBUG(4, "%s()\n", __func__ );
 | |
| 
 | |
| 	IRDA_ASSERT(self != NULL, return -1;);
 | |
| 
 | |
| 	switch(event) {
 | |
| 	case IRLAN_DATA_INDICATION:
 | |
| 		irlan_client_parse_response(self, skb);
 | |
| 
 | |
| 		/*
 | |
| 		 *  Check if we have got the remote TSAP for data
 | |
| 		 *  communications
 | |
| 		 */
 | |
| 		IRDA_ASSERT(self->dtsap_sel_data != 0, return -1;);
 | |
| 
 | |
| 		/* Check which access type we are dealing with */
 | |
| 		switch (self->client.access_type) {
 | |
| 		case ACCESS_PEER:
 | |
| 		    if (self->provider.state == IRLAN_OPEN) {
 | |
| 
 | |
| 			    irlan_next_client_state(self, IRLAN_ARB);
 | |
| 			    irlan_do_client_event(self, IRLAN_CHECK_CON_ARB,
 | |
| 						  NULL);
 | |
| 		    } else {
 | |
| 
 | |
| 			    irlan_next_client_state(self, IRLAN_WAIT);
 | |
| 		    }
 | |
| 		    break;
 | |
| 		case ACCESS_DIRECT:
 | |
| 		case ACCESS_HOSTED:
 | |
| 			qos.link_disc_time.bits = 0x01; /* 3 secs */
 | |
| 
 | |
| 			irttp_connect_request(self->tsap_data,
 | |
| 					      self->dtsap_sel_data,
 | |
| 					      self->saddr, self->daddr, &qos,
 | |
| 					      IRLAN_MTU, NULL);
 | |
| 
 | |
| 			irlan_next_client_state(self, IRLAN_DATA);
 | |
| 			break;
 | |
| 		default:
 | |
| 			IRDA_DEBUG(2, "%s(), unknown access type!\n", __func__ );
 | |
| 			break;
 | |
| 		}
 | |
| 		break;
 | |
| 	case IRLAN_LMP_DISCONNECT:
 | |
| 	case IRLAN_LAP_DISCONNECT:
 | |
| 		irlan_next_client_state(self, IRLAN_IDLE);
 | |
| 		break;
 | |
| 	case IRLAN_WATCHDOG_TIMEOUT:
 | |
| 		IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __func__ );
 | |
| 		break;
 | |
| 	default:
 | |
| 		IRDA_DEBUG(2, "%s(), Unknown event %d\n", __func__ , event);
 | |
| 		break;
 | |
| 	}
 | |
| 
 | |
| 	if (skb)
 | |
| 		dev_kfree_skb(skb);
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Function irlan_client_state_wait (self, event, skb, info)
 | |
|  *
 | |
|  *    WAIT, The irlan_client is waiting for the local provider to enter the
 | |
|  *    provider OPEN state.
 | |
|  *
 | |
|  */
 | |
| static int irlan_client_state_wait(struct irlan_cb *self, IRLAN_EVENT event,
 | |
| 				   struct sk_buff *skb)
 | |
| {
 | |
| 	IRDA_DEBUG(4, "%s()\n", __func__ );
 | |
| 
 | |
| 	IRDA_ASSERT(self != NULL, return -1;);
 | |
| 
 | |
| 	switch(event) {
 | |
| 	case IRLAN_PROVIDER_SIGNAL:
 | |
| 		irlan_next_client_state(self, IRLAN_ARB);
 | |
| 		irlan_do_client_event(self, IRLAN_CHECK_CON_ARB, NULL);
 | |
| 		break;
 | |
| 	case IRLAN_LMP_DISCONNECT:
 | |
| 	case IRLAN_LAP_DISCONNECT:
 | |
| 		irlan_next_client_state(self, IRLAN_IDLE);
 | |
| 		break;
 | |
| 	case IRLAN_WATCHDOG_TIMEOUT:
 | |
| 		IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __func__ );
 | |
| 		break;
 | |
| 	default:
 | |
| 		IRDA_DEBUG(2, "%s(), Unknown event %d\n", __func__ , event);
 | |
| 		break;
 | |
| 	}
 | |
| 	if (skb)
 | |
| 		dev_kfree_skb(skb);
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static int irlan_client_state_arb(struct irlan_cb *self, IRLAN_EVENT event,
 | |
| 				  struct sk_buff *skb)
 | |
| {
 | |
| 	struct qos_info qos;
 | |
| 
 | |
| 	IRDA_DEBUG(2, "%s()\n", __func__ );
 | |
| 
 | |
| 	IRDA_ASSERT(self != NULL, return -1;);
 | |
| 
 | |
| 	switch(event) {
 | |
| 	case IRLAN_CHECK_CON_ARB:
 | |
| 		if (self->client.recv_arb_val == self->provider.send_arb_val) {
 | |
| 			irlan_next_client_state(self, IRLAN_CLOSE);
 | |
| 			irlan_close_data_channel(self);
 | |
| 		} else if (self->client.recv_arb_val <
 | |
| 			   self->provider.send_arb_val)
 | |
| 		{
 | |
| 			qos.link_disc_time.bits = 0x01; /* 3 secs */
 | |
| 
 | |
| 			irlan_next_client_state(self, IRLAN_DATA);
 | |
| 			irttp_connect_request(self->tsap_data,
 | |
| 					      self->dtsap_sel_data,
 | |
| 					      self->saddr, self->daddr, &qos,
 | |
| 					      IRLAN_MTU, NULL);
 | |
| 		} else if (self->client.recv_arb_val >
 | |
| 			   self->provider.send_arb_val)
 | |
| 		{
 | |
| 			IRDA_DEBUG(2, "%s(), lost the battle :-(\n", __func__ );
 | |
| 		}
 | |
| 		break;
 | |
| 	case IRLAN_DATA_CONNECT_INDICATION:
 | |
| 		irlan_next_client_state(self, IRLAN_DATA);
 | |
| 		break;
 | |
| 	case IRLAN_LMP_DISCONNECT:
 | |
| 	case IRLAN_LAP_DISCONNECT:
 | |
| 		irlan_next_client_state(self, IRLAN_IDLE);
 | |
| 		break;
 | |
| 	case IRLAN_WATCHDOG_TIMEOUT:
 | |
| 		IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __func__ );
 | |
| 		break;
 | |
| 	default:
 | |
| 		IRDA_DEBUG(2, "%s(), Unknown event %d\n", __func__ , event);
 | |
| 		break;
 | |
| 	}
 | |
| 	if (skb)
 | |
| 		dev_kfree_skb(skb);
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Function irlan_client_state_data (self, event, skb, info)
 | |
|  *
 | |
|  *    DATA, The data channel is connected, allowing data transfers between
 | |
|  *    the local and remote machines.
 | |
|  *
 | |
|  */
 | |
| static int irlan_client_state_data(struct irlan_cb *self, IRLAN_EVENT event,
 | |
| 				   struct sk_buff *skb)
 | |
| {
 | |
| 	IRDA_DEBUG(4, "%s()\n", __func__ );
 | |
| 
 | |
| 	IRDA_ASSERT(self != NULL, return -1;);
 | |
| 	IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -1;);
 | |
| 
 | |
| 	switch(event) {
 | |
| 	case IRLAN_DATA_INDICATION:
 | |
| 		irlan_client_parse_response(self, skb);
 | |
| 		break;
 | |
| 	case IRLAN_LMP_DISCONNECT: /* FALLTHROUGH */
 | |
| 	case IRLAN_LAP_DISCONNECT:
 | |
| 		irlan_next_client_state(self, IRLAN_IDLE);
 | |
| 		break;
 | |
| 	default:
 | |
| 		IRDA_DEBUG(2, "%s(), Unknown event %d\n", __func__ , event);
 | |
| 		break;
 | |
| 	}
 | |
| 	if (skb)
 | |
| 		dev_kfree_skb(skb);
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Function irlan_client_state_close (self, event, skb, info)
 | |
|  *
 | |
|  *
 | |
|  *
 | |
|  */
 | |
| static int irlan_client_state_close(struct irlan_cb *self, IRLAN_EVENT event,
 | |
| 				    struct sk_buff *skb)
 | |
| {
 | |
| 	IRDA_DEBUG(2, "%s()\n", __func__ );
 | |
| 
 | |
| 	if (skb)
 | |
| 		dev_kfree_skb(skb);
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Function irlan_client_state_sync (self, event, skb, info)
 | |
|  *
 | |
|  *
 | |
|  *
 | |
|  */
 | |
| static int irlan_client_state_sync(struct irlan_cb *self, IRLAN_EVENT event,
 | |
| 				   struct sk_buff *skb)
 | |
| {
 | |
| 	IRDA_DEBUG(2, "%s()\n", __func__ );
 | |
| 
 | |
| 	if (skb)
 | |
| 		dev_kfree_skb(skb);
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 |