Loading drivers/gpu/drm/msm/sde_hdcp.h +2 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,8 @@ #define SDE_HDCP_DEBUG(fmt, args...) SDE_DEBUG(fmt, ##args) #endif #define SDE_HDCP_SRM_FAIL 29 enum sde_hdcp_client_id { HDCP_CLIENT_HDMI, HDCP_CLIENT_DP, Loading drivers/gpu/drm/msm/sde_hdcp_1x.c +162 −1 Original line number Diff line number Diff line Loading @@ -748,6 +748,107 @@ error: return rc; } static u8 *sde_hdcp_1x_swap_byte_order(u8 *bksv_in, int num_dev) { u8 *bksv_out; u8 *tmp_out; u8 *tmp_in; int i, j; /* Dont exceed max downstream devices */ if (num_dev > MAX_DEVICES_SUPPORTED) { pr_err("invalid params\n"); return NULL; } bksv_out = kzalloc(RECV_ID_SIZE * num_dev, GFP_KERNEL); if (!bksv_out) return NULL; SDE_HDCP_DEBUG("num_dev = %d\n", num_dev); /* Store temporarily for return */ tmp_out = bksv_out; tmp_in = bksv_in; for (i = 0; i < num_dev; i++) { for (j = 0; j < RECV_ID_SIZE; j++) bksv_out[j] = tmp_in[RECV_ID_SIZE - j - 1]; /* Each KSV is 5 bytes long */ bksv_out += RECV_ID_SIZE; tmp_in += RECV_ID_SIZE; } return tmp_out; } static int sde_hdcp_1x_revoked_rcv_chk(struct sde_hdcp_1x *hdcp) { int rc = 0; u8 *bksv = hdcp->current_tp.bksv; u8 *bksv_out; struct hdcp_srm_device_id_t *bksv_srm; bksv_out = sde_hdcp_1x_swap_byte_order(bksv, 1); if (!bksv_out) { rc = -ENOMEM; goto exit; } SDE_HDCP_DEBUG("bksv_out : 0x%2x%2x%2x%2x%2x\n", bksv_out[4], bksv_out[3], bksv_out[2], bksv_out[1], bksv_out[0]); bksv_srm = (struct hdcp_srm_device_id_t *)bksv_out; /* Here we are checking only receiver ID * hence the device count is one */ rc = hdcp1_validate_receiver_ids(bksv_srm, 1); kfree(bksv_out); exit: return rc; } static int sde_hdcp_1x_revoked_rpt_chk(struct sde_hdcp_1x *hdcp) { int rc = 0; int i; u8 *bksv = hdcp->current_tp.ksv_list; u8 *bksv_out; struct hdcp_srm_device_id_t *bksv_srm; for (i = 0; i < hdcp->sink_addr.ksv_fifo.len; i += RECV_ID_SIZE) { SDE_HDCP_DEBUG("bksv : 0x%2x%2x%2x%2x%2x\n", bksv[i + 4], bksv[i + 3], bksv[i + 2], bksv[i + 1], bksv[i]); } bksv_out = sde_hdcp_1x_swap_byte_order(bksv, hdcp->current_tp.dev_count); if (!bksv_out) { rc = -ENOMEM; goto exit; } bksv_srm = (struct hdcp_srm_device_id_t *)bksv_out; /* Here we are checking repeater ksv list */ rc = hdcp1_validate_receiver_ids(bksv_srm, hdcp->current_tp.dev_count); kfree(bksv_out); exit: return rc; } static void sde_hdcp_1x_enable_sink_irq_hpd(struct sde_hdcp_1x *hdcp) { int rc; Loading Loading @@ -872,6 +973,12 @@ static int sde_hdcp_1x_authentication_part1(struct sde_hdcp_1x *hdcp) if (rc) goto error; rc = sde_hdcp_1x_revoked_rcv_chk(hdcp); if (rc) { rc = -SDE_HDCP_SRM_FAIL; goto error; } rc = sde_hdcp_1x_send_an_aksv_to_sink(hdcp); if (rc) goto error; Loading Loading @@ -1196,6 +1303,12 @@ static int sde_hdcp_1x_authentication_part2(struct sde_hdcp_1x *hdcp) if (rc) goto error; rc = sde_hdcp_1x_revoked_rpt_chk(hdcp); if (rc) { rc = -SDE_HDCP_SRM_FAIL; goto error; } do { rc = sde_hdcp_1x_transfer_v_h(hdcp); if (rc) Loading Loading @@ -1317,8 +1430,11 @@ static void sde_hdcp_1x_auth_work(struct work_struct *work) end: if (rc && !sde_hdcp_1x_state(HDCP_STATE_INACTIVE)) if (rc && !sde_hdcp_1x_state(HDCP_STATE_INACTIVE)) { hdcp->hdcp_state = HDCP_STATE_AUTH_FAIL; if (rc == -SDE_HDCP_SRM_FAIL) hdcp->hdcp_state = HDCP_STATE_AUTH_FAIL_NOREAUTH; } /* * Disabling software DDC before going into part3 to make sure Loading Loading @@ -1581,6 +1697,7 @@ void sde_hdcp_1x_deinit(void *input) if (hdcp->workq) destroy_workqueue(hdcp->workq); hdcp1_client_unregister(); kfree(hdcp); } /* hdcp_1x_deinit */ Loading Loading @@ -1680,6 +1797,44 @@ irq_not_handled: return -EINVAL; } static void sde_hdcp_1x_srm_cb(void *input) { struct sde_hdcp_1x *hdcp = (struct sde_hdcp_1x *)input; int rc = 0; if (!hdcp) { pr_err("invalid input\n"); return; } rc = sde_hdcp_1x_revoked_rcv_chk(hdcp); if (rc) { pr_err("receiver failed SRM check\n"); goto fail_noreauth; } /* If its not a repeater we are done */ if (hdcp->current_tp.ds_type != DS_REPEATER) return; /* Check the repeater KSV against SRM */ rc = sde_hdcp_1x_revoked_rpt_chk(hdcp); if (rc) { pr_err("repeater failed SRM check\n"); goto fail_noreauth; } return; fail_noreauth: /* No reauth in case of SRM failure */ hdcp->hdcp_state = HDCP_STATE_AUTH_FAIL_NOREAUTH; sde_hdcp_1x_update_auth_status(hdcp); } void *sde_hdcp_1x_init(struct sde_hdcp_init_data *init_data) { struct sde_hdcp_1x *hdcp = NULL; Loading @@ -1692,6 +1847,10 @@ void *sde_hdcp_1x_init(struct sde_hdcp_init_data *init_data) .off = sde_hdcp_1x_off }; static struct hdcp_client_ops client_ops = { .srm_cb = sde_hdcp_1x_srm_cb, }; if (!init_data || !init_data->core_io || !init_data->qfprom_io || !init_data->mutex || !init_data->notify_status || !init_data->workq || !init_data->cb_data) { Loading Loading @@ -1729,6 +1888,8 @@ void *sde_hdcp_1x_init(struct sde_hdcp_init_data *init_data) init_completion(&hdcp->r0_checked); init_completion(&hdcp->sink_r0_available); /* Register client ctx and the srm_cb with hdcp lib */ hdcp1_client_register((void *)hdcp, &client_ops); SDE_HDCP_DEBUG("HDCP module initialized. HDCP_STATE=%s\n", SDE_HDCP_STATE_NAME); Loading drivers/misc/hdcp.c +186 −19 Original line number Diff line number Diff line Loading @@ -93,6 +93,8 @@ #define RXINFO_SIZE 2 #define SEQ_NUM_V_SIZE 3 #define HDCP_SRM_CMD_CHECK_DEVICE_ID 2 #define RCVR_ID_SIZE BITS_40_IN_BYTES #define MAX_RCVR_IDS_ALLOWED_IN_LIST 31 #define MAX_RCVR_ID_LIST_SIZE \ Loading Loading @@ -437,6 +439,17 @@ struct __attribute__ ((__packed__)) hdcp_update_srm_rsp { uint32_t commandid; }; struct __attribute__ ((__packed__)) hdcp_srm_check_device_ids_req { uint32_t commandid; uint32_t num_device_ids; uint8_t device_ids[1]; }; struct __attribute__ ((__packed__)) hdcp_srm_check_device_ids_rsp { uint32_t commandid; int32_t retval; }; struct __attribute__ ((__packed__)) hdcp_get_topology_req { uint32_t commandid; uint32_t ctxhandle; Loading Loading @@ -496,6 +509,20 @@ struct __attribute__ ((__packed__)) hdcp_rcv_id_list_rsp { uint32_t commandid; }; /* * struct hdcp1_lib_handle - handle for hdcp1 client * @qseecom_handle - for sending commands to hdcp1 TA * @srm_handle - for sending commands to SRM TA * @client_ops - handle to call APIs exposed by hdcp1 client * @client_ctx - client context maintained by hdmi */ struct hdcp1_lib_handle { struct qseecom_handle *qsee_handle; struct qseecom_handle *srm_handle; struct hdcp_client_ops *client_ops; void *client_ctx; }; /* * struct hdcp_lib_handle - handle for hdcp client * @qseecom_handle - for sending commands to qseecom Loading Loading @@ -585,9 +612,10 @@ static void hdcp_lib_stream(struct hdcp_lib_handle *handle); static int hdcp_lib_txmtr_init(struct hdcp_lib_handle *handle); static int hdcp_lib_txmtr_init_legacy(struct hdcp_lib_handle *handle); static struct qseecom_handle *hdcp1_handle; static struct qseecom_handle *hdcpsrm_handle; static struct hdcp1_lib_handle *hdcp1_handle; static bool hdcp1_supported = true; static bool hdcp1_enc_enabled; static struct mutex hdcp1_ta_cmd_lock; Loading Loading @@ -2283,31 +2311,69 @@ static void hdcp_lib_wait_work(struct kthread_work *work) bool hdcp1_check_if_supported_load_app(void) { int rc = 0; bool hdcp1_srm_supported = true; /* start hdcp1 app */ if (hdcp1_supported && !hdcp1_handle) { rc = qseecom_start_app(&hdcp1_handle, HDCP1_APP_NAME, if (hdcp1_supported && !hdcp1_handle->qsee_handle) { rc = qseecom_start_app(&hdcp1_handle->qsee_handle, HDCP1_APP_NAME, QSEECOM_SBUFF_SIZE); if (rc) { pr_err("qseecom_start_app failed %d\n", rc); pr_err("hdcp1 qseecom_start_app failed %d\n", rc); hdcp1_supported = false; } else { kfree(hdcp1_handle); } } /* if hdcp1 app succeeds load SRM TA as well */ if (hdcp1_supported && !hdcp1_handle->srm_handle) { mutex_init(&hdcp1_ta_cmd_lock); rc = qseecom_start_app(&hdcp1_handle->srm_handle, SRMAPP_NAME, QSEECOM_SBUFF_SIZE); if (rc) { hdcp1_srm_supported = false; pr_err("hdcp1_srm qseecom_start_app failed %d\n", rc); } } pr_debug("hdcp1 app %s loaded\n", hdcp1_supported ? "successfully" : "not"); pr_debug("hdcp1 srm app %s loaded\n", hdcp1_srm_supported ? "successfully" : "not"); return hdcp1_supported; } void hdcp1_client_register(void *client_ctx, struct hdcp_client_ops *ops) { /* initialize the hdcp1 handle */ hdcp1_handle = kzalloc(sizeof(*hdcp1_handle), GFP_KERNEL); if (hdcp1_handle) { hdcp1_handle->client_ops = ops; hdcp1_handle->client_ctx = client_ctx; } } void hdcp1_client_unregister(void) { if (hdcp1_handle && hdcp1_handle->qsee_handle) qseecom_shutdown_app(&hdcp1_handle->qsee_handle); if (hdcp1_handle && hdcp1_handle->srm_handle) qseecom_shutdown_app(&hdcp1_handle->srm_handle); kfree(hdcp1_handle); } /* APIs exposed to all clients */ int hdcp1_set_keys(uint32_t *aksv_msb, uint32_t *aksv_lsb) { int rc = 0; struct hdcp1_key_set_req *key_set_req; struct hdcp1_key_set_rsp *key_set_rsp; struct qseecom_handle *hdcp1_qsee_handle; if (aksv_msb == NULL || aksv_lsb == NULL) return -EINVAL; Loading @@ -2315,12 +2381,17 @@ int hdcp1_set_keys(uint32_t *aksv_msb, uint32_t *aksv_lsb) if (!hdcp1_supported || !hdcp1_handle) return -EINVAL; hdcp1_qsee_handle = hdcp1_handle->qsee_handle; if (!hdcp1_qsee_handle) return -EINVAL; /* set keys and request aksv */ key_set_req = (struct hdcp1_key_set_req *)hdcp1_handle->sbuf; key_set_req = (struct hdcp1_key_set_req *)hdcp1_qsee_handle->sbuf; key_set_req->commandid = HDCP1_SET_KEY_MESSAGE_ID; key_set_rsp = (struct hdcp1_key_set_rsp *)(hdcp1_handle->sbuf + key_set_rsp = (struct hdcp1_key_set_rsp *)(hdcp1_qsee_handle->sbuf + QSEECOM_ALIGN(sizeof(struct hdcp1_key_set_req))); rc = qseecom_send_command(hdcp1_handle, key_set_req, rc = qseecom_send_command(hdcp1_qsee_handle, key_set_req, QSEECOM_ALIGN(sizeof (struct hdcp1_key_set_req)), key_set_rsp, Loading Loading @@ -2351,6 +2422,85 @@ int hdcp1_set_keys(uint32_t *aksv_msb, uint32_t *aksv_lsb) return 0; } int hdcp1_validate_receiver_ids(struct hdcp_srm_device_id_t *device_ids, uint32_t device_id_cnt) { int rc = 0; struct hdcp_srm_check_device_ids_req *recv_id_req; struct hdcp_srm_check_device_ids_rsp *recv_id_rsp; uint32_t sbuf_len; uint32_t rbuf_len; int i = 0; struct qseecom_handle *hdcp1_srmhandle; /* If client has not been registered return */ if (!hdcp1_supported || !hdcp1_handle) return -EINVAL; /* Start the hdcp srm app if not already started */ if (hdcp1_handle && !hdcp1_handle->srm_handle) { rc = qseecom_start_app(&hdcp1_handle->srm_handle, SRMAPP_NAME, QSEECOM_SBUFF_SIZE); if (rc) { pr_err("qseecom_start_app failed for SRM TA %d\n", rc); goto end; } } pr_debug("device_id_cnt = %d\n", device_id_cnt); hdcp1_srmhandle = hdcp1_handle->srm_handle; sbuf_len = sizeof(struct hdcp_srm_check_device_ids_req) + sizeof(struct hdcp_srm_device_id_t) * device_id_cnt - 1; rbuf_len = sizeof(struct hdcp_srm_check_device_ids_rsp); /* Create a SRM validate receiver ID request */ recv_id_req = (struct hdcp_srm_check_device_ids_req *) hdcp1_srmhandle->sbuf; recv_id_req->commandid = HDCP_SRM_CMD_CHECK_DEVICE_ID; recv_id_req->num_device_ids = device_id_cnt; memcpy(recv_id_req->device_ids, device_ids, device_id_cnt * sizeof(struct hdcp_srm_device_id_t)); for (i = 0; i < device_id_cnt * sizeof(struct hdcp_srm_device_id_t); i++) { pr_debug("recv_id_req->device_ids[%d] = 0x%x\n", i, recv_id_req->device_ids[i]); } recv_id_rsp = (struct hdcp_srm_check_device_ids_rsp *) (hdcp1_srmhandle->sbuf + QSEECOM_ALIGN(sbuf_len)); rc = qseecom_send_command(hdcp1_srmhandle, recv_id_req, QSEECOM_ALIGN(sbuf_len), recv_id_rsp, QSEECOM_ALIGN(rbuf_len)); if (rc < 0) { pr_err("qseecom cmd failed err=%d\n", rc); goto end; } rc = recv_id_rsp->retval; if (rc) { pr_err("enc cmd failed, rsp=%d\n", recv_id_rsp->retval); rc = -EINVAL; goto end; } pr_debug("rsp=%d\n", recv_id_rsp->retval); pr_debug("commandid=%d\n", recv_id_rsp->commandid); end: return rc; } static int hdcp_validate_recv_id(struct hdcp_lib_handle *handle) { int rc = 0; Loading Loading @@ -2398,6 +2548,7 @@ int hdcp1_set_enc(bool enable) int rc = 0; struct hdcp1_set_enc_req *set_enc_req; struct hdcp1_set_enc_rsp *set_enc_rsp; struct qseecom_handle *hdcp1_qsee_handle; mutex_lock(&hdcp1_ta_cmd_lock); Loading @@ -2406,18 +2557,23 @@ int hdcp1_set_enc(bool enable) goto end; } hdcp1_qsee_handle = hdcp1_handle->qsee_handle; if (!hdcp1_qsee_handle) return -EINVAL; if (hdcp1_enc_enabled == enable) { pr_info("already %s\n", enable ? "enabled" : "disabled"); goto end; } /* set keys and request aksv */ set_enc_req = (struct hdcp1_set_enc_req *)hdcp1_handle->sbuf; set_enc_req = (struct hdcp1_set_enc_req *)hdcp1_qsee_handle->sbuf; set_enc_req->commandid = HDCP1_SET_ENC_MESSAGE_ID; set_enc_req->enable = enable; set_enc_rsp = (struct hdcp1_set_enc_rsp *)(hdcp1_handle->sbuf + set_enc_rsp = (struct hdcp1_set_enc_rsp *)(hdcp1_qsee_handle->sbuf + QSEECOM_ALIGN(sizeof(struct hdcp1_set_enc_req))); rc = qseecom_send_command(hdcp1_handle, set_enc_req, rc = qseecom_send_command(hdcp1_qsee_handle, set_enc_req, QSEECOM_ALIGN(sizeof (struct hdcp1_set_enc_req)), set_enc_rsp, Loading Loading @@ -2679,6 +2835,8 @@ static ssize_t hdmi_hdcp_srm_updated(struct device *dev, int srm_updated; struct hdcp_lib_handle *handle; ssize_t ret = count; struct hdcp_client_ops *client_ops; void *hdcp_client_ctx; handle = hdcp_drv_mgr->handle; Loading @@ -2689,12 +2847,21 @@ static ssize_t hdmi_hdcp_srm_updated(struct device *dev, } if (srm_updated) { if (handle && handle->qseecom_handle) { client_ops = handle->client_ops; hdcp_client_ctx = handle->client_ctx; if (hdcp_validate_recv_id(handle)) { pr_debug("SRM check FAILED\n"); if (handle && handle->client_ops->srm_cb) handle->client_ops->srm_cb(handle->client_ctx); } else { pr_debug("SRM check PASSED\n"); pr_debug("HDCP 2.2 SRM check FAILED\n"); if (handle && client_ops->srm_cb) client_ops->srm_cb(hdcp_client_ctx); } else pr_debug("HDCP 2.2 SRM check PASSED\n"); } else if (hdcp1_handle && hdcp1_handle->qsee_handle) { pr_debug("HDCP 1.4 SRM check\n"); hdcp_client_ctx = hdcp1_handle->client_ctx; client_ops = hdcp1_handle->client_ops; if (client_ops->srm_cb) client_ops->srm_cb(hdcp_client_ctx); } } Loading include/linux/hdcp_qseecom.h +12 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,8 @@ #include <linux/types.h> #define HDCP_MAX_MESSAGE_PARTS 4 #define RECV_ID_SIZE 5 #define MAX_DEVICES_SUPPORTED 127 enum hdcp_lib_wakeup_cmd { HDCP_LIB_WKUP_CMD_INVALID, Loading Loading @@ -115,6 +117,10 @@ static inline char *hdcp_lib_cmd_to_str(uint32_t cmd) } } struct hdcp_srm_device_id_t { uint8_t data[RECV_ID_SIZE]; }; struct hdcp_txmtr_ops { int (*wakeup)(struct hdcp_lib_wakeup_data *data); bool (*feature_supported)(void *phdcpcontext); Loading Loading @@ -148,6 +154,12 @@ void hdcp_library_deregister(void *phdcpcontext); bool hdcp1_check_if_supported_load_app(void); int hdcp1_set_keys(uint32_t *aksv_msb, uint32_t *aksv_lsb); int hdcp1_set_enc(bool enable); int hdcp1_validate_receiver_ids(struct hdcp_srm_device_id_t *device_ids, uint32_t device_id_cnt); void hdcp1_cache_repeater_topology(void *hdcp1_cached_tp); void hdcp1_notify_topology(void); void hdcp1_client_register(void *client_ctx, struct hdcp_client_ops *ops); void hdcp1_client_unregister(void); #endif /* __HDCP_QSEECOM_H */ Loading
drivers/gpu/drm/msm/sde_hdcp.h +2 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,8 @@ #define SDE_HDCP_DEBUG(fmt, args...) SDE_DEBUG(fmt, ##args) #endif #define SDE_HDCP_SRM_FAIL 29 enum sde_hdcp_client_id { HDCP_CLIENT_HDMI, HDCP_CLIENT_DP, Loading
drivers/gpu/drm/msm/sde_hdcp_1x.c +162 −1 Original line number Diff line number Diff line Loading @@ -748,6 +748,107 @@ error: return rc; } static u8 *sde_hdcp_1x_swap_byte_order(u8 *bksv_in, int num_dev) { u8 *bksv_out; u8 *tmp_out; u8 *tmp_in; int i, j; /* Dont exceed max downstream devices */ if (num_dev > MAX_DEVICES_SUPPORTED) { pr_err("invalid params\n"); return NULL; } bksv_out = kzalloc(RECV_ID_SIZE * num_dev, GFP_KERNEL); if (!bksv_out) return NULL; SDE_HDCP_DEBUG("num_dev = %d\n", num_dev); /* Store temporarily for return */ tmp_out = bksv_out; tmp_in = bksv_in; for (i = 0; i < num_dev; i++) { for (j = 0; j < RECV_ID_SIZE; j++) bksv_out[j] = tmp_in[RECV_ID_SIZE - j - 1]; /* Each KSV is 5 bytes long */ bksv_out += RECV_ID_SIZE; tmp_in += RECV_ID_SIZE; } return tmp_out; } static int sde_hdcp_1x_revoked_rcv_chk(struct sde_hdcp_1x *hdcp) { int rc = 0; u8 *bksv = hdcp->current_tp.bksv; u8 *bksv_out; struct hdcp_srm_device_id_t *bksv_srm; bksv_out = sde_hdcp_1x_swap_byte_order(bksv, 1); if (!bksv_out) { rc = -ENOMEM; goto exit; } SDE_HDCP_DEBUG("bksv_out : 0x%2x%2x%2x%2x%2x\n", bksv_out[4], bksv_out[3], bksv_out[2], bksv_out[1], bksv_out[0]); bksv_srm = (struct hdcp_srm_device_id_t *)bksv_out; /* Here we are checking only receiver ID * hence the device count is one */ rc = hdcp1_validate_receiver_ids(bksv_srm, 1); kfree(bksv_out); exit: return rc; } static int sde_hdcp_1x_revoked_rpt_chk(struct sde_hdcp_1x *hdcp) { int rc = 0; int i; u8 *bksv = hdcp->current_tp.ksv_list; u8 *bksv_out; struct hdcp_srm_device_id_t *bksv_srm; for (i = 0; i < hdcp->sink_addr.ksv_fifo.len; i += RECV_ID_SIZE) { SDE_HDCP_DEBUG("bksv : 0x%2x%2x%2x%2x%2x\n", bksv[i + 4], bksv[i + 3], bksv[i + 2], bksv[i + 1], bksv[i]); } bksv_out = sde_hdcp_1x_swap_byte_order(bksv, hdcp->current_tp.dev_count); if (!bksv_out) { rc = -ENOMEM; goto exit; } bksv_srm = (struct hdcp_srm_device_id_t *)bksv_out; /* Here we are checking repeater ksv list */ rc = hdcp1_validate_receiver_ids(bksv_srm, hdcp->current_tp.dev_count); kfree(bksv_out); exit: return rc; } static void sde_hdcp_1x_enable_sink_irq_hpd(struct sde_hdcp_1x *hdcp) { int rc; Loading Loading @@ -872,6 +973,12 @@ static int sde_hdcp_1x_authentication_part1(struct sde_hdcp_1x *hdcp) if (rc) goto error; rc = sde_hdcp_1x_revoked_rcv_chk(hdcp); if (rc) { rc = -SDE_HDCP_SRM_FAIL; goto error; } rc = sde_hdcp_1x_send_an_aksv_to_sink(hdcp); if (rc) goto error; Loading Loading @@ -1196,6 +1303,12 @@ static int sde_hdcp_1x_authentication_part2(struct sde_hdcp_1x *hdcp) if (rc) goto error; rc = sde_hdcp_1x_revoked_rpt_chk(hdcp); if (rc) { rc = -SDE_HDCP_SRM_FAIL; goto error; } do { rc = sde_hdcp_1x_transfer_v_h(hdcp); if (rc) Loading Loading @@ -1317,8 +1430,11 @@ static void sde_hdcp_1x_auth_work(struct work_struct *work) end: if (rc && !sde_hdcp_1x_state(HDCP_STATE_INACTIVE)) if (rc && !sde_hdcp_1x_state(HDCP_STATE_INACTIVE)) { hdcp->hdcp_state = HDCP_STATE_AUTH_FAIL; if (rc == -SDE_HDCP_SRM_FAIL) hdcp->hdcp_state = HDCP_STATE_AUTH_FAIL_NOREAUTH; } /* * Disabling software DDC before going into part3 to make sure Loading Loading @@ -1581,6 +1697,7 @@ void sde_hdcp_1x_deinit(void *input) if (hdcp->workq) destroy_workqueue(hdcp->workq); hdcp1_client_unregister(); kfree(hdcp); } /* hdcp_1x_deinit */ Loading Loading @@ -1680,6 +1797,44 @@ irq_not_handled: return -EINVAL; } static void sde_hdcp_1x_srm_cb(void *input) { struct sde_hdcp_1x *hdcp = (struct sde_hdcp_1x *)input; int rc = 0; if (!hdcp) { pr_err("invalid input\n"); return; } rc = sde_hdcp_1x_revoked_rcv_chk(hdcp); if (rc) { pr_err("receiver failed SRM check\n"); goto fail_noreauth; } /* If its not a repeater we are done */ if (hdcp->current_tp.ds_type != DS_REPEATER) return; /* Check the repeater KSV against SRM */ rc = sde_hdcp_1x_revoked_rpt_chk(hdcp); if (rc) { pr_err("repeater failed SRM check\n"); goto fail_noreauth; } return; fail_noreauth: /* No reauth in case of SRM failure */ hdcp->hdcp_state = HDCP_STATE_AUTH_FAIL_NOREAUTH; sde_hdcp_1x_update_auth_status(hdcp); } void *sde_hdcp_1x_init(struct sde_hdcp_init_data *init_data) { struct sde_hdcp_1x *hdcp = NULL; Loading @@ -1692,6 +1847,10 @@ void *sde_hdcp_1x_init(struct sde_hdcp_init_data *init_data) .off = sde_hdcp_1x_off }; static struct hdcp_client_ops client_ops = { .srm_cb = sde_hdcp_1x_srm_cb, }; if (!init_data || !init_data->core_io || !init_data->qfprom_io || !init_data->mutex || !init_data->notify_status || !init_data->workq || !init_data->cb_data) { Loading Loading @@ -1729,6 +1888,8 @@ void *sde_hdcp_1x_init(struct sde_hdcp_init_data *init_data) init_completion(&hdcp->r0_checked); init_completion(&hdcp->sink_r0_available); /* Register client ctx and the srm_cb with hdcp lib */ hdcp1_client_register((void *)hdcp, &client_ops); SDE_HDCP_DEBUG("HDCP module initialized. HDCP_STATE=%s\n", SDE_HDCP_STATE_NAME); Loading
drivers/misc/hdcp.c +186 −19 Original line number Diff line number Diff line Loading @@ -93,6 +93,8 @@ #define RXINFO_SIZE 2 #define SEQ_NUM_V_SIZE 3 #define HDCP_SRM_CMD_CHECK_DEVICE_ID 2 #define RCVR_ID_SIZE BITS_40_IN_BYTES #define MAX_RCVR_IDS_ALLOWED_IN_LIST 31 #define MAX_RCVR_ID_LIST_SIZE \ Loading Loading @@ -437,6 +439,17 @@ struct __attribute__ ((__packed__)) hdcp_update_srm_rsp { uint32_t commandid; }; struct __attribute__ ((__packed__)) hdcp_srm_check_device_ids_req { uint32_t commandid; uint32_t num_device_ids; uint8_t device_ids[1]; }; struct __attribute__ ((__packed__)) hdcp_srm_check_device_ids_rsp { uint32_t commandid; int32_t retval; }; struct __attribute__ ((__packed__)) hdcp_get_topology_req { uint32_t commandid; uint32_t ctxhandle; Loading Loading @@ -496,6 +509,20 @@ struct __attribute__ ((__packed__)) hdcp_rcv_id_list_rsp { uint32_t commandid; }; /* * struct hdcp1_lib_handle - handle for hdcp1 client * @qseecom_handle - for sending commands to hdcp1 TA * @srm_handle - for sending commands to SRM TA * @client_ops - handle to call APIs exposed by hdcp1 client * @client_ctx - client context maintained by hdmi */ struct hdcp1_lib_handle { struct qseecom_handle *qsee_handle; struct qseecom_handle *srm_handle; struct hdcp_client_ops *client_ops; void *client_ctx; }; /* * struct hdcp_lib_handle - handle for hdcp client * @qseecom_handle - for sending commands to qseecom Loading Loading @@ -585,9 +612,10 @@ static void hdcp_lib_stream(struct hdcp_lib_handle *handle); static int hdcp_lib_txmtr_init(struct hdcp_lib_handle *handle); static int hdcp_lib_txmtr_init_legacy(struct hdcp_lib_handle *handle); static struct qseecom_handle *hdcp1_handle; static struct qseecom_handle *hdcpsrm_handle; static struct hdcp1_lib_handle *hdcp1_handle; static bool hdcp1_supported = true; static bool hdcp1_enc_enabled; static struct mutex hdcp1_ta_cmd_lock; Loading Loading @@ -2283,31 +2311,69 @@ static void hdcp_lib_wait_work(struct kthread_work *work) bool hdcp1_check_if_supported_load_app(void) { int rc = 0; bool hdcp1_srm_supported = true; /* start hdcp1 app */ if (hdcp1_supported && !hdcp1_handle) { rc = qseecom_start_app(&hdcp1_handle, HDCP1_APP_NAME, if (hdcp1_supported && !hdcp1_handle->qsee_handle) { rc = qseecom_start_app(&hdcp1_handle->qsee_handle, HDCP1_APP_NAME, QSEECOM_SBUFF_SIZE); if (rc) { pr_err("qseecom_start_app failed %d\n", rc); pr_err("hdcp1 qseecom_start_app failed %d\n", rc); hdcp1_supported = false; } else { kfree(hdcp1_handle); } } /* if hdcp1 app succeeds load SRM TA as well */ if (hdcp1_supported && !hdcp1_handle->srm_handle) { mutex_init(&hdcp1_ta_cmd_lock); rc = qseecom_start_app(&hdcp1_handle->srm_handle, SRMAPP_NAME, QSEECOM_SBUFF_SIZE); if (rc) { hdcp1_srm_supported = false; pr_err("hdcp1_srm qseecom_start_app failed %d\n", rc); } } pr_debug("hdcp1 app %s loaded\n", hdcp1_supported ? "successfully" : "not"); pr_debug("hdcp1 srm app %s loaded\n", hdcp1_srm_supported ? "successfully" : "not"); return hdcp1_supported; } void hdcp1_client_register(void *client_ctx, struct hdcp_client_ops *ops) { /* initialize the hdcp1 handle */ hdcp1_handle = kzalloc(sizeof(*hdcp1_handle), GFP_KERNEL); if (hdcp1_handle) { hdcp1_handle->client_ops = ops; hdcp1_handle->client_ctx = client_ctx; } } void hdcp1_client_unregister(void) { if (hdcp1_handle && hdcp1_handle->qsee_handle) qseecom_shutdown_app(&hdcp1_handle->qsee_handle); if (hdcp1_handle && hdcp1_handle->srm_handle) qseecom_shutdown_app(&hdcp1_handle->srm_handle); kfree(hdcp1_handle); } /* APIs exposed to all clients */ int hdcp1_set_keys(uint32_t *aksv_msb, uint32_t *aksv_lsb) { int rc = 0; struct hdcp1_key_set_req *key_set_req; struct hdcp1_key_set_rsp *key_set_rsp; struct qseecom_handle *hdcp1_qsee_handle; if (aksv_msb == NULL || aksv_lsb == NULL) return -EINVAL; Loading @@ -2315,12 +2381,17 @@ int hdcp1_set_keys(uint32_t *aksv_msb, uint32_t *aksv_lsb) if (!hdcp1_supported || !hdcp1_handle) return -EINVAL; hdcp1_qsee_handle = hdcp1_handle->qsee_handle; if (!hdcp1_qsee_handle) return -EINVAL; /* set keys and request aksv */ key_set_req = (struct hdcp1_key_set_req *)hdcp1_handle->sbuf; key_set_req = (struct hdcp1_key_set_req *)hdcp1_qsee_handle->sbuf; key_set_req->commandid = HDCP1_SET_KEY_MESSAGE_ID; key_set_rsp = (struct hdcp1_key_set_rsp *)(hdcp1_handle->sbuf + key_set_rsp = (struct hdcp1_key_set_rsp *)(hdcp1_qsee_handle->sbuf + QSEECOM_ALIGN(sizeof(struct hdcp1_key_set_req))); rc = qseecom_send_command(hdcp1_handle, key_set_req, rc = qseecom_send_command(hdcp1_qsee_handle, key_set_req, QSEECOM_ALIGN(sizeof (struct hdcp1_key_set_req)), key_set_rsp, Loading Loading @@ -2351,6 +2422,85 @@ int hdcp1_set_keys(uint32_t *aksv_msb, uint32_t *aksv_lsb) return 0; } int hdcp1_validate_receiver_ids(struct hdcp_srm_device_id_t *device_ids, uint32_t device_id_cnt) { int rc = 0; struct hdcp_srm_check_device_ids_req *recv_id_req; struct hdcp_srm_check_device_ids_rsp *recv_id_rsp; uint32_t sbuf_len; uint32_t rbuf_len; int i = 0; struct qseecom_handle *hdcp1_srmhandle; /* If client has not been registered return */ if (!hdcp1_supported || !hdcp1_handle) return -EINVAL; /* Start the hdcp srm app if not already started */ if (hdcp1_handle && !hdcp1_handle->srm_handle) { rc = qseecom_start_app(&hdcp1_handle->srm_handle, SRMAPP_NAME, QSEECOM_SBUFF_SIZE); if (rc) { pr_err("qseecom_start_app failed for SRM TA %d\n", rc); goto end; } } pr_debug("device_id_cnt = %d\n", device_id_cnt); hdcp1_srmhandle = hdcp1_handle->srm_handle; sbuf_len = sizeof(struct hdcp_srm_check_device_ids_req) + sizeof(struct hdcp_srm_device_id_t) * device_id_cnt - 1; rbuf_len = sizeof(struct hdcp_srm_check_device_ids_rsp); /* Create a SRM validate receiver ID request */ recv_id_req = (struct hdcp_srm_check_device_ids_req *) hdcp1_srmhandle->sbuf; recv_id_req->commandid = HDCP_SRM_CMD_CHECK_DEVICE_ID; recv_id_req->num_device_ids = device_id_cnt; memcpy(recv_id_req->device_ids, device_ids, device_id_cnt * sizeof(struct hdcp_srm_device_id_t)); for (i = 0; i < device_id_cnt * sizeof(struct hdcp_srm_device_id_t); i++) { pr_debug("recv_id_req->device_ids[%d] = 0x%x\n", i, recv_id_req->device_ids[i]); } recv_id_rsp = (struct hdcp_srm_check_device_ids_rsp *) (hdcp1_srmhandle->sbuf + QSEECOM_ALIGN(sbuf_len)); rc = qseecom_send_command(hdcp1_srmhandle, recv_id_req, QSEECOM_ALIGN(sbuf_len), recv_id_rsp, QSEECOM_ALIGN(rbuf_len)); if (rc < 0) { pr_err("qseecom cmd failed err=%d\n", rc); goto end; } rc = recv_id_rsp->retval; if (rc) { pr_err("enc cmd failed, rsp=%d\n", recv_id_rsp->retval); rc = -EINVAL; goto end; } pr_debug("rsp=%d\n", recv_id_rsp->retval); pr_debug("commandid=%d\n", recv_id_rsp->commandid); end: return rc; } static int hdcp_validate_recv_id(struct hdcp_lib_handle *handle) { int rc = 0; Loading Loading @@ -2398,6 +2548,7 @@ int hdcp1_set_enc(bool enable) int rc = 0; struct hdcp1_set_enc_req *set_enc_req; struct hdcp1_set_enc_rsp *set_enc_rsp; struct qseecom_handle *hdcp1_qsee_handle; mutex_lock(&hdcp1_ta_cmd_lock); Loading @@ -2406,18 +2557,23 @@ int hdcp1_set_enc(bool enable) goto end; } hdcp1_qsee_handle = hdcp1_handle->qsee_handle; if (!hdcp1_qsee_handle) return -EINVAL; if (hdcp1_enc_enabled == enable) { pr_info("already %s\n", enable ? "enabled" : "disabled"); goto end; } /* set keys and request aksv */ set_enc_req = (struct hdcp1_set_enc_req *)hdcp1_handle->sbuf; set_enc_req = (struct hdcp1_set_enc_req *)hdcp1_qsee_handle->sbuf; set_enc_req->commandid = HDCP1_SET_ENC_MESSAGE_ID; set_enc_req->enable = enable; set_enc_rsp = (struct hdcp1_set_enc_rsp *)(hdcp1_handle->sbuf + set_enc_rsp = (struct hdcp1_set_enc_rsp *)(hdcp1_qsee_handle->sbuf + QSEECOM_ALIGN(sizeof(struct hdcp1_set_enc_req))); rc = qseecom_send_command(hdcp1_handle, set_enc_req, rc = qseecom_send_command(hdcp1_qsee_handle, set_enc_req, QSEECOM_ALIGN(sizeof (struct hdcp1_set_enc_req)), set_enc_rsp, Loading Loading @@ -2679,6 +2835,8 @@ static ssize_t hdmi_hdcp_srm_updated(struct device *dev, int srm_updated; struct hdcp_lib_handle *handle; ssize_t ret = count; struct hdcp_client_ops *client_ops; void *hdcp_client_ctx; handle = hdcp_drv_mgr->handle; Loading @@ -2689,12 +2847,21 @@ static ssize_t hdmi_hdcp_srm_updated(struct device *dev, } if (srm_updated) { if (handle && handle->qseecom_handle) { client_ops = handle->client_ops; hdcp_client_ctx = handle->client_ctx; if (hdcp_validate_recv_id(handle)) { pr_debug("SRM check FAILED\n"); if (handle && handle->client_ops->srm_cb) handle->client_ops->srm_cb(handle->client_ctx); } else { pr_debug("SRM check PASSED\n"); pr_debug("HDCP 2.2 SRM check FAILED\n"); if (handle && client_ops->srm_cb) client_ops->srm_cb(hdcp_client_ctx); } else pr_debug("HDCP 2.2 SRM check PASSED\n"); } else if (hdcp1_handle && hdcp1_handle->qsee_handle) { pr_debug("HDCP 1.4 SRM check\n"); hdcp_client_ctx = hdcp1_handle->client_ctx; client_ops = hdcp1_handle->client_ops; if (client_ops->srm_cb) client_ops->srm_cb(hdcp_client_ctx); } } Loading
include/linux/hdcp_qseecom.h +12 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,8 @@ #include <linux/types.h> #define HDCP_MAX_MESSAGE_PARTS 4 #define RECV_ID_SIZE 5 #define MAX_DEVICES_SUPPORTED 127 enum hdcp_lib_wakeup_cmd { HDCP_LIB_WKUP_CMD_INVALID, Loading Loading @@ -115,6 +117,10 @@ static inline char *hdcp_lib_cmd_to_str(uint32_t cmd) } } struct hdcp_srm_device_id_t { uint8_t data[RECV_ID_SIZE]; }; struct hdcp_txmtr_ops { int (*wakeup)(struct hdcp_lib_wakeup_data *data); bool (*feature_supported)(void *phdcpcontext); Loading Loading @@ -148,6 +154,12 @@ void hdcp_library_deregister(void *phdcpcontext); bool hdcp1_check_if_supported_load_app(void); int hdcp1_set_keys(uint32_t *aksv_msb, uint32_t *aksv_lsb); int hdcp1_set_enc(bool enable); int hdcp1_validate_receiver_ids(struct hdcp_srm_device_id_t *device_ids, uint32_t device_id_cnt); void hdcp1_cache_repeater_topology(void *hdcp1_cached_tp); void hdcp1_notify_topology(void); void hdcp1_client_register(void *client_ctx, struct hdcp_client_ops *ops); void hdcp1_client_unregister(void); #endif /* __HDCP_QSEECOM_H */