FAR void *usbhost_devaddr_find(FAR struct usbhost_devaddr_s *hcd, uint8_t devaddr) { FAR struct usbhost_devhash_s *hentry; uint8_t hvalue; /* Get exclusive access to the HCD device address data */ hvalue = usbhost_devaddr_hash(devaddr); usbhost_takesem(hcd); /* Check each entry in the hash table */ for (hentry = hcd->hashtab[hvalue]; hentry; hentry = hentry->flink) { /* Is this the address we are looking for? */ if (hentry->devaddr == devaddr) { /* Yes.. return the payload from the hash table entry */ usbhost_givesem(hcd); return hentry->payload; } } /* Didn't find the device address */ usbhost_givesem(hcd); return NULL; }
int usbhost_devaddr_create(FAR struct usbhost_devaddr_s *hcd, FAR void *associate) { FAR struct usbhost_devhash_s *hentry; uint8_t hvalue; int devaddr; /* Allocate a hash table entry */ hentry = (FAR struct usbhost_devhash_s *)kmalloc(sizeof(struct usbhost_devhash_s)); if (!hentry) { udbg("ERROR: Failed to allocate a hash table entry\n"); return -ENOMEM; } /* Get exclusive access to the HCD device address data */ usbhost_takesem(hcd); /* Allocate a device address */ devaddr = usbhost_devaddr_allocate(hcd); if (devaddr < 0) { udbg("ERROR: Failed to allocate a device address\n"); free(hentry); } else { /* Initialize the hash table entry */ hentry->devaddr = devaddr; hentry->payload = associate; /* Add the new device address to the hash table */ hvalue = usbhost_devaddr_hash(devaddr); hentry->flink = hcd->hashtab[hvalue]; hcd->hashtab[hvalue] = hentry; /* Try to re-use the lowest numbered device addresses */ if (hcd->next > devaddr) { hcd->next = devaddr; } } usbhost_givesem(hcd); return devaddr; }
void usbhost_devaddr_destroy(FAR struct usbhost_devaddr_s *hcd, uint8_t devaddr) { FAR struct usbhost_devhash_s *hentry; FAR struct usbhost_devhash_s *prev; uint8_t hvalue; /* Get exclusive access to the HCD device address data */ hvalue = usbhost_devaddr_hash(devaddr); usbhost_takesem(hcd); /* Search the hast table for the matching entry */ for (hentry = hcd->hashtab[hvalue], prev = NULL; hentry; prev = hentry, hentry = hentry->flink) { /* Is this the address we are looking for? */ if (hentry->devaddr == devaddr) { /* Yes.. remove the entry from the hash list */ if (prev) { prev->flink = hentry->flink; } else { hcd->hashtab[hvalue] = hentry->flink; } /* And release the entry */ kfree(hentry); break; } } usbhost_givesem(hcd); }
static inline int usbhost_devinit(FAR struct usbhost_state_s *priv) { int ret = OK; /* Set aside a transfer buffer for exclusive use by the class driver */ /* Increment the reference count. This will prevent usbhost_destroy() from * being called asynchronously if the device is removed. */ priv->crefs++; DEBUGASSERT(priv->crefs == 2); /* Configure the device */ /* Register the driver */ if (ret >= 0) { char devname[DEV_NAMELEN]; uvdbg("Register block driver\n"); usbhost_mkdevname(priv, devname); // ret = register_blockdriver(devname, &g_bops, 0, priv); } /* Check if we successfully initialized. We now have to be concerned * about asynchronous modification of crefs because the block * driver has been registerd. */ if (ret >= 0) { usbhost_takesem(&priv->exclsem); DEBUGASSERT(priv->crefs >= 2); /* Handle a corner case where (1) open() has been called so the * reference count is > 2, but the device has been disconnected. * In this case, the class instance needs to persist until close() * is called. */ if (priv->crefs <= 2 && priv->disconnected) { /* We don't have to give the semaphore because it will be * destroyed when usb_destroy is called. */ ret = -ENODEV; } else { /* Ready for normal operation as a block device driver */ uvdbg("Successfully initialized\n"); priv->crefs--; usbhost_givesem(&priv->exclsem); } } return ret; }