Skip to content
This repository has been archived by the owner on Oct 8, 2024. It is now read-only.

Hdcp 2.2 #471

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions common/core/logicaldisplay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion common/core/logicaldisplay.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
10 changes: 8 additions & 2 deletions common/core/logicaldisplaymanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion common/core/logicaldisplaymanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
10 changes: 8 additions & 2 deletions common/core/mosaicdisplay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion common/core/mosaicdisplay.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
13 changes: 7 additions & 6 deletions public/hwcdefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
3 changes: 2 additions & 1 deletion public/nativedisplay.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
44 changes: 44 additions & 0 deletions tests/apps/jsonlayerstest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<hwcomposer::NativeDisplay *> connected_displays_;
hwcomposer::GpuDevice *device_;
Expand Down Expand Up @@ -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) {
Expand Down
96 changes: 68 additions & 28 deletions wsi/drm/drmdisplay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<HWCContentProtection>(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<HWCContentType>(value);

GetDrmHDCPObjectProperty("CP_SRM", connector, connector_props,
&hdcp_srm_id_prop_, &value);
Expand All @@ -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_);
Expand Down Expand Up @@ -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))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when and how the status will change from kDesired to kEnabled? Is it possible in the sleep time frame it is already changed to kEnabled, you can not get the kDesired state.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry, could you please explain more about the sleep time frame?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean in the SetHDCPState() there is 'usleep(100 * 1000);' for every iteration. is it possible in this time frame, the state changes from kUnDisired->kDesired->kEnabled? for such case, your logic in Check state will not return true.

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) */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

possible to wait up to 15s blocking hwc service such long time seems not acceptable. I would suggest not blocking in hwc.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, agreed. This should be done by the hdcp daemon. I had previously raised it as a concern.
Once the daemon does it, We can remove this here.

for (uint8_t i = 0; i < 160; i++) {
if (CheckHDCPStatus()) {
harishkrupo marked this conversation as resolved.
Show resolved Hide resolved
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) {
Expand Down
7 changes: 5 additions & 2 deletions wsi/drm/drmdisplay.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -139,6 +139,7 @@ class DrmDisplay : public PhysicalDisplay {
std::vector<uint8_t *> FindExtendedBlocksForTag(uint8_t *edid,
uint8_t block_tag);
void DrmConnectorGetDCIP3Support(const ScopedDrmObjectPropertyPtr &props);
bool CheckHDCPStatus();

uint32_t crtc_id_ = 0;
uint32_t mmWidth_ = 0;
Expand All @@ -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;
Expand All @@ -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<drmModeModeInfo> modes_;
SpinLock display_lock_;
DrmDisplayManager *manager_;
Expand Down