cregit-Linux how code gets into the kernel

Release 4.7 net/irda/irnet/irnet_irda.c

Directory: net/irda/irnet
/*
 *      IrNET protocol module : Synchronous PPP over an IrDA socket.
 *
 *              Jean II - HPL `00 - <jt@hpl.hp.com>
 *
 * This file implement the IRDA interface of IrNET.
 * Basically, we sit on top of IrTTP. We set up IrTTP, IrIAS properly,
 * and exchange frames with IrTTP.
 */

#include "irnet_irda.h"		/* Private header */
#include <linux/sched.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <asm/unaligned.h>

/*
 * PPP disconnect work: we need to make sure we're in
 * process context when calling ppp_unregister_channel().
 */

static void irnet_ppp_disconnect(struct work_struct *work) { irnet_socket * self = container_of(work, irnet_socket, disconnect_work); if (self == NULL) return; /* * If we were connected, cleanup & close the PPP * channel, which will kill pppd (hangup) and the rest. */ if (self->ppp_open && !self->ttp_open && !self->ttp_connect) { ppp_unregister_channel(&self->chan); self->ppp_open = 0; } }

Contributors

PersonTokensPropCommitsCommitProp
samuel ortizsamuel ortiz64100.00%1100.00%
Total64100.00%1100.00%

/************************* CONTROL CHANNEL *************************/ /* * When ppp is not active, /dev/irnet act as a control channel. * Writing allow to set up the IrDA destination of the IrNET channel, * and any application may be read events happening on IrNET... */ /*------------------------------------------------------------------*/ /* * Post an event to the control channel... * Put the event in the log, and then wait all process blocked on read * so they can read the log... */
static void irnet_post_event(irnet_socket * ap, irnet_event event, __u32 saddr, __u32 daddr, char * name, __u16 hints) { int index; /* In the log */ DENTER(CTRL_TRACE, "(ap=0x%p, event=%d, daddr=%08x, name=``%s'')\n", ap, event, daddr, name); /* Protect this section via spinlock. * Note : as we are the only event producer, we only need to exclude * ourself when touching the log, which is nice and easy. */ spin_lock_bh(&irnet_events.spinlock); /* Copy the event in the log */ index = irnet_events.index; irnet_events.log[index].event = event; irnet_events.log[index].daddr = daddr; irnet_events.log[index].saddr = saddr; /* Try to copy IrDA nickname */ if(name) strcpy(irnet_events.log[index].name, name); else irnet_events.log[index].name[0] = '\0'; /* Copy hints */ irnet_events.log[index].hints.word = hints; /* Try to get ppp unit number */ if((ap != (irnet_socket *) NULL) && (ap->ppp_open)) irnet_events.log[index].unit = ppp_unit_number(&ap->chan); else irnet_events.log[index].unit = -1; /* Increment the index * Note that we increment the index only after the event is written, * to make sure that the readers don't get garbage... */ irnet_events.index = (index + 1) % IRNET_MAX_EVENTS; DEBUG(CTRL_INFO, "New event index is %d\n", irnet_events.index); /* Spin lock end */ spin_unlock_bh(&irnet_events.spinlock); /* Now : wake up everybody waiting for events... */ wake_up_interruptible_all(&irnet_events.rwait); DEXIT(CTRL_TRACE, "\n"); }

Contributors

PersonTokensPropCommitsCommitProp
pre-gitpre-git20284.17%120.00%
jean tourrilhesjean tourrilhes197.92%240.00%
linus torvaldslinus torvalds187.50%120.00%
david s. millerdavid s. miller10.42%120.00%
Total240100.00%5100.00%

/************************* IRDA SUBROUTINES *************************/ /* * These are a bunch of subroutines called from other functions * down there, mostly common code or to improve readability... * * Note : we duplicate quite heavily some routines of af_irda.c, * because our input structure (self) is quite different * (struct irnet instead of struct irda_sock), which make sharing * the same code impossible (at least, without templates). */ /*------------------------------------------------------------------*/ /* * Function irda_open_tsap (self) * * Open local Transport Service Access Point (TSAP) * * Create a IrTTP instance for us and set all the IrTTP callbacks. */
static inline int irnet_open_tsap(irnet_socket * self) { notify_t notify; /* Callback structure */ DENTER(IRDA_SR_TRACE, "(self=0x%p)\n", self); DABORT(self->tsap != NULL, -EBUSY, IRDA_SR_ERROR, "Already busy !\n"); /* Initialize IrTTP callbacks to be used by the IrDA stack */ irda_notify_init(&notify); notify.connect_confirm = irnet_connect_confirm; notify.connect_indication = irnet_connect_indication; notify.disconnect_indication = irnet_disconnect_indication; notify.data_indication = irnet_data_indication; /*notify.udata_indication = NULL;*/ notify.flow_indication = irnet_flow_indication; notify.status_indication = irnet_status_indication; notify.instance = self; strlcpy(notify.name, IRNET_NOTIFY_NAME, sizeof(notify.name)); /* Open an IrTTP instance */ self->tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT, &notify); DABORT(self->tsap == NULL, -ENOMEM, IRDA_SR_ERROR, "Unable to allocate TSAP !\n"); /* Remember which TSAP selector we actually got */ self->stsap_sel = self->tsap->stsap_sel; DEXIT(IRDA_SR_TRACE, " - tsap=0x%p, sel=0x%X\n", self->tsap, self->stsap_sel); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
pre-gitpre-git15794.58%133.33%
ben collinsben collins74.22%133.33%
david s. millerdavid s. miller21.20%133.33%
Total166100.00%3100.00%

/*------------------------------------------------------------------*/ /* * Function irnet_ias_to_tsap (self, result, value) * * Examine an IAS object and extract TSAP * * We do an IAP query to find the TSAP associated with the IrNET service. * When IrIAP pass us the result of the query, this function look at * the return values to check for failures and extract the TSAP if * possible. * Also deallocate value * The failure is in self->errno * Return TSAP or -1 */
static inline __u8 irnet_ias_to_tsap(irnet_socket * self, int result, struct ias_value * value) { __u8 dtsap_sel = 0; /* TSAP we are looking for */ DENTER(IRDA_SR_TRACE, "(self=0x%p)\n", self); /* By default, no error */ self->errno = 0; /* Check if request succeeded */ switch(result) { /* Standard errors : service not available */ case IAS_CLASS_UNKNOWN: case IAS_ATTRIB_UNKNOWN: DEBUG(IRDA_SR_INFO, "IAS object doesn't exist ! (%d)\n", result); self->errno = -EADDRNOTAVAIL; break; /* Other errors, most likely IrDA stack failure */ default : DEBUG(IRDA_SR_INFO, "IAS query failed ! (%d)\n", result); self->errno = -EHOSTUNREACH; break; /* Success : we got what we wanted */ case IAS_SUCCESS: break; } /* Check what was returned to us */ if(value != NULL) { /* What type of argument have we got ? */ switch(value->type) { case IAS_INTEGER: DEBUG(IRDA_SR_INFO, "result=%d\n", value->t.integer); if(value->t.integer != -1) /* Get the remote TSAP selector */ dtsap_sel = value->t.integer; else self->errno = -EADDRNOTAVAIL; break; default: self->errno = -EADDRNOTAVAIL; DERROR(IRDA_SR_ERROR, "bad type ! (0x%X)\n", value->type); break; } /* Cleanup */ irias_delete_value(value); } else /* value == NULL */ { /* Nothing returned to us - usually result != SUCCESS */ if(!(self->errno)) { DERROR(IRDA_SR_ERROR, "IrDA bug : result == SUCCESS && value == NULL\n"); self->errno = -EHOSTUNREACH; } } DEXIT(IRDA_SR_TRACE, "\n"); /* Return the TSAP */ return dtsap_sel; }

Contributors

PersonTokensPropCommitsCommitProp
pre-gitpre-git12354.42%133.33%
linus torvaldslinus torvalds10245.13%133.33%
david s. millerdavid s. miller10.44%133.33%
Total226100.00%3100.00%

/*------------------------------------------------------------------*/ /* * Function irnet_find_lsap_sel (self) * * Try to lookup LSAP selector in remote LM-IAS * * Basically, we start a IAP query, and then go to sleep. When the query * return, irnet_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 inline int irnet_find_lsap_sel(irnet_socket * self) { DENTER(IRDA_SR_TRACE, "(self=0x%p)\n", self); /* This should not happen */ DABORT(self->iriap, -EBUSY, IRDA_SR_ERROR, "busy with a previous query.\n"); /* Create an IAP instance, will be closed in irnet_getvalue_confirm() */ self->iriap = iriap_open(LSAP_ANY, IAS_CLIENT, self, irnet_getvalue_confirm); /* Treat unexpected signals as disconnect */ self->errno = -EHOSTUNREACH; /* Query remote LM-IAS */ iriap_getvaluebyclass_request(self->iriap, self->rsaddr, self->daddr, IRNET_SERVICE_NAME, IRNET_IAS_VALUE); /* The above request is non-blocking. * After a while, IrDA will call us back in irnet_getvalue_confirm() * We will then call irnet_ias_to_tsap() and finish the * connection procedure */ DEXIT(IRDA_SR_TRACE, "\n"); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
linus torvaldslinus torvalds4853.33%133.33%
pre-gitpre-git4145.56%133.33%
david s. millerdavid s. miller11.11%133.33%
Total90100.00%3100.00%

/*------------------------------------------------------------------*/ /* * Function irnet_connect_tsap (self) * * Initialise the TTP socket and initiate TTP connection * */
static inline int irnet_connect_tsap(irnet_socket * self) { int err; DENTER(IRDA_SR_TRACE, "(self=0x%p)\n", self); /* Open a local TSAP (an IrTTP instance) */ err = irnet_open_tsap(self); if(err != 0) { clear_bit(0, &self->ttp_connect); DERROR(IRDA_SR_ERROR, "connect aborted!\n"); return err; } /* Connect to remote device */ err = irttp_connect_request(self->tsap, self->dtsap_sel, self->rsaddr, self->daddr, NULL, self->max_sdu_size_rx, NULL); if(err != 0) { clear_bit(0, &self->ttp_connect); DERROR(IRDA_SR_ERROR, "connect aborted!\n"); return err; } /* The above call is non-blocking. * After a while, the IrDA stack will either call us back in * irnet_connect_confirm() or irnet_disconnect_indication() * See you there ;-) */ DEXIT(IRDA_SR_TRACE, "\n"); return err; }

Contributors

PersonTokensPropCommitsCommitProp
linus torvaldslinus torvalds10783.59%250.00%
pre-gitpre-git2015.62%125.00%
david s. millerdavid s. miller10.78%125.00%
Total128100.00%4100.00%

/*------------------------------------------------------------------*/ /* * Function irnet_discover_next_daddr (self) * * Query the IrNET TSAP of the next device in the log. * * Used in the TSAP discovery procedure. */
static inline int irnet_discover_next_daddr(irnet_socket * self) { /* Close the last instance of IrIAP, and open a new one. * We can't reuse the IrIAP instance in the IrIAP callback */ if(self->iriap) { iriap_close(self->iriap); self->iriap = NULL; } /* Create a new IAP instance */ self->iriap = iriap_open(LSAP_ANY, IAS_CLIENT, self, irnet_discovervalue_confirm); if(self->iriap == NULL) return -ENOMEM; /* Next discovery - before the call to avoid races */ self->disco_index++; /* Check if we have one more address to try */ if(self->disco_index < self->disco_number) { /* Query remote LM-IAS */ iriap_getvaluebyclass_request(self->iriap, self->discoveries[self->disco_index].saddr, self->discoveries[self->disco_index].daddr, IRNET_SERVICE_NAME, IRNET_IAS_VALUE); /* The above request is non-blocking. * After a while, IrDA will call us back in irnet_discovervalue_confirm() * We will then call irnet_ias_to_tsap() and come back here again... */ return 0; } else return 1; }

Contributors

PersonTokensPropCommitsCommitProp
linus torvaldslinus torvalds8872.13%133.33%
pre-gitpre-git2218.03%133.33%
jean tourrilhesjean tourrilhes129.84%133.33%
Total122100.00%3100.00%

/*------------------------------------------------------------------*/ /* * Function irnet_discover_daddr_and_lsap_sel (self) * * This try to find a device with the requested service. * * Initiate a TSAP discovery procedure. * 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). * If we find one node which have the requested TSAP, we connect to it. * * This function just start the whole procedure. It request the discovery * log and submit the first IAS query. * The bulk of the job is handled in irnet_discovervalue_confirm() * * Note : this procedure fails if there is more than one device in range * on the same dongle, 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) { int ret; DENTER(IRDA_SR_TRACE, "(self=0x%p)\n", self); /* Ask lmp for the current discovery log */ self->discoveries = irlmp_get_discoveries(&self->disco_number, self->mask, DISCOVERY_DEFAULT_SLOTS); /* Check if the we got some results */ if(self->discoveries == NULL) { self->disco_number = -1; clear_bit(0, &self->ttp_connect); DRETURN(-ENETUNREACH, IRDA_SR_INFO, "No Cachelog...\n"); } DEBUG(IRDA_SR_INFO, "Got the log (0x%p), size is %d\n", self->discoveries, self->disco_number); /* Start with the first discovery */ self->disco_index = -1; self->daddr = DEV_ADDR_ANY; /* This will fail if the log is empty - this is non-blocking */ ret = irnet_discover_next_daddr(self); if(ret) { /* Close IAP */ if(self->iriap) iriap_close(self->iriap); self->iriap = NULL; /* Cleanup our copy of the discovery log */ kfree(self->discoveries); self->discoveries = NULL; clear_bit(0, &self->ttp_connect); DRETURN(-ENETUNREACH, IRDA_SR_INFO, "Cachelog empty...\n"); } /* Follow me in irnet_discovervalue_confirm() */ DEXIT(IRDA_SR_TRACE, "\n"); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
linus torvaldslinus torvalds14175.00%350.00%
pre-gitpre-git3920.74%116.67%
jean tourrilhesjean tourrilhes63.19%116.67%
david s. millerdavid s. miller21.06%116.67%
Total188100.00%6100.00%

/*------------------------------------------------------------------*/ /* * Function irnet_dname_to_daddr (self) * * Convert an IrDA nickname to a valid IrDA address * * It basically look into the discovery log until there is a match. */
static inline int irnet_dname_to_daddr(irnet_socket * self) { struct irda_device_info *discoveries; /* Copy of the discovery log */ int number; /* Number of nodes in the log */ int i; DENTER(IRDA_SR_TRACE, "(self=0x%p)\n", self); /* Ask lmp for the current discovery log */ discoveries = irlmp_get_discoveries(&number, 0xffff, DISCOVERY_DEFAULT_SLOTS); /* 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++) { /* Does the name match ? */ if(!strncmp(discoveries[i].info, self->rname, NICKNAME_MAX_LEN)) { /* Yes !!! Get it.. */ self->daddr = discoveries[i].daddr; DEBUG(IRDA_SR_INFO, "discovered device ``%s'' at address 0x%08x.\n", self->rname, self->daddr); kfree(discoveries); DEXIT(IRDA_SR_TRACE, "\n"); return 0; } } /* No luck ! */ DEBUG(IRDA_SR_INFO, "cannot discover device ``%s'' !!!\n", self->rname); kfree(discoveries); return -EADDRNOTAVAIL; }

Contributors

PersonTokensPropCommitsCommitProp
pre-gitpre-git16097.56%125.00%
linus torvaldslinus torvalds21.22%125.00%
hideaki yoshifujihideaki yoshifuji10.61%125.00%
david s. millerdavid s. miller10.61%125.00%
Total164100.00%4100.00%

/************************* SOCKET ROUTINES *************************/ /* * This are the main operations on IrNET sockets, basically to create * and destroy IrNET sockets. These are called from the PPP part... */ /*------------------------------------------------------------------*/ /* * Create a IrNET instance : just initialise some parameters... */
int irda_irnet_create(irnet_socket * self) { DENTER(IRDA_SOCK_TRACE, "(self=0x%p)\n", self); self->magic = IRNET_MAGIC; /* Paranoia */ self->ttp_open = 0; /* Prevent higher layer from accessing IrTTP */ self->ttp_connect = 0; /* Not connecting yet */ self->rname[0] = '\0'; /* May be set via control channel */ self->rdaddr = DEV_ADDR_ANY; /* May be set via control channel */ self->rsaddr = DEV_ADDR_ANY; /* May be set via control channel */ self->daddr = DEV_ADDR_ANY; /* Until we get connected */ self->saddr = DEV_ADDR_ANY; /* Until we get connected */ self->max_sdu_size_rx = TTP_SAR_UNBOUND; /* Register as a client with IrLMP */ self->ckey = irlmp_register_client(0, NULL, NULL, NULL); #ifdef DISCOVERY_NOMASK self->mask = 0xffff; /* For W2k compatibility */ #else /* DISCOVERY_NOMASK */ self->mask = irlmp_service_to_hint(S_LAN); #endif /* DISCOVERY_NOMASK */ self->tx_flow = FLOW_START; /* Flow control from IrTTP */ INIT_WORK(&self->disconnect_work, irnet_ppp_disconnect); DEXIT(IRDA_SOCK_TRACE, "\n"); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
pre-gitpre-git12280.79%116.67%
linus torvaldslinus torvalds1811.92%350.00%
samuel ortizsamuel ortiz106.62%116.67%
david s. millerdavid s. miller10.66%116.67%
Total151100.00%6100.00%

/*------------------------------------------------------------------*/ /* * Connect to the other side : * o convert device name to an address * o find the socket number (dlsap) * o Establish the connection * * Note : We no longer mimic af_irda. The IAS query for finding the TSAP * is done asynchronously, like the TTP connection. This allow us to * call this function from any context (not only process). * The downside is that following what's happening in there is tricky * because it involve various functions all over the place... */
int irda_irnet_connect(irnet_socket * self) { int err; DENTER(IRDA_SOCK_TRACE, "(self=0x%p)\n", self); /* Check if we are already trying to connect. * Because irda_irnet_connect() can be called directly by pppd plus * packet retries in ppp_generic and connect may take time, plus we may * race with irnet_connect_indication(), we need to be careful there... */ 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"); /* 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)) { 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 we don't have anything (no address, no name) */ if((self->rdaddr == 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"); /* In most cases, the call above is non-blocking */ } else { /* If we have only the name (no address), try to get an address */ if(self->rdaddr == 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->rdaddr; /* Query remote LM-IAS to find LSAP selector */ irnet_find_lsap_sel(self); /* The above call is non blocking */ } /* At this point, we are waiting for the IrDA stack to call us back, * or we have already failed. * We will finish the connection procedure in irnet_connect_tsap(). */ DEXIT(IRDA_SOCK_TRACE, "\n"); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
pre-gitpre-git20582.66%120.00%
linus torvaldslinus torvalds4016.13%240.00%
jean tourrilhesjean tourrilhes20.81%120.00%
david s. millerdavid s. miller10.40%120.00%
Total248100.00%5100.00%

/*------------------------------------------------------------------*/ /* * Function irda_irnet_destroy(self) * * Destroy irnet instance * * Note : this need to be called from a process context. */
void irda_irnet_destroy(irnet_socket * self) { DENTER(IRDA_SOCK_TRACE, "(self=0x%p)\n", self); if(self == NULL) return; /* Remove ourselves from hashbin (if we are queued in hashbin) * Note : `irnet_server.running' protect us from calls in hashbin_delete() */ if((irnet_server.running) && (self->q.q_next != NULL)) { struct irnet_socket * entry; DEBUG(IRDA_SOCK_INFO, "Removing from hash..\n"); spin_lock_bh(&irnet_server.spinlock); entry = hashbin_remove_this(irnet_server.list, (irda_queue_t *) self); self->q.q_next = NULL; spin_unlock_bh(&irnet_server.spinlock); DASSERT(entry == self, , IRDA_SOCK_ERROR, "Can't remove from hash.\n"); } /* If we were connected, post a message */ if(test_bit(0, &self->ttp_open)) { /* Note : as the disconnect comes from ppp_generic, the unit number * doesn't exist anymore when we post the event, so we need to pass * NULL as the first arg... */ irnet_post_event(NULL, IRNET_DISCONNECT_TO, self->saddr, self->daddr, self->rname, 0); } /* Prevent various IrDA callbacks from messing up things * Need to be first */ clear_bit(0, &self->ttp_connect); /* Prevent higher layer from accessing IrTTP */ clear_bit(0, &self->ttp_open); /* Unregister with IrLMP */ irlmp_unregister_client(self->ckey); /* Unregister with LM-IAS */ if(self->iriap) { iriap_close(self->iriap); self->iriap = NULL; } /* Cleanup eventual discoveries from connection attempt or control channel */ if(self->discoveries != NULL) { /* Cleanup our copy of the discovery log */ kfree(self->discoveries); self->discoveries = NULL; } /* Close our IrTTP connection */ if(self->tsap) { DEBUG(IRDA_SOCK_INFO, "Closing our TTP connection.\n"); irttp_disconnect_request(self->tsap, NULL, P_NORMAL); irttp_close_tsap(self->tsap); self->tsap = NULL; } self->stsap_sel = 0; DEXIT(IRDA_SOCK_TRACE, "\n"); }

Contributors

PersonTokensPropCommitsCommitProp
pre-gitpre-git17965.09%114.29%
linus torvaldslinus torvalds9032.73%228.57%
jean tourrilhesjean tourrilhes51.82%342.86%
david s. millerdavid s. miller10.36%114.29%
Total275100.00%7100.00%

/************************** SERVER SOCKET **************************/ /* * The IrNET service is composed of one server socket and a variable * number of regular IrNET sockets. The server socket is supposed to * handle incoming connections and redirect them to one IrNET sockets. * It's a superset of the regular IrNET socket, but has a very distinct * behaviour... */ /*------------------------------------------------------------------*/ /* * Function irnet_daddr_to_dname (self) * * Convert an IrDA address to a IrDA nickname * * It basically look into the discovery log until there is a match. */
static inline int irnet_daddr_to_dname(irnet_socket * self) { struct irda_device_info *discoveries; /* Copy of the discovery log */ int number; /* Number of nodes in the log */ int i; DENTER(IRDA_SERV_TRACE, "(self=0x%p)\n", self); /* Ask lmp for the current discovery log */ discoveries = irlmp_get_discoveries(&number, 0xffff, DISCOVERY_DEFAULT_SLOTS); /* Check if the we got some results */ if (discoveries == NULL) DRETURN(-ENETUNREACH, IRDA_SERV_INFO, "Cachelog empty...\n"); /* Now, check all discovered devices (if any) */ for(i = 0; i < number; i++) { /* Does the name match ? */ if(discoveries[i].daddr == self->daddr) { /* Yes !!! Get it.. */ strlcpy(self->rname, discoveries[i].info, sizeof(self->rname)); self->rname[sizeof(self->rname) - 1] = '\0'; DEBUG(IRDA_SERV_INFO, "Device 0x%08x is in fact ``%s''.\n", self->daddr, self->rname); kfree(discoveries); DEXIT(IRDA_SERV_TRACE, "\n"); return 0; } } /* No luck ! */ DEXIT(IRDA_SERV_INFO, ": cannot discover device 0x%08x !!!\n", self->daddr); kfree(discoveries); return -EADDRNOTAVAIL; }

Contributors

PersonTokensPropCommitsCommitProp
pre-gitpre-git16790.76%120.00%
ben collinsben collins73.80%120.00%
david bindermandavid binderman73.80%120.00%
linus torvaldslinus torvalds21.09%120.00%
david s. millerdavid s. miller10.54%120.00%
Total184100.00%5100.00%

/*------------------------------------------------------------------*/ /* * Function irda_find_socket (self) * * Find the correct IrNET socket * * Look into the list of IrNET sockets and finds one with the right * properties... */
static inline irnet_socket * irnet_find_socket(irnet_socket * self) { irnet_socket * new = (irnet_socket *) NULL; int err; DENTER(IRDA_SERV_TRACE, "(self=0x%p)\n", self); /* Get the addresses of the requester */ self->daddr = irttp_get_daddr(self->tsap); self->saddr = irttp_get_saddr(self->tsap); /* Try to get the IrDA nickname of the requester */ err = irnet_daddr_to_dname(self); /* Protect access to the instance list */ spin_lock_bh(&irnet_server.spinlock); /* So now, try to get an socket having specifically * requested that nickname */ if(err == 0) { new = (irnet_socket *) hashbin_find(irnet_server.list, 0, self->rname); if(new) DEBUG(IRDA_SERV_INFO, "Socket 0x%p matches rname ``%s''.\n", new, new->rname); } /* If no name matches, try to find an socket by the destination address */ /* It can be either the requested destination address (set via the * control channel), or the current destination address if the * socket is in the middle of a connection request */ if(new == (irnet_socket *) NULL) { new = (irnet_socket *) hashbin_get_first(irnet_server.list); while(new !=(irnet_socket *) NULL) { /* Does it have the same address ? */ if((new->rdaddr == self->daddr) || (new->daddr == self->daddr)) { /* Yes !!! Get it.. */ DEBUG(IRDA_SERV_INFO, "Socket 0x%p matches daddr %#08x.\n", new, self->daddr); break; } new = (irnet_socket *) hashbin_get_next(irnet_server.list); } } /* If we don't have any socket, get the first unconnected socket */ if(new == (irnet_socket *) NULL) { new = (irnet_socket *) hashbin_get_first(irnet_server.list); while(new !=(irnet_socket *) NULL) { /* Is it available ? */ if(!(test_bit(0, &new->ttp_open)) && (new->rdaddr == DEV_ADDR_ANY) && (new->rname[0] == '\0') && (new->ppp_open)) { /* Yes !!! Get it.. */ DEBUG(IRDA_SERV_INFO, "Socket 0x%p is free.\n", new); break; } new = (irnet_socket *) hashbin_get_next(irnet_server.list); } } /* Spin lock end */ spin_unlock_bh(&irnet_server.spinlock); DEXIT(IRDA_SERV_TRACE, " - new = 0x%p\n", new); return new; }

Contributors

PersonTokensPropCommitsCommitProp
pre-gitpre-git31091.99%120.00%
linus torvaldslinus torvalds205.93%240.00%
david s. millerdavid s. miller51.48%120.00%
jean tourrilhesjean tourrilhes20.59%120.00%
Total337100.00%5100.00%

/*------------------------------------------------------------------*/ /* * Function irda_connect_socket (self) * * Connect an incoming connection to the socket * */
static inline int irnet_connect_socket(irnet_socket * server, irnet_socket * new, struct qos_info * qos, __u32 max_sdu_size, __u8 max_header_size) { DENTER(IRDA_SERV_TRACE, "(server=0x%p, new=0x%p)\n", server, new); /* Now attach up the new socket */ new->tsap = irttp_dup(server->tsap, new); DABORT(new->tsap == NULL, -1, IRDA_SERV_ERROR, "dup failed!\n"); /* Set up all the relevant parameters on the new socket */ new->stsap_sel = new->tsap->stsap_sel; new->dtsap_sel = new->tsap->dtsap_sel; new->saddr = irttp_get_saddr(new->tsap); new->daddr = irttp_get_daddr(new->tsap); new->max_header_size = max_header_size; new->max_sdu_size_tx = max_sdu_size; new->max_data_size = max_sdu_size; #ifdef STREAM_COMPAT /* If we want to receive "stream sockets" */ if(max_sdu_size == 0) new->max_data_size = irttp_get_max_seg_size(new->tsap); #endif /* STREAM_COMPAT */ /* Clean up the original one to keep it in listen state */ irttp_listen(server->tsap); /* Send a connection response on the new socket */ irttp_connect_response(new->tsap, new->max_sdu_size_rx, NULL); /* Allow PPP to send its junk over the new socket... */ set_bit(0, &new->ttp_open); /* Not connecting anymore, and clean up last possible remains * of connection attempts on the socket */ clear_bit(0, &new->ttp_connect); if(new->iriap) { iriap_close(new->iriap); new->iriap = NULL; } if(new->discoveries != NULL) { kfree(new->discoveries); new->discoveries = NULL; } #ifdef CONNECT_INDIC_KICK /* As currently we don't block packets in ppp_irnet_send() while passive, * this is not really needed... * Also, not doing it give IrDA a chance to finish the setup properly * before being swamped with packets... */ ppp_output_wakeup(&new->chan); #endif /* CONNECT_INDIC_KICK */ /* Notify the control channel */ irnet_post_event(new, IRNET_CONNECT_FROM, new->saddr, new->daddr, server->rname, 0); DEXIT(IRDA_SERV_TRACE, "\n"); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
pre-gitpre-git20872.47%112.50%
linus torvaldslinus torvalds7526.13%450.00%
jean tourrilhesjean tourrilhes20.70%112.50%
david s. millerdavid s. miller10.35%112.50%
steven colesteven cole10.35%112.50%
Total287100.00%8100.00%

/*------------------------------------------------------------------*/ /* * Function irda_disconnect_server (self) * * Cleanup the server socket when the incoming connection abort * */
static inline void irnet_disconnect_server(irnet_socket * self, struct sk_buff *skb) { DENTER(IRDA_SERV_TRACE, "(self=0x%p)\n", self); /* Put the received packet in the black hole */ kfree_skb(skb); #ifdef FAIL_SEND_DISCONNECT /* Tell the other party we don't want to be connected */ /* Hum... Is it the right thing to do ? And do we need to send * a connect response before ? It looks ok without this... */ irttp_disconnect_request(self->tsap, NULL, P_NORMAL); #endif /* FAIL_SEND_DISCONNECT */ /* Notify the control channel (see irnet_find_socket()) */ irnet_post_event(NULL, IRNET_REQUEST_FROM, self->saddr, self->daddr, self->rname, 0); /* Clean up the server to keep it in listen state */ irttp_listen(self->tsap); DEXIT(IRDA_SERV_TRACE, "\n"); }

Contributors

PersonTokensPropCommitsCommitProp
pre-gitpre-git6068.97%116.67%
linus torvaldslinus torvalds2427.59%350.00%
jean tourrilhesjean tourrilhes22.30%116.67%
david s. millerdavid s. miller11.15%116.67%
Total87100.00%6100.00%

/*------------------------------------------------------------------*/ /* * Function irda_setup_server (self) * * Create a IrTTP server and set it up... * * Register the IrLAN hint bit, create a IrTTP instance for us, * set all the IrTTP callbacks and create an IrIAS entry... */
static inline int irnet_setup_server(void) { __u16 hints; DENTER(IRDA_SERV_TRACE, "()\n"); /* Initialise the regular socket part of the server */ irda_irnet_create(&irnet_server.s); /* Open a local TSAP (an IrTTP instance) for the server */ irnet_open_tsap(&irnet_server.s); /* PPP part setup */ irnet_server.s.ppp_open = 0; irnet_server.s.chan.private = NULL; irnet_server.s.file = NULL; /* Get the hint bit corresponding to IrLAN */ /* Note : we overload the IrLAN hint bit. As it is only a "hint", and as * we provide roughly the same functionality as IrLAN, this is ok. * In fact, the situation is similar as JetSend overloading the Obex hint */ hints = irlmp_service_to_hint(S_LAN); #ifdef ADVERTISE_HINT /* Register with IrLMP as a service (advertise our hint bit) */ irnet_server.skey = irlmp_register_service(hints); #endif /* ADVERTISE_HINT */ /* Register with LM-IAS (so that people can connect to us) */ irnet_server.ias_obj = irias_new_object(IRNET_SERVICE_NAME, jiffies); irias_add_integer_attrib(irnet_server.ias_obj, IRNET_IAS_VALUE, irnet_server.s.stsap_sel, IAS_KERNEL_ATTR); irias_insert_object(irnet_server.ias_obj); #ifdef DISCOVERY_EVENTS /* Tell IrLMP we want to be notified of newly discovered nodes */ irlmp_update_client(irnet_server.s.ckey, hints, irnet_discovery_indication, irnet_expiry_indication, (void *) &irnet_server.s); #endif DEXIT(IRDA_SERV_TRACE, " - self=0x%p\n", &irnet_server.s); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
pre-gitpre-git16898.82%133.33%
linus torvaldslinus torvalds10.59%133.33%
jean tourrilhesjean tourrilhes10.59%133.33%
Total170100.00%3100.00%

/*------------------------------------------------------------------*/ /* * Function irda_destroy_server (self) * * Destroy the IrTTP server... * * Reverse of the previous function... */
static inline void irnet_destroy_server(void) { DENTER(IRDA_SERV_TRACE, "()\n"); #ifdef ADVERTISE_HINT /* Unregister with IrLMP */ irlmp_unregister_service(irnet_server.skey); #endif /* ADVERTISE_HINT */ /* Unregister with LM-IAS */ if