diff --git a/common/core/logicaldisplay.cpp b/common/core/logicaldisplay.cpp index dce7f8039..8f076d976 100644 --- a/common/core/logicaldisplay.cpp +++ b/common/core/logicaldisplay.cpp @@ -68,9 +68,9 @@ bool LogicalDisplay::SetPowerMode(uint32_t power_mode) { return true; } -void LogicalDisplay::SetHDCPState(HWCContentProtection state, +bool LogicalDisplay::SetHDCPState(HWCContentProtection state, HWCContentType content_type) { - logical_display_manager_->SetHDCPState(state, content_type); + return logical_display_manager_->SetHDCPState(state, content_type); } void LogicalDisplay::SetHDCPSRM(const int8_t *SRM, uint32_t SRMLength) { diff --git a/common/core/logicaldisplay.h b/common/core/logicaldisplay.h index f09478b4c..883fdf8aa 100644 --- a/common/core/logicaldisplay.h +++ b/common/core/logicaldisplay.h @@ -122,7 +122,7 @@ class LogicalDisplay : public NativeDisplay { void HotPlugUpdate(bool connected) override; - void SetHDCPState(HWCContentProtection state, + bool SetHDCPState(HWCContentProtection state, HWCContentType content_type) override; void SetHDCPSRM(const int8_t *SRM, uint32_t SRMLength) override; diff --git a/common/core/logicaldisplaymanager.cpp b/common/core/logicaldisplaymanager.cpp index 67741c30e..f2baa4409 100644 --- a/common/core/logicaldisplaymanager.cpp +++ b/common/core/logicaldisplaymanager.cpp @@ -223,12 +223,18 @@ void LogicalDisplayManager::GetLogicalDisplays( } } -void LogicalDisplayManager::SetHDCPState(HWCContentProtection state, +bool LogicalDisplayManager::SetHDCPState(HWCContentProtection state, HWCContentType content_type) { uint32_t size = displays_.size(); + bool ret = true; for (uint32_t i = 0; i < size; i++) { - displays_.at(i)->SetHDCPState(state, content_type); + if (ret) + ret = displays_.at(i)->SetHDCPState(state, content_type); + else + break; } + + return ret; } void LogicalDisplayManager::SetHDCPSRM(const int8_t* SRM, uint32_t SRMLength) { diff --git a/common/core/logicaldisplaymanager.h b/common/core/logicaldisplaymanager.h index 7289c25e8..ff183d23f 100644 --- a/common/core/logicaldisplaymanager.h +++ b/common/core/logicaldisplaymanager.h @@ -95,7 +95,7 @@ class LogicalDisplayManager { * @param state an enum named HWCContentProtection * @param content_type an enum of HWCContentType */ - void SetHDCPState(HWCContentProtection state, HWCContentType content_type); + bool SetHDCPState(HWCContentProtection state, HWCContentType content_type); void SetHDCPSRM(const int8_t* SRM, uint32_t SRMLength); diff --git a/common/core/mosaicdisplay.cpp b/common/core/mosaicdisplay.cpp index a6eaa44b6..d76148e43 100644 --- a/common/core/mosaicdisplay.cpp +++ b/common/core/mosaicdisplay.cpp @@ -504,12 +504,18 @@ bool MosaicDisplay::GetDisplayName(uint32_t *size, char *name) { return true; } -void MosaicDisplay::SetHDCPState(HWCContentProtection state, +bool MosaicDisplay::SetHDCPState(HWCContentProtection state, HWCContentType content_type) { uint32_t size = physical_displays_.size(); + bool ret = true; for (uint32_t i = 0; i < size; i++) { - physical_displays_.at(i)->SetHDCPState(state, content_type); + if (ret) + ret = physical_displays_.at(i)->SetHDCPState(state, content_type); + else + break; } + + return ret; } void MosaicDisplay::SetHDCPSRM(const int8_t *SRM, uint32_t SRMLength) { diff --git a/common/core/mosaicdisplay.h b/common/core/mosaicdisplay.h index 03fd32f8a..a065fc9fd 100644 --- a/common/core/mosaicdisplay.h +++ b/common/core/mosaicdisplay.h @@ -109,7 +109,7 @@ class MosaicDisplay : public NativeDisplay { void HotPlugUpdate(bool connected); - void SetHDCPState(HWCContentProtection state, + bool SetHDCPState(HWCContentProtection state, HWCContentType content_type) override; void SetHDCPSRM(const int8_t *SRM, uint32_t SRMLength) override; diff --git a/public/hwcdefs.h b/public/hwcdefs.h index f320f3801..5e37d3140 100644 --- a/public/hwcdefs.h +++ b/public/hwcdefs.h @@ -40,15 +40,16 @@ enum class HWCBlending : int32_t { // Enumerations for content protection. enum HWCContentProtection { - kUnSupported = 0, // Content Protection is not supported. - kUnDesired = 1, // Content Protection is not required. - kDesired = 2 // Content Protection is desired. + kUnSupported = -1, // Content Protection is not supported. + kUnDesired = 0, // Content Protection is not required. + kDesired = 1, // Content Protection is desired. + kEnabled = 2 }; enum HWCContentType { - kInvalid, // Used when disabling HDCP. - kCONTENT_TYPE0, // Can support any HDCP specifiction. - kCONTENT_TYPE1, // Can support only HDCP 2.2 and higher specification. + kInvalid = -1, // Used when disabling HDCP. + kCONTENT_TYPE0 = 0, // Can support any HDCP specifiction. + kCONTENT_TYPE1 = 1, // Can support only HDCP 2.2 and higher specification. }; enum HWCTransform : uint32_t { diff --git a/public/nativedisplay.h b/public/nativedisplay.h index fdc02358d..473526cb9 100644 --- a/public/nativedisplay.h +++ b/public/nativedisplay.h @@ -400,8 +400,9 @@ class NativeDisplay { * tries to take advantage of any HDCP support advertised by * the Kernel. */ - virtual void SetHDCPState(HWCContentProtection /*state*/, + virtual bool SetHDCPState(HWCContentProtection /*state*/, HWCContentType /*content_type*/) { + return false; } virtual void SetPAVPSessionStatus(bool enabled, uint32_t pavp_session_id, diff --git a/tests/apps/jsonlayerstest.cpp b/tests/apps/jsonlayerstest.cpp index 02d50b827..670cf5f6b 100644 --- a/tests/apps/jsonlayerstest.cpp +++ b/tests/apps/jsonlayerstest.cpp @@ -411,6 +411,28 @@ class HotPlugEventCallback : public hwcomposer::DisplayHotPlugEventCallback { } } + bool EnableHDCP(hwcomposer::HWCContentType type) { + bool ret = true; + for (auto &display : connected_displays_) { + ret = ret && + display->SetHDCPState(hwcomposer::HWCContentProtection::kDesired, + type); + } + + return ret; + } + + bool DisableHDCP() { + bool ret = true; + for (auto &display : connected_displays_) { + ret = ret && + display->SetHDCPState(hwcomposer::HWCContentProtection::kUnDesired, + hwcomposer::HWCContentType::kInvalid); + } + + return ret; + } + private: std::vector connected_displays_; hwcomposer::GpuDevice *device_; @@ -964,6 +986,28 @@ int main(int argc, char *argv[]) { callback->SetContrast(0x80, 0x80, 0x80); callback->SetCanvasColor(0x0, 8); + // Test for HDCP 1.4: TYPE 0 content + + fprintf(stderr, "Trying to enable HDCP 1.4\n"); + ret = callback->EnableHDCP(hwcomposer::HWCContentType::kCONTENT_TYPE0); + if (!ret) { + fprintf(stderr, "Unable to enable HDCP 1.4\n"); + } else { + fprintf(stderr, "HDCP 1.4 successfully enabled\n"); + callback->DisableHDCP(); + } + + // Test for HDCP 2.2: TYPE 1 content + + fprintf(stderr, "Trying to enable HDCP 2.2\n"); + ret = callback->EnableHDCP(hwcomposer::HWCContentType::kCONTENT_TYPE1); + if (!ret) { + fprintf(stderr, "Unable to enable HDCP 2.2\n"); + } else { + fprintf(stderr, "HDCP 2.2 successfully enabled\n"); + callback->DisableHDCP(); + } + for (size_t i = 0; i < ARRAY_SIZE(frames); ++i) { struct frame *frame = &frames[i]; for (int32_t &fence : frame->fences) { diff --git a/wsi/drm/drmdisplay.cpp b/wsi/drm/drmdisplay.cpp index 961d91d00..0f00356bb 100644 --- a/wsi/drm/drmdisplay.cpp +++ b/wsi/drm/drmdisplay.cpp @@ -182,22 +182,12 @@ bool DrmDisplay::ConnectDisplay(const drmModeModeInfo &mode_info, GetDrmHDCPObjectProperty("Content Protection", connector, connector_props, &hdcp_id_prop_, &value); - if (value >= 0) { - switch (value) { - case 0: - current_protection_support_ = HWCContentProtection::kUnDesired; - break; - case 1: - current_protection_support_ = HWCContentProtection::kDesired; - break; - default: - break; - } + current_protection_support_ = static_cast(value); - if (desired_protection_support_ == HWCContentProtection::kUnSupported) { - desired_protection_support_ = current_protection_support_; - } - } + GetDrmHDCPObjectProperty("CP_Content_Type", connector, connector_props, + &hdcp_type_prop_, &value); + + current_content_type_ = static_cast(value); GetDrmHDCPObjectProperty("CP_SRM", connector, connector_props, &hdcp_srm_id_prop_, &value); @@ -213,7 +203,6 @@ bool DrmDisplay::ConnectDisplay(const drmModeModeInfo &mode_info, ITRACE("DCIP3 support not available"); PhysicalDisplay::Connect(); - SetHDCPState(desired_protection_support_, content_type_); drmModePropertyPtr broadcastrgb_props = drmModeGetProperty(gpu_fd_, broadcastrgb_id_); @@ -419,30 +408,81 @@ bool DrmDisplay::SetBroadcastRGB(const char *range_property) { return true; } -void DrmDisplay::SetHDCPState(HWCContentProtection state, +bool DrmDisplay::CheckHDCPStatus() { + int val = -1; + uint32_t i; + ScopedDrmObjectPropertyPtr cprops(drmModeObjectGetProperties( + gpu_fd_, connector_, DRM_MODE_OBJECT_CONNECTOR)); + for (i = 0; i < cprops->count_props; i++) { + if (cprops->props[i] == hdcp_id_prop_) { + val = cprops->prop_values[i]; + break; + } + } + + if ((current_protection_support_ && val == HWCContentProtection::kEnabled) || + (!current_protection_support_ && val == HWCContentProtection::kDesired)) + return true; + + return false; +} + +bool DrmDisplay::SetHDCPState(HWCContentProtection state, HWCContentType content_type) { desired_protection_support_ = state; - content_type_ = content_type; - if (desired_protection_support_ == current_protection_support_) - return; + desired_content_type_ = content_type; + + if (desired_protection_support_ == current_protection_support_ && + desired_content_type_ == current_content_type_) + return true; if (hdcp_id_prop_ <= 0) { ETRACE("Cannot set HDCP state as Connector property is not supported \n"); - return; + return false; + } + if ((hdcp_type_prop_ <= 0) && (desired_content_type_ == 1)) { + ETRACE("Content type property unavailable. HDCP 2.2 cannot be enabled\n"); + return false; } if (!(connection_state_ & kConnected)) { - return; + return false; } - current_protection_support_ = desired_protection_support_; - uint32_t value = 0; - if (current_protection_support_ == kDesired) { - value = 1; + ScopedDrmAtomicReqPtr pset(drmModeAtomicAlloc()); + int ret = drmModeAtomicAddProperty(pset.get(), connector_, hdcp_id_prop_, + desired_protection_support_) < 0; + if (current_protection_support_ && (hdcp_type_prop_ > 0)) + ret = ret || + drmModeAtomicAddProperty(pset.get(), connector_, hdcp_type_prop_, + desired_content_type_) < 0; + if (ret) { + ETRACE("Unable to fill pset for HDCP\n"); + return false; + } + ret = drmModeAtomicCommit(gpu_fd_, pset.get(), DRM_MODE_ATOMIC_ALLOW_MODESET, + NULL); + if (ret) { + ETRACE("Failed to commit HDCP ret %d errno %d : %s\n", ret, errno, + PRINTERROR()); + return false; } - drmModeConnectorSetProperty(gpu_fd_, connector_, hdcp_id_prop_, value); - ETRACE("Ignored Content type. \n"); + /* Wait for Enable should be 5.1 Sec * 3(kernel reattempt cnt) */ + for (uint8_t i = 0; i < 160; i++) { + if (CheckHDCPStatus()) { + current_protection_support_ = desired_protection_support_; + current_content_type_ = desired_content_type_; + return true; + } + usleep(100 * 1000); + } + + // HDCP failed to enable, mark it as undesired + drmModeConnectorSetProperty(gpu_fd_, connector_, hdcp_id_prop_, + HWCContentProtection::kUnDesired); + + return false; } void DrmDisplay::SetHDCPSRM(const int8_t *SRM, uint32_t SRMLength) { diff --git a/wsi/drm/drmdisplay.h b/wsi/drm/drmdisplay.h index 790708291..faf9145b2 100644 --- a/wsi/drm/drmdisplay.h +++ b/wsi/drm/drmdisplay.h @@ -53,7 +53,7 @@ class DrmDisplay : public PhysicalDisplay { bool SetBroadcastRGB(const char *range_property) override; - void SetHDCPState(HWCContentProtection state, + bool SetHDCPState(HWCContentProtection state, HWCContentType content_type) override; void SetHDCPSRM(const int8_t *SRM, uint32_t SRMLength) override; @@ -139,6 +139,7 @@ class DrmDisplay : public PhysicalDisplay { std::vector FindExtendedBlocksForTag(uint8_t *edid, uint8_t block_tag); void DrmConnectorGetDCIP3Support(const ScopedDrmObjectPropertyPtr &props); + bool CheckHDCPStatus(); uint32_t crtc_id_ = 0; uint32_t mmWidth_ = 0; @@ -155,6 +156,7 @@ class DrmDisplay : public PhysicalDisplay { uint32_t active_prop_ = 0; uint32_t mode_id_prop_ = 0; uint32_t hdcp_id_prop_ = 0; + uint32_t hdcp_type_prop_ = 0; uint32_t hdcp_srm_id_prop_ = 0; uint32_t edid_prop_ = 0; uint32_t canvas_color_prop_ = 0; @@ -169,7 +171,8 @@ class DrmDisplay : public PhysicalDisplay { HWCContentProtection desired_protection_support_ = HWCContentProtection::kUnSupported; drmModeModeInfo current_mode_; - HWCContentType content_type_ = kCONTENT_TYPE0; + HWCContentType current_content_type_ = kCONTENT_TYPE0; + HWCContentType desired_content_type_ = kInvalid; std::vector modes_; SpinLock display_lock_; DrmDisplayManager *manager_;