设备驱动模型之总线查找设备:
 
/**
 * bus_find_device - device iterator for locating a particular device.
 * @bus: bus type
 * @start: Device to begin with
 * @data: Data to pass to match function
 * @match: Callback function to check device
 *
 * This is similar to the bus_for_each_dev() function above, but it
 * returns a reference to a device that is 'found' for later use, as
 * determined by the @match callback.
 *
 * The callback should return 0 if the device doesn't match and non-zero
 * if it does.  If the callback returns non-zero, this function will
 * return to the caller and not iterate over any more devices.
 */
struct device *bus_find_device(struct bus_type *bus,
          struct device *start, void *data,
          int (*match)(struct device *dev, void *data))
{
 struct klist_iter i;
 struct device *dev;
 
 if (!bus || !bus->p)
  return NULL;
 klist_iter_init_node(&bus->p->klist_devices, &i,
        (start ? &start->p->knode_bus : NULL));
 while ((dev = next_device(&i)))
  if (match(dev, data) && get_device(dev))
   break;
 klist_iter_exit(&i);
 return dev;
}

根据名字查找设备:
/**
 * bus_find_device_by_name - device iterator for locating a particular device of a specific name
 * @bus: bus type
 * @start: Device to begin with
 * @name: name of the device to match
 *
 * This is similar to the bus_find_device() function above, but it handles
 * searching by a name automatically, no need to write another strcmp matching
 * function.
 */
struct device *bus_find_device_by_name(struct bus_type *bus,
           struct device *start, const char *name)
{
 return bus_find_device(bus, start, (void *)name, match_name);
}
EXPORT_SYMBOL_GPL(bus_find_device_by_name);
 
 
总线上迭代设备:
 

/**
 * bus_for_each_dev - device iterator.
 * @bus: bus type.
 * @start: device to start iterating from.
 * @data: data for the callback.
 * @fn: function to be called for each device.
 *
 * Iterate over @bus's list of devices, and call @fn for each,
 * passing it @data. If @start is not NULL, we use that device to
 * begin iterating from.
 *
 * We check the return of @fn each time. If it returns anything
 * other than 0, we break out and return that value.
 *
 * NOTE: The device that returns a non-zero value is not retained
 * in any way, nor is its refcount incremented. If the caller needs
 * to retain this data, it should do so, and increment the reference
 * count in the supplied callback.
 */
int bus_for_each_dev(struct bus_type *bus, struct device *start,
       void *data, int (*fn)(struct device *, void *))
{
 struct klist_iter i;
 struct device *dev;
 int error = 0;
 if (!bus || !bus->p)
  return -EINVAL;
 klist_iter_init_node(&bus->p->klist_devices, &i,
        (start ? &start->p->knode_bus : NULL));
 while ((dev = next_device(&i)) && !error)
  error = fn(dev, data);
 klist_iter_exit(&i);
 return error;
}

根据id查找设备:

/**
 * subsys_find_device_by_id - find a device with a specific enumeration number
 * @subsys: subsystem
 * @id: index 'id' in struct device
 * @hint: device to check first
 *
 * Check the hint's next object and if it is a match return it directly,
 * otherwise, fall back to a full list search. Either way a reference for
 * the returned object is taken.
 */
struct device *subsys_find_device_by_id(struct bus_type *subsys, unsigned int id,
     struct device *hint)
{
 struct klist_iter i;
 struct device *dev;
 if (!subsys)
  return NULL;
 if (hint) {
  klist_iter_init_node(&subsys->p->klist_devices, &i, &hint->p->knode_bus);
  dev = next_device(&i);
  if (dev && dev->id == id && get_device(dev)) {
   klist_iter_exit(&i);
   return dev;
  }
  klist_iter_exit(&i);
 }
 klist_iter_init_node(&subsys->p->klist_devices, &i, NULL);
 while ((dev = next_device(&i))) {
  if (dev->id == id && get_device(dev)) {
   klist_iter_exit(&i);
   return dev;
  }
 }
 klist_iter_exit(&i);
 return NULL;
}