Esempio n. 1
0
int
irda_irnet_connect(irnet_socket *	self)
{
  int		err;

  DENTER(IRDA_SOCK_TRACE, "(self=0x%p)\n", self);

  
  if(test_and_set_bit(0, &self->ttp_connect))
    DRETURN(-EBUSY, IRDA_SOCK_INFO, "Already connecting...\n");
  if((self->iriap != NULL) || (self->tsap != NULL))
    DERROR(IRDA_SOCK_ERROR, "Socket not cleaned up...\n");

  
  if((irnet_server.running) && (self->q.q_next == NULL))
    {
      spin_lock_bh(&irnet_server.spinlock);
      hashbin_insert(irnet_server.list, (irda_queue_t *) self, 0, self->rname);
      spin_unlock_bh(&irnet_server.spinlock);
      DEBUG(IRDA_SOCK_INFO, "Inserted ``%s'' in hashbin...\n", self->rname);
    }

  
  if((self->rdaddr == DEV_ADDR_ANY) && (self->rname[0] == '\0'))
    {
      
      if((err = irnet_discover_daddr_and_lsap_sel(self)) != 0)
	DRETURN(err, IRDA_SOCK_INFO, "auto-connect failed!\n");
      
    }
  else
    {
      
      if(self->rdaddr == DEV_ADDR_ANY)
	{
	  if((err = irnet_dname_to_daddr(self)) != 0)
	    DRETURN(err, IRDA_SOCK_INFO, "name connect failed!\n");
	}
      else
	
	self->daddr = self->rdaddr;

      
      irnet_find_lsap_sel(self);
      
    }

  
  DEXIT(IRDA_SOCK_TRACE, "\n");
  return(0);
}
Esempio n. 2
0
/*
 * Connect to the other side :
 *	o convert device name to an address
 *	o find the socket number (dlsap)
 *	o Establish the connection
 */
int
irda_irnet_connect(irnet_socket *	self)
{
  int		err;

  DENTER(IRDA_SOCK_TRACE, "(self=0x%X)\n", (unsigned int) self);

  /* Check if we have opened a local TSAP :
   * If we have already opened a TSAP, it means that either we are already
   * connected or in the process of doing so... */
  if(self->tsap != NULL)
    DRETURN(-EBUSY, IRDA_SOCK_INFO, "Already connecting...\n");

  /* Insert ourselves in the hashbin so that the IrNET server can find us.
   * Notes : 4th arg is string of 32 char max and must be null terminated
   *	     When 4th arg is used (string), 3rd arg isn't (int)
   *	     Can't re-insert (MUST remove first) so check for that... */
  if((irnet_server.running) && (self->q.q_next == NULL))
    {
      unsigned long		flags;
      spin_lock_irqsave(&irnet_server.spinlock, flags);
      hashbin_insert(irnet_server.list, (irda_queue_t *) self, 0, self->rname);
      spin_unlock_irqrestore(&irnet_server.spinlock, flags);
      DEBUG(IRDA_SOCK_INFO, "Inserted ``%s'' in hashbin...\n", self->rname);
    }

  /* If we don't have anything (no address, no name) */
  if((self->raddr == DEV_ADDR_ANY) && (self->rname[0] == '\0'))
    {
      /* Try to find a suitable address */
      if((err = irnet_discover_daddr_and_lsap_sel(self)) != 0) 
	DRETURN(err, IRDA_SOCK_INFO, "auto-connect failed!\n");
    }
  else
    {
      /* If we have only the name (no address), try to get an address */
      if(self->raddr == DEV_ADDR_ANY)
	{
	  if((err = irnet_dname_to_daddr(self)) != 0)
	    DRETURN(err, IRDA_SOCK_INFO, "name-connect failed!\n");
	}
      else
	/* Use the requested destination address */
	self->daddr = self->raddr;

      /* Query remote LM-IAS to find LSAP selector */
      if((err = irnet_find_lsap_sel(self)) != 0)
	DRETURN(err, IRDA_SOCK_INFO, "connect failed!\n");
    }
  DEBUG(IRDA_SOCK_INFO, "daddr = %08x, lsap = %d, starting IrTTP connection\n",
	self->daddr, self->dtsap_sel);

  /* Open a local TSAP (an IrTTP instance) */
  err = irnet_open_tsap(self);
  DABORT(err != 0, err, IRDA_SOCK_ERROR, "connect aborted!\n");

  /* Connect to remote device */
  err = irttp_connect_request(self->tsap, self->dtsap_sel, 
			      self->saddr, self->daddr, NULL, 
			      self->max_sdu_size_rx, NULL);
  DABORT(err != 0, err, IRDA_SOCK_ERROR, "connect aborted!\n");

  DEXIT(IRDA_SOCK_TRACE, "\n");
  return(0);
}
Esempio n. 3
0
/*
 * Function irnet_discover_daddr_and_lsap_sel (self)
 *
 *    This try to find a device with the requested service.
 *
 * It basically look into the discovery log. For each address in the list,
 * it queries the LM-IAS of the device to find if this device offer
 * the requested service.
 * If there is more than one node supporting the service, we complain
 * to the user (it should move devices around).
 * The, we set both the destination address and the lsap selector to point
 * on the service on the unique device we have found.
 *
 * Note : this function fails if there is more than one device in range,
 * because IrLMP doesn't disconnect the LAP when the last LSAP is closed.
 * Moreover, we would need to wait the LAP disconnection...
 */
static inline int
irnet_discover_daddr_and_lsap_sel(irnet_socket *	self)
{
  struct irda_device_info *discoveries;	/* Copy of the discovery log */
  int	number;			/* Number of nodes in the log */
  int	i;
  int	err = -ENETUNREACH;
  __u32	daddr = DEV_ADDR_ANY;	/* Address we found the service on */
  __u8	dtsap_sel = 0x0;	/* TSAP associated with it */

  DENTER(IRDA_SR_TRACE, "(self=0x%X)\n", (unsigned int) self);

  /* Ask lmp for the current discovery log
   * Note : we have to use irlmp_get_discoveries(), as opposed
   * to play with the cachelog directly, because while we are
   * making our ias query, le log might change... */
  discoveries = irlmp_get_discoveries(&number, self->mask);
  /* Check if the we got some results */
  if (discoveries == NULL)
    DRETURN(-ENETUNREACH, IRDA_SR_INFO, "Cachelog empty...\n");

  /* 
   * Now, check all discovered devices (if any), and connect
   * client only about the services that the client is
   * interested in...
   */
  for(i = 0; i < number; i++)
    {
      /* Try the address in the log */
      self->daddr = discoveries[i].daddr;
      self->saddr = 0x0;
      DEBUG(IRDA_SR_INFO, "trying daddr = %08x\n", self->daddr);

      /* Query remote LM-IAS for this service */
      err = irnet_find_lsap_sel(self);
      switch(err)
	{
	case 0:
	  /* We found the requested service */
	  if(daddr != DEV_ADDR_ANY)
	    {
	      DEBUG(IRDA_SR_INFO, "More than one device in range supports IrNET...\n");
	    }
	  else
	    {
	      /* First time we found that one, save it ! */
	      daddr = self->daddr;
	      dtsap_sel = self->dtsap_sel;
	    }
	  break;
	case -EADDRNOTAVAIL:
	  /* Requested service simply doesn't exist on this node */
	  break;
	default:
	  /* Something bad did happen :-( */
	  DERROR(IRDA_SR_ERROR, "unexpected IAS query failure\n");
	  self->daddr = DEV_ADDR_ANY;
	  kfree(discoveries);
	  return(-EHOSTUNREACH);
	  break;
	}
    }
  /* Cleanup our copy of the discovery log */
  kfree(discoveries);

  /* Check out what we found */
  if(daddr == DEV_ADDR_ANY)
    {
      self->daddr = DEV_ADDR_ANY;
      DEXIT(IRDA_SR_INFO, "cannot discover IrNET in any device !!!\n");
      return(-EADDRNOTAVAIL);
    }

  /* Revert back to discovered device & service */
  self->daddr = daddr;
  self->saddr = 0x0;
  self->dtsap_sel = dtsap_sel;

  DEBUG(IRDA_SR_INFO, "discovered IrNET at address %08x\n", self->daddr);
  DEXIT(IRDA_SR_TRACE, "\n");

  return 0;
}