blob: bbbb85706020902dd40cdd0cdb6c56ad53f4d82b [file] [log] [blame]
// Copyright 2018 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CECSERVICE_CEC_MANAGER_H_
#define CECSERVICE_CEC_MANAGER_H_
#include <map>
#include <memory>
#include <string>
#include <vector>
#include <base/files/file_path.h>
#include <base/functional/callback.h>
#include <base/memory/weak_ptr.h>
#include <chromeos/dbus/service_constants.h>
#include "cecservice/cec_device.h"
#include "cecservice/udev.h"
namespace cecservice {
// Main service object that maintains list of /dev/cec* nodes (with a help of
// udev) and passes received commands to CEC devices.
class CecManager {
public:
using GetTvsPowerStatusCallback =
base::OnceCallback<void(const std::vector<TvPowerStatus>&)>;
using PowerChangeSentCallback = base::OnceCallback<void()>;
CecManager(const UdevFactory& udev_factory,
const CecDeviceFactory& cec_factory);
CecManager(const CecManager&) = delete;
CecManager& operator=(const CecManager&) = delete;
~CecManager();
// Queries power status of CEC-enabled TVs (devices with logical address 0).
// The order of returned values is arbitrary.
void GetTvsPowerStatus(GetTvsPowerStatusCallback callback);
// Sends wake up (image view on + active source) request to all CEC-enabled
// TVs.
void SetWakeUp(PowerChangeSentCallback callback);
// Passes stand by command to all CEC-enabled TVs.
void SetStandBy(PowerChangeSentCallback callback);
private:
// Ids for get tv power queries.
typedef unsigned QueryId;
// Represents a power status query result from a single CEC device.
struct TvPowerStatusResult;
// Ongoing power status query.
struct TvsPowerStatusQuery;
// Ongoing power change request. Used for standby and wakeup requests.
struct PowerChangeRequest;
// Callback for TV power status responses.
void OnTvPowerResponse(QueryId id,
base::FilePath device_path,
TvPowerStatus result);
// If all responses for a given query has been received, this method will
// invoke the query's callback and return true. False is returned when not
// all of the responses have been received and thus the query has not
// completed yet.
bool MaybeRespondToTvsPowerStatusQuery(TvsPowerStatusQuery& query);
// Create a new power change request and add it to power_change_requests_.
// Returns the request ID.
QueryId CreatePowerChangeRequest(PowerChangeSentCallback callback);
// Callback when a standby or wakeup message has been sent to a device.
void OnPowerChangeSent(QueryId id, base::FilePath device_path);
// If messages have been sent to all devices, run the callback and return
// true. Otherwise return false.
bool MaybePowerChangeRequestComplete(PowerChangeRequest& request);
// Called when udev reports that new device has been added.
void OnDeviceAdded(const base::FilePath& device_path);
// Called when udev reports that a device has been removed.
void OnDeviceRemoved(const base::FilePath& device_path);
// Enumerates and adds all existing devices.
void EnumerateAndAddExistingDevices();
// Creates new handler for a device with a given path.
void AddNewDevice(const base::FilePath& path);
// Factory of CEC device handlers.
const CecDeviceFactory& cec_factory_;
// Id to be used for next query.
QueryId next_query_id_ = 0;
// Id to be used for the next power change request.
QueryId next_power_change_id_ = 0;
// Ongoing power status queries.
std::map<QueryId, TvsPowerStatusQuery> tv_power_status_queries_;
// Ongoing power change requests.
std::map<QueryId, PowerChangeRequest> power_change_requests_;
// List of currently opened CEC devices.
std::map<base::FilePath, std::unique_ptr<CecDevice>> devices_;
// Udev object used to communicate with libudev.
std::unique_ptr<Udev> udev_;
base::WeakPtrFactory<CecManager> weak_factory_{this};
};
} // namespace cecservice
#endif // CECSERVICE_CEC_MANAGER_H_