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

📄 irnet_irda.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
       * ALLOW_SIMULT_CONNECT is undefined. ttp_connect should be 1.       * 3) we are half way in irnet_disconnect_indication(), and it's a       * nice race condition... Fortunately, we can detect that by checking       * if tsap is still alive. On the other hand, we can't be in       * irda_irnet_destroy() otherwise we would not have found this       * socket in the hashbin.       * Jean II */      if((test_bit(0, &new->ttp_connect)) || (new->tsap != NULL))	{	  /* Don't mess this socket, somebody else in in charge... */	  DERROR(IRDA_CB_ERROR, "Race condition detected, socket in use, abort connect...\n");	  irnet_disconnect_server(server, skb);	  return;	}    }  /* So : at this point, we have a socket, and it is idle. Good ! */  irnet_connect_socket(server, new, qos, max_sdu_size, max_header_size);  /* Check size of received packet */  if(skb->len > 0)    {#ifdef PASS_CONNECT_PACKETS      DEBUG(IRDA_CB_INFO, "Passing connect packet to PPP.\n");      /* Try to pass it to PPP */      irnet_data_indication(new, new->tsap, skb);#else /* PASS_CONNECT_PACKETS */      DERROR(IRDA_CB_ERROR, "Dropping non empty packet.\n");      kfree_skb(skb);	/* Note : will be optimised with other kfree... */#endif /* PASS_CONNECT_PACKETS */    }  else    kfree_skb(skb);  DEXIT(IRDA_TCB_TRACE, "\n");}/********************** IRDA-IAS/LMP CALLBACKS **********************//* * These are the callbacks called by other layers of the IrDA stack, * mainly LMP for discovery and IAS for name queries. *//*------------------------------------------------------------------*//* * Function irnet_getvalue_confirm (result, obj_id, value, priv) * *    Got answer from remote LM-IAS, just connect * * This is the reply to a IAS query we were doing to find the TSAP of * the device we want to connect to. * If we have found a valid TSAP, just initiate the TTP connection * on this TSAP. */static voidirnet_getvalue_confirm(int	result,		       __u16	obj_id, 		       struct ias_value *value,		       void *	priv){  irnet_socket *	self = (irnet_socket *) priv;  DENTER(IRDA_OCB_TRACE, "(self=0x%X)\n", (unsigned int) self);  DASSERT(self != NULL, , IRDA_OCB_ERROR, "Self is NULL !!!\n");  /* Check if already connected (via irnet_connect_socket())   * or socket is closing down (via irda_irnet_destroy()) */  if(! test_bit(0, &self->ttp_connect))    {      DERROR(IRDA_OCB_ERROR, "Socket no longer connecting. Ouch !\n");      return;    }  /* We probably don't need to make any more queries */  iriap_close(self->iriap);  self->iriap = NULL;  /* Post process the IAS reply */  self->dtsap_sel = irnet_ias_to_tsap(self, result, value);  /* If error, just go out */  if(self->errno)    {      clear_bit(0, &self->ttp_connect);      DERROR(IRDA_OCB_ERROR, "IAS connect failed ! (0x%X)\n", self->errno);      return;    }  DEBUG(IRDA_OCB_INFO, "daddr = %08x, lsap = %d, starting IrTTP connection\n",	self->daddr, self->dtsap_sel);  /* Start up TTP - non blocking */  irnet_connect_tsap(self);  DEXIT(IRDA_OCB_TRACE, "\n");}/*------------------------------------------------------------------*//* * Function irnet_discovervalue_confirm (result, obj_id, value, priv) * *    Handle the TSAP discovery procedure state machine. *    Got answer from remote LM-IAS, try next device * * We are doing a  TSAP discovery procedure, and we got an answer to * a IAS query we were doing to find the TSAP on one of the address * in the discovery log. * * If we have found a valid TSAP for the first time, save it. If it's * not the first time we found one, complain. * * If we have more addresses in the log, just initiate a new query. * Note that those query may fail (see irnet_discover_daddr_and_lsap_sel()) * * Otherwise, wrap up the procedure (cleanup), check if we have found * any device and connect to it. */static voidirnet_discovervalue_confirm(int		result,			    __u16	obj_id, 			    struct ias_value *value,			    void *	priv){  irnet_socket *	self = (irnet_socket *) priv;  __u8			dtsap_sel;		/* TSAP we are looking for */  DENTER(IRDA_OCB_TRACE, "(self=0x%X)\n", (unsigned int) self);  DASSERT(self != NULL, , IRDA_OCB_ERROR, "Self is NULL !!!\n");  /* Check if already connected (via irnet_connect_socket())   * or socket is closing down (via irda_irnet_destroy()) */  if(! test_bit(0, &self->ttp_connect))    {      DERROR(IRDA_OCB_ERROR, "Socket no longer connecting. Ouch !\n");      return;    }  /* Post process the IAS reply */  dtsap_sel = irnet_ias_to_tsap(self, result, value);  /* Have we got something ? */  if(self->errno == 0)    {      /* We found the requested service */      if(self->daddr != DEV_ADDR_ANY)	{	  DERROR(IRDA_OCB_ERROR, "More than one device in range supports IrNET...\n");	}      else	{	  /* First time we found that one, save it ! */	  self->daddr = self->discoveries[self->disco_index].daddr;	  self->dtsap_sel = dtsap_sel;	}    }  /* If no failure */  if((self->errno == -EADDRNOTAVAIL) || (self->errno == 0))    {      int	ret;      /* Search the next node */      ret = irnet_discover_next_daddr(self);      if(!ret)	{	  /* In this case, the above request was non-blocking.	   * We will return here after a while... */	  return;	}      /* In this case, we have processed the last discovery item */    }  /* No more queries to be done (failure or last one) */  /* We probably don't need to make any more queries */  iriap_close(self->iriap);  self->iriap = NULL;  /* No more items : remove the log and signal termination */  DEBUG(IRDA_OCB_INFO, "Cleaning up log (0x%X)\n",	(unsigned int) self->discoveries);  if(self->discoveries != NULL)    {      /* Cleanup our copy of the discovery log */      kfree(self->discoveries);      self->discoveries = NULL;    }  self->disco_number = -1;  /* Check out what we found */  if(self->daddr == DEV_ADDR_ANY)    {      self->daddr = DEV_ADDR_ANY;      clear_bit(0, &self->ttp_connect);      DEXIT(IRDA_OCB_TRACE, ": cannot discover IrNET in any device !!!\n");      return;    }  /* We have a valid address - just connect */  DEBUG(IRDA_OCB_INFO, "daddr = %08x, lsap = %d, starting IrTTP connection\n",	self->daddr, self->dtsap_sel);  /* Start up TTP - non blocking */  irnet_connect_tsap(self);  DEXIT(IRDA_OCB_TRACE, "\n");}#ifdef DISCOVERY_EVENTS/*------------------------------------------------------------------*//* * Function irnet_discovery_indication (discovery) * *    Got a discovery indication from IrLMP, post an event * * Note : IrLMP take care of matching the hint mask for us, we only * check if it is a "new" node... * * As IrLMP filter on the IrLAN hint bit, we get both IrLAN and IrNET * nodes, so it's only at connection time that we will know if the * node support IrNET, IrLAN or both. The other solution is to check * in IAS the PNP ids and service name. * Note : even if a node support IrNET (or IrLAN), it's no guarantee * that we will be able to connect to it, the node might already be * busy... * * One last thing : in some case, this function will trigger duplicate * discovery events. On the other hand, we should catch all * discoveries properly (i.e. not miss one). Filtering duplicate here * is to messy, so we leave that to user space... */static voidirnet_discovery_indication(discovery_t *	discovery,			   DISCOVERY_MODE	mode,			   void *		priv){  irnet_socket *	self = &irnet_server.s;	  DENTER(IRDA_OCB_TRACE, "(self=0x%X)\n", (unsigned int) self);  DASSERT(priv == &irnet_server, , IRDA_OCB_ERROR,	  "Invalid instance (0x%X) !!!\n", (unsigned int) priv);  /* Check if node is discovered is a new one or an old one.   * We check when how long ago this node was discovered, with a   * coarse timeout (we may miss some discovery events or be delayed).   */  if((jiffies - discovery->first_timestamp) >= (sysctl_discovery_timeout * HZ))    {      return;		/* Too old, not interesting -> goodbye */    }  DEBUG(IRDA_OCB_INFO, "Discovered new IrNET/IrLAN node %s...\n",	discovery->nickname);  /* Notify the control channel */  irnet_post_event(NULL, IRNET_DISCOVER,		   discovery->saddr, discovery->daddr, discovery->nickname);  DEXIT(IRDA_OCB_TRACE, "\n");}/*------------------------------------------------------------------*//* * Function irnet_expiry_indication (expiry) * *    Got a expiry indication from IrLMP, post an event * * Note : IrLMP take care of matching the hint mask for us, we only * check if it is a "new" node... */static voidirnet_expiry_indication(discovery_t *	expiry,			DISCOVERY_MODE	mode,			void *		priv){  irnet_socket *	self = &irnet_server.s;	  DENTER(IRDA_OCB_TRACE, "(self=0x%X)\n", (unsigned int) self);  DASSERT(priv == &irnet_server, , IRDA_OCB_ERROR,	  "Invalid instance (0x%X) !!!\n", (unsigned int) priv);  DEBUG(IRDA_OCB_INFO, "IrNET/IrLAN node %s expired...\n",	expiry->nickname);  /* Notify the control channel */  irnet_post_event(NULL, IRNET_EXPIRE,		   expiry->saddr, expiry->daddr, expiry->nickname);  DEXIT(IRDA_OCB_TRACE, "\n");}#endif /* DISCOVERY_EVENTS *//*********************** PROC ENTRY CALLBACKS ***********************//* * We create a instance in the /proc filesystem, and here we take care * of that... */#ifdef CONFIG_PROC_FS/*------------------------------------------------------------------*//* * Function irnet_proc_read (buf, start, offset, len, unused) * *    Give some info to the /proc file system */static intirnet_proc_read(char *	buf,		char **	start,		off_t	offset,		int	len){  irnet_socket *	self;  char *		state;  unsigned long		flags;  int			i = 0;  len = 0;	  /* Get the IrNET server information... */  len += sprintf(buf+len, "IrNET server - ");  len += sprintf(buf+len, "IrDA state: %s, ",		 (irnet_server.running ? "running" : "dead"));  len += sprintf(buf+len, "stsap_sel: %02x, ", irnet_server.s.stsap_sel);  len += sprintf(buf+len, "dtsap_sel: %02x\n", irnet_server.s.dtsap_sel);  /* Do we need to continue ? */  if(!irnet_server.running)    return len;  /* Protect access to the instance list */  spin_lock_irqsave(&irnet_server.spinlock, flags);  /* Get the sockets one by one... */  self = (irnet_socket *) hashbin_get_first(irnet_server.list);  while(self != NULL)    {      /* Start printing info about the socket. */      len += sprintf(buf+len, "\nIrNET socket %d - ", i++);      /* First, get the requested configuration */      len += sprintf(buf+len, "Requested IrDA name: \"%s\", ", self->rname);      len += sprintf(buf+len, "daddr: %08x, ", self->rdaddr);      len += sprintf(buf+len, "saddr: %08x\n", self->rsaddr);      /* Second, get all the PPP info */      len += sprintf(buf+len, "	PPP state: %s",		 (self->ppp_open ? "registered" : "unregistered"));      if(self->ppp_open)	{	  len += sprintf(buf+len, ", unit: ppp%d",			 ppp_unit_number(&self->chan));	  len += sprintf(buf+len, ", channel: %d",			 ppp_channel_index(&self->chan));	  len += sprintf(buf+len, ", mru: %d",			 self->mru);	  /* Maybe add self->flags ? Later... */	}      /* Then, get all the IrDA specific info... */      if(self->ttp_open)	state = "connected";      else	if(self->tsap != NULL)	  state = "connecting";	else	  if(self->iriap != NULL)	    state = "searching";	  else	    if(self->ttp_connect)	      state = "weird";	    else	      state = "idle";      len += sprintf(buf+len, "\n	IrDA state: %s, ", state);      len += sprintf(buf+len, "daddr: %08x, ", self->daddr);      len += sprintf(buf+len, "stsap_sel: %02x, ", self->stsap_sel);      len += sprintf(buf+len, "dtsap_sel: %02x\n", self->dtsap_sel);      /* Next socket, please... */      self = (irnet_socket *) hashbin_get_next(irnet_server.list);    }  /* Spin lock end */  spin_unlock_irqrestore(&irnet_server.spinlock, flags);  return len;}#endif /* PROC_FS *//********************** CONFIGURATION/CLEANUP **********************//* * Initialisation and teardown of the IrDA part, called at module * insertion and removal... *//*------------------------------------------------------------------*//* * Prepare the IrNET layer for operation... */intirda_irnet_init(void){  int		err = 0;  DENTER(MODULE_TRACE, "()\n");  /* Pure paranoia - should be redundant */  memset(&irnet_server, 0, sizeof(struct irnet_root));  /* Setup start of irnet instance list */  irnet_server.list = hashbin_new(HB_NOLOCK);   DABORT(irnet_server.list == NULL, -ENOMEM,	 MODULE_ERROR, "Can't allocate hashbin!\n");  /* Init spinlock for instance list */  spin_lock_init(&irnet_server.spinlock);  /* Initialise control channel */  init_waitqueue_head(&irnet_events.rwait);  irnet_events.index = 0;  /* Init spinlock for event logging */  spin_lock_init(&irnet_events.spinlock);#ifdef CONFIG_PROC_FS  /* Add a /proc file for irnet infos */  create_proc_info_entry("irnet", 0, proc_irda, irnet_proc_read);#endif /* CONFIG_PROC_FS */  /* Setup the IrNET server */  err = irnet_setup_server();  if(!err)    /* We are no longer functional... */    irnet_server.running = 1;  DEXIT(MODULE_TRACE, "\n");  return err;}/*------------------------------------------------------------------*//* * Cleanup at exit... */voidirda_irnet_cleanup(void){  DENTER(MODULE_TRACE, "()\n");  /* We are no longer there... */  irnet_server.running = 0;#ifdef CONFIG_PROC_FS  /* Remove our /proc file */  remove_proc_entry("irnet", proc_irda);#endif /* CONFIG_PROC_FS */  /* Remove our IrNET server from existence */  irnet_destroy_server();  /* Remove all instances of IrNET socket still present */  hashbin_delete(irnet_server.list, (FREE_FUNC) irda_irnet_destroy);  DEXIT(MODULE_TRACE, "\n");}

⌨️ 快捷键说明

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