blob: 387bc85eaa87cb62e40d5974c126105a8ef8d698 [file] [log] [blame]
// Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef POWER_MANAGER_POWERD_SYSTEM_UDEV_H_
#define POWER_MANAGER_POWERD_SYSTEM_UDEV_H_
#include <map>
#include <string>
#include <vector>
#include <base/macros.h>
#include <base/memory/linked_ptr.h>
#include <base/message_loop/message_loop.h>
#include <base/observer_list.h>
struct udev;
struct udev_device;
struct udev_monitor;
namespace power_manager {
namespace system {
class TaggedDevice;
class UdevSubsystemObserver;
class UdevTaggedDeviceObserver;
// Action described in a udev event.
enum UdevAction {
UDEV_ACTION_ADD = 0,
UDEV_ACTION_REMOVE,
UDEV_ACTION_CHANGE,
UDEV_ACTION_ONLINE,
UDEV_ACTION_OFFLINE,
UDEV_ACTION_UNKNOWN,
};
// Watches the udev manager for device-related events (e.g. hotplug).
class UdevInterface {
public:
UdevInterface() {}
virtual ~UdevInterface() {}
// Adds or removes an observer for watching |subsystem|. To receive events,
// this subsystem must also be listed in udev/90-powerd-tags.rules.
virtual void AddSubsystemObserver(const std::string& subsystem,
UdevSubsystemObserver* observer) = 0;
virtual void RemoveSubsystemObserver(const std::string& subsystem,
UdevSubsystemObserver* observer) = 0;
// Adds/removes an observer that will receive events for tagged devices.
virtual void AddTaggedDeviceObserver(UdevTaggedDeviceObserver* observer) = 0;
virtual void RemoveTaggedDeviceObserver(UdevTaggedDeviceObserver* observer)
= 0;
// Retrieves a list of all known tagged devices.
virtual std::vector<TaggedDevice> GetTaggedDevices() = 0;
// Reads the sysfs attribute |sysattr| from the device specified by |syspath|.
// Returns true on success. |syspath| is the syspath of a device as returned
// by libudev, e.g.
// "/sys/devices/pci0000:00/0000:00:14.0/usb1/1-2/1-2:1.0/input/input22".
virtual bool GetSysattr(const std::string& syspath,
const std::string& sysattr,
std::string* value) = 0;
// Sets the value of a sysfs attribute. Returns true on success.
virtual bool SetSysattr(const std::string& syspath,
const std::string& sysattr,
const std::string& value) = 0;
// For the device specified by |syspath|, finds the first parent device which
// has a sysattr named |sysattr|, and stores the parent's syspath in
// |parent_syspath|. If |stop_at_devtype| is a nonempty string, then no parent
// devices will be considered beyond the first device matching
// |stop_at_devtype|. Returns true on success, or false on failure or when no
// matching parent device was found.
virtual bool FindParentWithSysattr(const std::string& syspath,
const std::string& sysattr,
const std::string& stop_at_devtype,
std::string* parent_syspath) = 0;
};
// Actual implementation of UdevInterface.
class Udev : public UdevInterface, public base::MessageLoopForIO::Watcher {
public:
Udev();
virtual ~Udev();
// Initializes the object to listen for events. Returns true on success.
bool Init();
// UdevInterface implementation:
void AddSubsystemObserver(const std::string& subsystem,
UdevSubsystemObserver* observer) override;
void RemoveSubsystemObserver(const std::string& subsystem,
UdevSubsystemObserver* observer) override;
void AddTaggedDeviceObserver(UdevTaggedDeviceObserver* observer) override;
void RemoveTaggedDeviceObserver(UdevTaggedDeviceObserver* observer) override;
std::vector<TaggedDevice> GetTaggedDevices() override;
bool GetSysattr(const std::string& syspath,
const std::string& sysattr,
std::string* value) override;
bool SetSysattr(const std::string& syspath,
const std::string& sysattr,
const std::string& value) override;
bool FindParentWithSysattr(const std::string& syspath,
const std::string& sysattr,
const std::string& stopat_devtype,
std::string* parent_syspath) override;
// base::MessageLoopForIO::Watcher implementation:
void OnFileCanReadWithoutBlocking(int fd) override;
void OnFileCanWriteWithoutBlocking(int fd) override;
private:
void HandleSubsystemEvent(UdevAction action,
struct udev_device* dev);
void HandleTaggedDevice(UdevAction action,
struct udev_device* dev);
void TaggedDeviceChanged(const std::string& syspath,
const std::string& tags);
void TaggedDeviceRemoved(const std::string& syspath);
// Populates |tagged_devices_| with currently-existing devices.
bool EnumerateTaggedDevices();
struct udev* udev_;
struct udev_monitor* udev_monitor_;
// Maps from a subsystem name to the corresponding observers.
typedef std::map<std::string,
linked_ptr<base::ObserverList<UdevSubsystemObserver>>>
SubsystemObserverMap;
SubsystemObserverMap subsystem_observers_;
base::ObserverList<UdevTaggedDeviceObserver> tagged_device_observers_;
// Maps a syspath to the corresponding TaggedDevice.
std::map<std::string, TaggedDevice> tagged_devices_;
// Controller for watching |udev_monitor_|'s FD for readability.
base::MessageLoopForIO::FileDescriptorWatcher watcher_;
DISALLOW_COPY_AND_ASSIGN(Udev);
};
} // namespace system
} // namespace power_manager
#endif // POWER_MANAGER_POWERD_SYSTEM_UDEV_H_