summaryrefslogtreecommitdiff
path: root/auth-control.c
diff options
context:
space:
mode:
Diffstat (limited to 'auth-control.c')
-rw-r--r--auth-control.c138
1 files changed, 138 insertions, 0 deletions
diff --git a/auth-control.c b/auth-control.c
new file mode 100644
index 0000000..21527cd
--- /dev/null
+++ b/auth-control.c
@@ -0,0 +1,138 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2022 Samsung Electronics Co., Ltd.
+ *
+ * Samsung DisplayPort driver.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+
+#include "exynos-hdcp-interface.h"
+
+#include "auth-control.h"
+#include "auth13.h"
+#include "auth22.h"
+#include "hdcp-log.h"
+#include "teeif.h"
+
+static struct delayed_work hdcp_work;
+
+static enum auth_state state;
+
+static unsigned long max_ver = 0; /* Disable HDCP by default */
+module_param(max_ver, ulong, 0664);
+MODULE_PARM_DESC(max_ver,
+ "support up to specific hdcp version by setting max_ver=x");
+
+int hdcp_get_auth_state(void) {
+ return state;
+}
+
+static int run_hdcp2_auth(void) {
+ int ret;
+ int i;
+
+ state = HDCP2_AUTH_PROGRESS;
+ for (i = 0; i < 5; ++i) {
+ ret = hdcp22_dplink_authenticate();
+ if (ret == 0) {
+ state = HDCP2_AUTH_DONE;
+ /* HDCP2.2 spec defined 200ms */
+ msleep(200);
+ hdcp_tee_enable_enc_22();
+ return 0;
+ } else if (ret != -EAGAIN) {
+ return -EIO;
+ }
+ hdcp_info("HDCP22 Retry...\n");
+ }
+
+ return -EIO;
+}
+
+static void hdcp_worker(struct work_struct *work) {
+ if (max_ver >= 2) {
+ hdcp_info("Trying HDCP22...\n");
+ if (run_hdcp2_auth() == 0) {
+ hdcp_info("HDCP22 Authentication Success\n");
+ return;
+ }
+ hdcp_info("HDCP22 Authentication Failed.\n");
+ } else {
+ hdcp_info("Not trying HDCP22. max_ver is %lu\n", max_ver);
+ }
+
+ if (max_ver >= 1) {
+ hdcp_info("Trying HDCP13...\n");
+ state = HDCP1_AUTH_PROGRESS;
+ if (hdcp13_dplink_authenticate() == 0) {
+ hdcp_info("HDCP13 Authentication Success\n");
+ state = HDCP1_AUTH_DONE;
+ return;
+ }
+
+ state = HDCP_AUTH_IDLE;
+ hdcp_info("HDCP13 Authentication Failed.\n");
+ } else {
+ hdcp_info("Not trying HDCP13. max_ver is %lu\n", max_ver);
+ }
+}
+
+void hdcp_dplink_handle_irq(void) {
+ if (state == HDCP2_AUTH_PROGRESS || state == HDCP2_AUTH_DONE) {
+ if (hdcp22_dplink_handle_irq() == -EAGAIN)
+ schedule_delayed_work(&hdcp_work, 0);
+ return;
+ }
+
+ if (state == HDCP1_AUTH_DONE) {
+ if (hdcp13_dplink_handle_irq() == -EAGAIN)
+ schedule_delayed_work(&hdcp_work, 0);
+ return;
+ }
+}
+EXPORT_SYMBOL_GPL(hdcp_dplink_handle_irq);
+
+
+void hdcp_dplink_connect_state(enum dp_state dp_hdcp_state) {
+ hdcp_info("Displayport connect info (%d)\n", dp_hdcp_state);
+ hdcp_tee_connect_info((int)dp_hdcp_state);
+ if (dp_hdcp_state == DP_DISCONNECT) {
+ hdcp13_dplink_abort();
+ hdcp22_dplink_abort();
+ hdcp_tee_disable_enc();
+ state = HDCP_AUTH_IDLE;
+ return;
+ }
+
+ schedule_delayed_work(&hdcp_work, msecs_to_jiffies(500));
+ return;
+}
+EXPORT_SYMBOL_GPL(hdcp_dplink_connect_state);
+
+void hdcp_auth_worker_init(void) {
+ INIT_DELAYED_WORK(&hdcp_work, hdcp_worker);
+}
+
+void hdcp_auth_worker_deinit(void) {
+ cancel_delayed_work_sync(&hdcp_work);
+}
+
+/* DEPRECATED */
+int hdcp_dplink_auth_check(enum auth_signal signal) { return -1; }
+EXPORT_SYMBOL_GPL(hdcp_dplink_auth_check);
+int hdcp_dplink_get_rxstatus(uint8_t *status) { return -1; }
+EXPORT_SYMBOL_GPL(hdcp_dplink_get_rxstatus);
+int hdcp_dplink_set_paring_available(void) { return -1; }
+EXPORT_SYMBOL_GPL(hdcp_dplink_set_paring_available);
+int hdcp_dplink_set_hprime_available(void) { return -1; }
+EXPORT_SYMBOL_GPL(hdcp_dplink_set_hprime_available);
+int hdcp_dplink_set_rp_ready(void) { return -1; }
+EXPORT_SYMBOL_GPL(hdcp_dplink_set_rp_ready);
+int hdcp_dplink_set_reauth(void) { return -1; }
+EXPORT_SYMBOL_GPL(hdcp_dplink_set_reauth);