diff options
author | Shivaprasad Hongal <shongal@codeaurora.org> | 2016-05-12 18:18:53 -0700 |
---|---|---|
committer | Kyle Yan <kyan@codeaurora.org> | 2016-06-23 14:01:18 -0700 |
commit | dca874b47a1e084eade65db5a19e2e72a1b3fa22 (patch) | |
tree | def3aaa6b50fac006a0ec1caff119a4cdefd3654 /drivers | |
parent | 5b7681a697921b39b9aa48024494bf6cf80775f7 (diff) |
msm: misc: hdcp: support tz hdcp2p2 app interface change
TZ hdcp2p2 app interface has changed to include device,
session commands and version control. Update hdcp driver
to align.
CRs-Fixed: 1027108
Change-Id: I4acdad2f243ea32f6ce10b6c0064ef2a5262fab2
Signed-off-by: Shivaprasad Hongal <shongal@codeaurora.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/misc/hdcp.c | 948 |
1 files changed, 755 insertions, 193 deletions
diff --git a/drivers/misc/hdcp.c b/drivers/misc/hdcp.c index 4a941b9f7600..7d1b9e9121a9 100644 --- a/drivers/misc/hdcp.c +++ b/drivers/misc/hdcp.c @@ -92,7 +92,6 @@ */ #define SLEEP_SET_HW_KEY_MS 300 - #define QSEECOM_ALIGN_SIZE 0x40 #define QSEECOM_ALIGN_MASK (QSEECOM_ALIGN_SIZE - 1) #define QSEECOM_ALIGN(x)\ @@ -108,24 +107,42 @@ #define HDCP_TXMTR_SUBSTATE_WAITING_FOR_STREAM_READY_MESSAGE 3 #define HDCP_TXMTR_SUBSTATE_REPEATER_AUTH_COMPLETE 4 +#define HDCP_DEVICE_ID 0x0008000 +#define HDCP_CREATE_DEVICE_ID(x) (HDCP_DEVICE_ID | (x)) + +#define HDCP_TXMTR_HDMI HDCP_CREATE_DEVICE_ID(1) #define HDCP_TXMTR_SERVICE_ID 0x0001000 -#define SERVICE_TXMTR_CREATE_CMD(x) (HDCP_TXMTR_SERVICE_ID | x) - -#define HDCP_TXMTR_INIT SERVICE_TXMTR_CREATE_CMD(1) -#define HDCP_TXMTR_DEINIT SERVICE_TXMTR_CREATE_CMD(2) -#define HDCP_TXMTR_PROCESS_RECEIVED_MESSAGE SERVICE_TXMTR_CREATE_CMD(3) -#define HDCP_TXMTR_SEND_MESSAGE_TIMEOUT SERVICE_TXMTR_CREATE_CMD(4) -#define HDCP_TXMTR_SET_HW_KEY SERVICE_TXMTR_CREATE_CMD(5) -#define HDCP_TXMTR_QUERY_STREAM_TYPE SERVICE_TXMTR_CREATE_CMD(6) -#define HDCP_TXMTR_GET_KSXORLC128_AND_RIV SERVICE_TXMTR_CREATE_CMD(7) -#define HDCP_TXMTR_PROVISION_KEY SERVICE_TXMTR_CREATE_CMD(8) -#define HDCP_TXMTR_GET_TOPOLOGY_INFO SERVICE_TXMTR_CREATE_CMD(9) -#define HDCP_TXMTR_UPDATE_SRM SERVICE_TXMTR_CREATE_CMD(10) -/*This API calls the library init function */ -#define HDCP_LIB_INIT SERVICE_TXMTR_CREATE_CMD(11) -/*This API calls the library deinit function */ -#define HDCP_LIB_DEINIT SERVICE_TXMTR_CREATE_CMD(12) +#define SERVICE_CREATE_CMD(x) (HDCP_TXMTR_SERVICE_ID | x) + +#define HDCP_TXMTR_INIT SERVICE_CREATE_CMD(1) +#define HDCP_TXMTR_DEINIT SERVICE_CREATE_CMD(2) +#define HDCP_TXMTR_PROCESS_RECEIVED_MESSAGE SERVICE_CREATE_CMD(3) +#define HDCP_TXMTR_SEND_MESSAGE_TIMEOUT SERVICE_CREATE_CMD(4) +#define HDCP_TXMTR_SET_HW_KEY SERVICE_CREATE_CMD(5) +#define HDCP_TXMTR_QUERY_STREAM_TYPE SERVICE_CREATE_CMD(6) +#define HDCP_TXMTR_GET_KSXORLC128_AND_RIV SERVICE_CREATE_CMD(7) +#define HDCP_TXMTR_PROVISION_KEY SERVICE_CREATE_CMD(8) +#define HDCP_TXMTR_GET_TOPOLOGY_INFO SERVICE_CREATE_CMD(9) +#define HDCP_TXMTR_UPDATE_SRM SERVICE_CREATE_CMD(10) +#define HDCP_LIB_INIT SERVICE_CREATE_CMD(11) +#define HDCP_LIB_DEINIT SERVICE_CREATE_CMD(12) +#define HDCP_TXMTR_DELETE_PAIRING_INFO SERVICE_CREATE_CMD(13) +#define HDCP_TXMTR_GET_VERSION SERVICE_CREATE_CMD(14) +#define HDCP_TXMTR_VERIFY_KEY SERVICE_CREATE_CMD(15) +#define HDCP_SESSION_INIT SERVICE_CREATE_CMD(16) +#define HDCP_SESSION_DEINIT SERVICE_CREATE_CMD(17) +#define HDCP_TXMTR_START_AUTHENTICATE SERVICE_CREATE_CMD(18) + +#define HCDP_TXMTR_GET_MAJOR_VERSION(v) (((v) >> 16) & 0xFF) +#define HCDP_TXMTR_GET_MINOR_VERSION(v) (((v) >> 8) & 0xFF) +#define HCDP_TXMTR_GET_PATCH_VERSION(v) ((v) & 0xFF) + +#define HDCP_CLIENT_MAJOR_VERSION 2 +#define HDCP_CLIENT_MINOR_VERSION 1 +#define HDCP_CLIENT_PATCH_VERSION 0 +#define HDCP_CLIENT_MAKE_VERSION(maj, min, patch) \ + ((((maj) & 0xFF) << 16) | (((min) & 0xFF) << 8) | ((patch) & 0xFF)) #define HDCP_LIB_EXECUTE(x) {\ if (handle->tethered)\ @@ -137,9 +154,10 @@ enum hdcp_state { HDCP_STATE_INIT = 0x00, HDCP_STATE_APP_LOADED = 0x01, - HDCP_STATE_TXMTR_INIT = 0x02, - HDCP_STATE_AUTHENTICATED = 0x04, - HDCP_STATE_ERROR = 0x08 + HDCP_STATE_SESSION_INIT = 0x02, + HDCP_STATE_TXMTR_INIT = 0x04, + HDCP_STATE_AUTHENTICATED = 0x08, + HDCP_STATE_ERROR = 0x10 }; enum hdcp_element { @@ -175,40 +193,111 @@ struct __attribute__ ((__packed__)) hdcp1_key_set_rsp { uint8_t ksv[HDCP1_AKSV_SIZE]; }; -struct __attribute__ ((__packed__)) hdcp_init_req { +struct __attribute__ ((__packed__)) hdcp_version_req { + uint32_t commandid; +}; + +struct __attribute__ ((__packed__)) hdcp_version_rsp { uint32_t commandid; + uint32_t commandId; + uint32_t appversion; }; -struct __attribute__ ((__packed__)) hdcp_init_rsp { +struct __attribute__ ((__packed__)) hdcp_lib_init_req_v1 { + uint32_t commandid; +}; + +struct __attribute__ ((__packed__)) hdcp_lib_init_rsp_v1 { uint32_t status; uint32_t commandid; uint32_t ctxhandle; uint32_t timeout; uint32_t msglen; - uint8_t message[MAX_TX_MESSAGE_SIZE]; + uint8_t message[MAX_TX_MESSAGE_SIZE]; }; +struct __attribute__ ((__packed__)) hdcp_lib_init_req { + uint32_t commandid; + uint32_t clientversion; +}; -struct __attribute__ ((__packed__)) hdcp_deinit_req { +struct __attribute__ ((__packed__)) hdcp_lib_init_rsp { + uint32_t status; + uint32_t commandid; + uint32_t appversion; +}; + +struct __attribute__ ((__packed__)) hdcp_lib_deinit_req { + uint32_t commandid; +}; + +struct __attribute__ ((__packed__)) hdcp_lib_deinit_rsp { + uint32_t status; + uint32_t commandid; +}; + +struct __attribute__ ((__packed__)) hdcp_lib_session_init_req { + uint32_t commandid; + uint32_t deviceid; +}; + +struct __attribute__ ((__packed__)) hdcp_lib_session_init_rsp { + uint32_t status; + uint32_t commandid; + uint32_t sessionid; +}; + +struct __attribute__ ((__packed__)) hdcp_lib_session_deinit_req { + uint32_t commandid; + uint32_t sessionid; +}; + +struct __attribute__ ((__packed__)) hdcp_lib_session_deinit_rsp { + uint32_t status; + uint32_t commandid; +}; + +struct __attribute__ ((__packed__)) hdcp_tx_init_req_v1 { + uint32_t commandid; +}; + +struct __attribute__ ((__packed__)) hdcp_tx_init_rsp_v1 { + uint32_t status; uint32_t commandid; uint32_t ctxhandle; + uint32_t timeout; + uint32_t msglen; + uint8_t message[MAX_TX_MESSAGE_SIZE]; }; +struct __attribute__ ((__packed__)) hdcp_tx_init_req { + uint32_t commandid; + uint32_t sessionid; +}; -struct __attribute__ ((__packed__)) hdcp_deinit_rsp { +struct __attribute__ ((__packed__)) hdcp_tx_init_rsp { uint32_t status; uint32_t commandid; + uint32_t ctxhandle; }; +struct __attribute__ ((__packed__)) hdcp_deinit_req { + uint32_t commandid; + uint32_t ctxhandle; +}; + +struct __attribute__ ((__packed__)) hdcp_deinit_rsp { + uint32_t status; + uint32_t commandid; +}; struct __attribute__ ((__packed__)) hdcp_rcvd_msg_req { uint32_t commandid; uint32_t ctxhandle; uint32_t msglen; - uint8_t msg[MAX_RX_MESSAGE_SIZE]; + uint8_t msg[MAX_RX_MESSAGE_SIZE]; }; - struct __attribute__ ((__packed__)) hdcp_rcvd_msg_rsp { uint32_t status; uint32_t commandid; @@ -216,34 +305,30 @@ struct __attribute__ ((__packed__)) hdcp_rcvd_msg_rsp { uint32_t timeout; uint32_t flag; uint32_t msglen; - uint8_t msg[MAX_TX_MESSAGE_SIZE]; + uint8_t msg[MAX_TX_MESSAGE_SIZE]; }; - struct __attribute__ ((__packed__)) hdcp_set_hw_key_req { uint32_t commandid; uint32_t ctxhandle; }; - struct __attribute__ ((__packed__)) hdcp_set_hw_key_rsp { uint32_t status; uint32_t commandid; }; - struct __attribute__ ((__packed__)) hdcp_send_timeout_req { uint32_t commandid; uint32_t ctxhandle; }; - struct __attribute__ ((__packed__)) hdcp_send_timeout_rsp { uint32_t status; uint32_t commandid; uint32_t timeout; uint32_t msglen; - uint8_t message[MAX_TX_MESSAGE_SIZE]; + uint8_t message[MAX_TX_MESSAGE_SIZE]; }; struct __attribute__ ((__packed__)) hdcp_query_stream_type_req { @@ -256,13 +341,13 @@ struct __attribute__ ((__packed__)) hdcp_query_stream_type_rsp { uint32_t commandid; uint32_t timeout; uint32_t msglen; - uint8_t msg[MAX_TX_MESSAGE_SIZE]; + uint8_t msg[MAX_TX_MESSAGE_SIZE]; }; struct __attribute__ ((__packed__)) hdcp_set_stream_type_req { uint32_t commandid; uint32_t ctxhandle; - uint8_t streamtype; + uint8_t streamtype; }; struct __attribute__ ((__packed__)) hdcp_set_stream_type_rsp { @@ -270,10 +355,9 @@ struct __attribute__ ((__packed__)) hdcp_set_stream_type_rsp { uint32_t commandid; uint32_t timeout; uint32_t msglen; - uint8_t message[MAX_TX_MESSAGE_SIZE]; + uint8_t message[MAX_TX_MESSAGE_SIZE]; }; - struct __attribute__ ((__packed__)) hdcp_update_srm_req { uint32_t commandid; uint32_t ctxhandle; @@ -281,26 +365,22 @@ struct __attribute__ ((__packed__)) hdcp_update_srm_req { uint32_t srmlength; }; - struct __attribute__ ((__packed__)) hdcp_update_srm_rsp { uint32_t status; uint32_t commandid; }; - struct __attribute__ ((__packed__)) hdcp_get_topology_req { uint32_t commandid; uint32_t ctxhandle; }; - struct __attribute__ ((__packed__)) hdcp_get_topology_rsp { uint32_t status; uint32_t commandid; struct topology_info topologyinfo; }; - struct __attribute__ ((__packed__)) rxvr_info_struct { uint8_t rcvrCert[522]; uint8_t rrx[BITS_64_IN_BYTES]; @@ -308,7 +388,6 @@ struct __attribute__ ((__packed__)) rxvr_info_struct { bool repeater; }; - struct __attribute__ ((__packed__)) repeater_info_struct { uint8_t RxInfo[RXINFO_SIZE]; uint8_t seq_num_V[SEQ_NUM_V_SIZE]; @@ -327,6 +406,20 @@ struct __attribute__ ((__packed__)) hdcp1_set_enc_rsp { uint32_t ret; }; +struct __attribute__ ((__packed__)) hdcp_start_auth_req { + uint32_t commandid; + uint32_t ctxHandle; +}; + +struct __attribute__ ((__packed__)) hdcp_start_auth_rsp { + uint32_t status; + uint32_t commandid; + uint32_t ctxhandle; + uint32_t timeout; + uint32_t msglen; + uint8_t message[MAX_TX_MESSAGE_SIZE]; +}; + /* * struct hdcp_lib_handle - handle for hdcp client * @qseecom_handle - for sending commands to qseecom @@ -361,6 +454,8 @@ struct hdcp_lib_handle { char *last_msg_recvd_buf; uint32_t last_msg_recvd_len; atomic_t hdcp_off; + uint32_t session_id; + bool legacy_app; struct task_struct *thread; struct completion topo_wait; @@ -373,6 +468,9 @@ struct hdcp_lib_handle { struct kthread_work wk_clean; struct kthread_work wk_topology; struct kthread_work wk_stream; + + int (*hdcp_app_init)(struct hdcp_lib_handle *handle); + int (*hdcp_txmtr_init)(struct hdcp_lib_handle *handle); }; struct hdcp_lib_message_map { @@ -386,6 +484,8 @@ static void hdcp_lib_msg_sent(struct hdcp_lib_handle *handle); static void hdcp_lib_msg_recvd(struct hdcp_lib_handle *handle); static void hdcp_lib_timeout(struct hdcp_lib_handle *handle); 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 bool hdcp1_supported = true; @@ -422,22 +522,24 @@ static const char *hdcp_lib_message_name(int msg_id) } static inline void hdcp_lib_wakeup_client(struct hdcp_lib_handle *handle, - struct hdmi_hdcp_wakeup_data *data) + struct hdmi_hdcp_wakeup_data *data) { int rc = 0; if (handle && handle->client_ops && handle->client_ops->wakeup && - data && (data->cmd != HDMI_HDCP_WKUP_CMD_INVALID)) { + data && (data->cmd != HDMI_HDCP_WKUP_CMD_INVALID)) { rc = handle->client_ops->wakeup(data); if (rc) pr_err("error sending %s to client\n", - hdmi_hdcp_cmd_to_str(data->cmd)); + hdmi_hdcp_cmd_to_str(data->cmd)); } } static inline void hdcp_lib_send_message(struct hdcp_lib_handle *handle) { - struct hdmi_hdcp_wakeup_data cdata = {HDMI_HDCP_WKUP_CMD_SEND_MESSAGE}; + struct hdmi_hdcp_wakeup_data cdata = { + HDMI_HDCP_WKUP_CMD_SEND_MESSAGE + }; cdata.context = handle->client_ctx; cdata.send_msg_buf = handle->listener_buf; @@ -454,7 +556,7 @@ static int hdcp_lib_enable_encryption(struct hdcp_lib_handle *handle) struct hdcp_set_hw_key_rsp *rsp_buf; if (!handle || !handle->qseecom_handle || - !handle->qseecom_handle->sbuf) { + !handle->qseecom_handle->sbuf) { pr_err("invalid handle\n"); rc = -EINVAL; goto error; @@ -466,23 +568,24 @@ static int hdcp_lib_enable_encryption(struct hdcp_lib_handle *handle) */ msleep(SLEEP_SET_HW_KEY_MS); - req_buf = (struct hdcp_set_hw_key_req *)( - handle->qseecom_handle->sbuf); + req_buf = (struct hdcp_set_hw_key_req *)(handle->qseecom_handle->sbuf); req_buf->commandid = HDCP_TXMTR_SET_HW_KEY; req_buf->ctxhandle = handle->tz_ctxhandle; - rsp_buf = (struct hdcp_set_hw_key_rsp *)( - handle->qseecom_handle->sbuf + QSEECOM_ALIGN( - sizeof(struct hdcp_set_hw_key_req))); + rsp_buf = (struct hdcp_set_hw_key_rsp *) + (handle->qseecom_handle->sbuf + + QSEECOM_ALIGN(sizeof(struct hdcp_set_hw_key_req))); rc = qseecom_send_command(handle->qseecom_handle, req_buf, - QSEECOM_ALIGN(sizeof(struct hdcp_set_hw_key_req)), - rsp_buf, QSEECOM_ALIGN(sizeof( - struct hdcp_set_hw_key_rsp))); + QSEECOM_ALIGN(sizeof + (struct hdcp_set_hw_key_req)), + rsp_buf, + QSEECOM_ALIGN(sizeof + (struct hdcp_set_hw_key_rsp))); if ((rc < 0) || (rsp_buf->status < 0)) { pr_err("qseecom cmd failed with err = %d status = %d\n", - rc, rsp_buf->status); + rc, rsp_buf->status); rc = -EINVAL; goto error; } @@ -499,11 +602,12 @@ error: return rc; } -static int hdcp_lib_library_load(struct hdcp_lib_handle *handle) +static int hdcp_lib_get_version(struct hdcp_lib_handle *handle) { int rc = 0; - struct hdcp_init_req *req_buf; - struct hdcp_init_rsp *rsp_buf; + struct hdcp_version_req *req_buf; + struct hdcp_version_rsp *rsp_buf; + uint32_t app_major_version = 0; if (!handle) { pr_err("invalid input\n"); @@ -515,12 +619,173 @@ static int hdcp_lib_library_load(struct hdcp_lib_handle *handle) return rc; } + /* get the TZ hdcp2p2 app version */ + req_buf = (struct hdcp_version_req *)handle->qseecom_handle->sbuf; + req_buf->commandid = HDCP_TXMTR_GET_VERSION; + + rsp_buf = (struct hdcp_version_rsp *) + (handle->qseecom_handle->sbuf + + QSEECOM_ALIGN(sizeof(struct hdcp_version_req))); + + rc = qseecom_send_command(handle->qseecom_handle, + req_buf, + QSEECOM_ALIGN(sizeof + (struct hdcp_lib_init_req)), + rsp_buf, + QSEECOM_ALIGN(sizeof + (struct hdcp_lib_init_rsp))); + + if (rc < 0) { + pr_err("qseecom cmd failed err = %d\n", rc); + goto exit; + } + + app_major_version = HCDP_TXMTR_GET_MAJOR_VERSION(rsp_buf->appversion); + + pr_debug("hdp2p2 app major version %d, app version %d\n", + app_major_version, rsp_buf->appversion); + + if (app_major_version == 1) + handle->legacy_app = true; + +exit: + return rc; +} + +static int hdcp_app_init_legacy(struct hdcp_lib_handle *handle) +{ + int rc = 0; + struct hdcp_lib_init_req_v1 *req_buf; + struct hdcp_lib_init_rsp_v1 *rsp_buf; + + if (!handle) { + pr_err("invalid input\n"); + goto exit; + } + + if (!handle->legacy_app) { + pr_err("wrong init function\n"); + goto exit; + } + + if (handle->hdcp_state & HDCP_STATE_APP_LOADED) { + pr_err("library already loaded\n"); + goto exit; + } + + /* now load the app by sending hdcp_lib_init */ + req_buf = (struct hdcp_lib_init_req_v1 *)handle->qseecom_handle->sbuf; + req_buf->commandid = HDCP_LIB_INIT; + rsp_buf = (struct hdcp_lib_init_rsp_v1 *) + (handle->qseecom_handle->sbuf + + QSEECOM_ALIGN(sizeof(struct hdcp_lib_init_req_v1))); + + rc = qseecom_send_command(handle->qseecom_handle, + req_buf, + QSEECOM_ALIGN(sizeof + (struct hdcp_lib_init_req_v1)), + rsp_buf, + QSEECOM_ALIGN(sizeof + (struct hdcp_lib_init_rsp_v1))); + + if (rc < 0) { + pr_err("qseecom cmd failed err = %d\n", rc); + goto exit; + } + + pr_debug("success\n"); + +exit: + return rc; +} + +static int hdcp_app_init(struct hdcp_lib_handle *handle) +{ + int rc = 0; + struct hdcp_lib_init_req *req_buf; + struct hdcp_lib_init_rsp *rsp_buf; + uint32_t app_minor_version = 0; + + if (!handle) { + pr_err("invalid input\n"); + goto exit; + } + + if (handle->legacy_app) { + pr_err("wrong init function\n"); + goto exit; + } + + if (handle->hdcp_state & HDCP_STATE_APP_LOADED) { + pr_err("library already loaded\n"); + goto exit; + } + + /* now load the app by sending hdcp_lib_init */ + req_buf = (struct hdcp_lib_init_req *)handle->qseecom_handle->sbuf; + req_buf->commandid = HDCP_LIB_INIT; + req_buf->clientversion = + HDCP_CLIENT_MAKE_VERSION(HDCP_CLIENT_MAJOR_VERSION, + HDCP_CLIENT_MINOR_VERSION, + HDCP_CLIENT_PATCH_VERSION); + rsp_buf = (struct hdcp_lib_init_rsp *) + (handle->qseecom_handle->sbuf + + QSEECOM_ALIGN(sizeof(struct hdcp_lib_init_req))); + + rc = qseecom_send_command(handle->qseecom_handle, + req_buf, + QSEECOM_ALIGN(sizeof + (struct hdcp_lib_init_req)), + rsp_buf, + QSEECOM_ALIGN(sizeof + (struct hdcp_lib_init_rsp))); + + if (rc < 0) { + pr_err("qseecom cmd failed err = %d\n", rc); + goto exit; + } + + app_minor_version = HCDP_TXMTR_GET_MINOR_VERSION(rsp_buf->appversion); + if (app_minor_version != HDCP_CLIENT_MINOR_VERSION) { + pr_err + ("client-app minor version mismatch app(%d), client(%d)\n", + app_minor_version, HDCP_CLIENT_MINOR_VERSION); + rc = -1; + goto exit; + } + pr_debug("success\n"); + pr_debug("client version major(%d), minor(%d), patch(%d)\n", + HDCP_CLIENT_MAJOR_VERSION, HDCP_CLIENT_MINOR_VERSION, + HDCP_CLIENT_PATCH_VERSION); + pr_debug("app version major(%d), minor(%d), patch(%d)\n", + HCDP_TXMTR_GET_MAJOR_VERSION(rsp_buf->appversion), + HCDP_TXMTR_GET_MINOR_VERSION(rsp_buf->appversion), + HCDP_TXMTR_GET_PATCH_VERSION(rsp_buf->appversion)); + +exit: + return rc; +} + +static int hdcp_lib_library_load(struct hdcp_lib_handle *handle) +{ + int rc = 0; + + if (!handle) { + pr_err("invalid input\n"); + goto exit; + } + + if (handle->hdcp_state & HDCP_STATE_APP_LOADED) { + pr_err("library already loaded\n"); + goto exit; + } + /* * allocating resource for qseecom handle * the app is not loaded here */ rc = qseecom_start_app(&(handle->qseecom_handle), - TZAPP_NAME, QSEECOM_SBUFF_SIZE); + TZAPP_NAME, QSEECOM_SBUFF_SIZE); if (rc) { pr_err("qseecom_start_app failed %d\n", rc); goto exit; @@ -528,22 +793,30 @@ static int hdcp_lib_library_load(struct hdcp_lib_handle *handle) pr_debug("qseecom_start_app success\n"); - /* now load the app by sending hdcp_lib_init */ - req_buf = (struct hdcp_init_req *)handle->qseecom_handle->sbuf; - req_buf->commandid = HDCP_LIB_INIT; - rsp_buf = (struct hdcp_init_rsp *)(handle->qseecom_handle-> - sbuf + QSEECOM_ALIGN(sizeof(struct hdcp_init_req))); + rc = hdcp_lib_get_version(handle); + if (rc) { + pr_err("library get version failed\n"); + goto exit; + } - rc = qseecom_send_command(handle->qseecom_handle, - req_buf, QSEECOM_ALIGN(sizeof(struct hdcp_init_req)), - rsp_buf, QSEECOM_ALIGN(sizeof(struct hdcp_init_rsp))); + if (handle->legacy_app) { + handle->hdcp_app_init = hdcp_app_init_legacy; + handle->hdcp_txmtr_init = hdcp_lib_txmtr_init_legacy; + } else { + handle->hdcp_app_init = hdcp_app_init; + handle->hdcp_txmtr_init = hdcp_lib_txmtr_init; + } - if (rc < 0) { - pr_err("qseecom cmd failed err = %d\n", rc); + if (handle->hdcp_app_init == NULL) { + pr_err("invalid app init function pointer\n"); goto exit; } - pr_debug("success\n"); + rc = handle->hdcp_app_init(handle); + if (rc) { + pr_err("app init failed\n"); + goto exit; + } handle->hdcp_state |= HDCP_STATE_APP_LOADED; exit: @@ -553,11 +826,11 @@ exit: static int hdcp_lib_library_unload(struct hdcp_lib_handle *handle) { int rc = 0; - struct hdcp_deinit_req *req_buf; - struct hdcp_deinit_rsp *rsp_buf; + struct hdcp_lib_deinit_req *req_buf; + struct hdcp_lib_deinit_rsp *rsp_buf; if (!handle || !handle->qseecom_handle || - !handle->qseecom_handle->sbuf) { + !handle->qseecom_handle->sbuf) { pr_err("invalid handle\n"); rc = -EINVAL; goto exit; @@ -569,15 +842,19 @@ static int hdcp_lib_library_unload(struct hdcp_lib_handle *handle) } /* unloading app by sending hdcp_lib_deinit cmd */ - req_buf = (struct hdcp_deinit_req *)handle-> - qseecom_handle->sbuf; + req_buf = (struct hdcp_lib_deinit_req *)handle->qseecom_handle->sbuf; req_buf->commandid = HDCP_LIB_DEINIT; - rsp_buf = (struct hdcp_deinit_rsp *)(handle->qseecom_handle-> - sbuf + QSEECOM_ALIGN(sizeof(struct hdcp_deinit_req))); + rsp_buf = (struct hdcp_lib_deinit_rsp *) + (handle->qseecom_handle->sbuf + + QSEECOM_ALIGN(sizeof(struct hdcp_lib_deinit_req))); rc = qseecom_send_command(handle->qseecom_handle, - req_buf, QSEECOM_ALIGN(sizeof(struct hdcp_deinit_req)), - rsp_buf, QSEECOM_ALIGN(sizeof(struct hdcp_deinit_rsp))); + req_buf, + QSEECOM_ALIGN(sizeof + (struct hdcp_lib_deinit_req)), + rsp_buf, + QSEECOM_ALIGN(sizeof + (struct hdcp_lib_deinit_rsp))); if (rc < 0) { pr_err("qseecom cmd failed err = %d\n", rc); @@ -597,14 +874,183 @@ exit: return rc; } +static int hdcp_lib_session_init(struct hdcp_lib_handle *handle) +{ + int rc = 0; + struct hdcp_lib_session_init_req *req_buf; + struct hdcp_lib_session_init_rsp *rsp_buf; + + if (!handle || !handle->qseecom_handle || + !handle->qseecom_handle->sbuf) { + pr_err("invalid handle\n"); + rc = -EINVAL; + goto exit; + } + + if (!(handle->hdcp_state & HDCP_STATE_APP_LOADED)) { + pr_err("app not loaded\n"); + goto exit; + } + + if (handle->hdcp_state & HDCP_STATE_SESSION_INIT) { + pr_err("session already initialized\n"); + goto exit; + } + + /* send HDCP_Session_Init command to TZ */ + req_buf = + (struct hdcp_lib_session_init_req *)handle->qseecom_handle->sbuf; + req_buf->commandid = HDCP_SESSION_INIT; + req_buf->deviceid = HDCP_TXMTR_HDMI; + rsp_buf = (struct hdcp_lib_session_init_rsp *) + (handle->qseecom_handle->sbuf + + QSEECOM_ALIGN(sizeof(struct hdcp_lib_session_init_req))); + + rc = qseecom_send_command(handle->qseecom_handle, req_buf, + QSEECOM_ALIGN(sizeof + (struct + hdcp_lib_session_init_req)), + rsp_buf, + QSEECOM_ALIGN(sizeof + (struct + hdcp_lib_session_init_rsp))); + + if ((rc < 0) || (rsp_buf->status != HDCP_SUCCESS) || + (rsp_buf->commandid != HDCP_SESSION_INIT)) { + pr_err("qseecom cmd failed with err = %d, status = %d\n", + rc, rsp_buf->status); + rc = -EINVAL; + goto exit; + } + + pr_debug("session id %d\n", rsp_buf->sessionid); + + handle->session_id = rsp_buf->sessionid; + handle->hdcp_state |= HDCP_STATE_SESSION_INIT; + + pr_debug("success\n"); +exit: + return rc; +} + +static int hdcp_lib_session_deinit(struct hdcp_lib_handle *handle) +{ + int rc = 0; + struct hdcp_lib_session_deinit_req *req_buf; + struct hdcp_lib_session_deinit_rsp *rsp_buf; + + if (!handle || !handle->qseecom_handle || + !handle->qseecom_handle->sbuf) { + pr_err("invalid handle\n"); + rc = -EINVAL; + goto exit; + } + + if (!(handle->hdcp_state & HDCP_STATE_APP_LOADED)) { + pr_err("app not loaded\n"); + goto exit; + } + + if (!(handle->hdcp_state & HDCP_STATE_SESSION_INIT)) { + /* unload library here */ + pr_err("session not initialized\n"); + goto exit; + } + + /* send command to TZ */ + req_buf = + (struct hdcp_lib_session_deinit_req *)handle->qseecom_handle->sbuf; + req_buf->commandid = HDCP_SESSION_DEINIT; + req_buf->sessionid = handle->session_id; + rsp_buf = (struct hdcp_lib_session_deinit_rsp *) + (handle->qseecom_handle->sbuf + + QSEECOM_ALIGN(sizeof(struct hdcp_lib_session_deinit_req))); + + rc = qseecom_send_command(handle->qseecom_handle, req_buf, + QSEECOM_ALIGN(sizeof + (struct + hdcp_lib_session_deinit_req)), + rsp_buf, + QSEECOM_ALIGN(sizeof + (struct + hdcp_lib_session_deinit_rsp))); + + if ((rc < 0) || (rsp_buf->status < 0) || + (rsp_buf->commandid != HDCP_SESSION_DEINIT)) { + pr_err("qseecom cmd failed with err = %d status = %d\n", + rc, rsp_buf->status); + rc = -EINVAL; + goto exit; + } + + handle->hdcp_state &= ~HDCP_STATE_SESSION_INIT; + pr_debug("success\n"); +exit: + return rc; +} + static int hdcp_lib_txmtr_init(struct hdcp_lib_handle *handle) { int rc = 0; - struct hdcp_init_req *req_buf; - struct hdcp_init_rsp *rsp_buf; + struct hdcp_tx_init_req *req_buf; + struct hdcp_tx_init_rsp *rsp_buf; + + if (!handle || !handle->qseecom_handle || + !handle->qseecom_handle->sbuf) { + pr_err("invalid handle\n"); + rc = -EINVAL; + goto exit; + } + + if (!(handle->hdcp_state & HDCP_STATE_SESSION_INIT)) { + pr_err("session not initialized\n"); + goto exit; + } + + if (handle->hdcp_state & HDCP_STATE_TXMTR_INIT) { + pr_err("txmtr already initialized\n"); + goto exit; + } + + /* send HDCP_Txmtr_Init command to TZ */ + req_buf = (struct hdcp_tx_init_req *)handle->qseecom_handle->sbuf; + req_buf->commandid = HDCP_TXMTR_INIT; + req_buf->sessionid = handle->session_id; + rsp_buf = (struct hdcp_tx_init_rsp *) + (handle->qseecom_handle->sbuf + + QSEECOM_ALIGN(sizeof(struct hdcp_tx_init_req))); + + rc = qseecom_send_command(handle->qseecom_handle, req_buf, + QSEECOM_ALIGN(sizeof + (struct hdcp_tx_init_req)), + rsp_buf, + QSEECOM_ALIGN(sizeof + (struct hdcp_tx_init_rsp))); + + if ((rc < 0) || (rsp_buf->status != HDCP_SUCCESS) || + (rsp_buf->commandid != HDCP_TXMTR_INIT)) { + pr_err("qseecom cmd failed with err = %d, status = %d\n", + rc, rsp_buf->status); + rc = -EINVAL; + goto exit; + } + + handle->tz_ctxhandle = rsp_buf->ctxhandle; + handle->hdcp_state |= HDCP_STATE_TXMTR_INIT; + + pr_debug("success\n"); +exit: + return rc; +} + +static int hdcp_lib_txmtr_init_legacy(struct hdcp_lib_handle *handle) +{ + int rc = 0; + struct hdcp_tx_init_req_v1 *req_buf; + struct hdcp_tx_init_rsp_v1 *rsp_buf; if (!handle || !handle->qseecom_handle || - !handle->qseecom_handle->sbuf) { + !handle->qseecom_handle->sbuf) { pr_err("invalid handle\n"); rc = -EINVAL; goto exit; @@ -621,33 +1067,36 @@ static int hdcp_lib_txmtr_init(struct hdcp_lib_handle *handle) } /* send HDCP_Txmtr_Init command to TZ */ - req_buf = (struct hdcp_init_req *)handle-> - qseecom_handle->sbuf; + req_buf = (struct hdcp_tx_init_req_v1 *)handle->qseecom_handle->sbuf; req_buf->commandid = HDCP_TXMTR_INIT; - rsp_buf = (struct hdcp_init_rsp *)(handle->qseecom_handle-> - sbuf + QSEECOM_ALIGN(sizeof(struct hdcp_init_req))); + rsp_buf = (struct hdcp_tx_init_rsp_v1 *) + (handle->qseecom_handle->sbuf + + QSEECOM_ALIGN(sizeof(struct hdcp_tx_init_req_v1))); rc = qseecom_send_command(handle->qseecom_handle, req_buf, - QSEECOM_ALIGN(sizeof(struct hdcp_init_req)), rsp_buf, - QSEECOM_ALIGN(sizeof(struct hdcp_init_rsp))); + QSEECOM_ALIGN(sizeof + (struct hdcp_tx_init_req_v1)), + rsp_buf, + QSEECOM_ALIGN(sizeof + (struct hdcp_tx_init_rsp_v1))); if ((rc < 0) || (rsp_buf->status != HDCP_SUCCESS) || - (rsp_buf->commandid != HDCP_TXMTR_INIT) || - (rsp_buf->msglen <= 0) || (rsp_buf->message == NULL)) { + (rsp_buf->commandid != HDCP_TXMTR_INIT) || + (rsp_buf->msglen <= 0) || (rsp_buf->message == NULL)) { pr_err("qseecom cmd failed with err = %d, status = %d\n", - rc, rsp_buf->status); + rc, rsp_buf->status); rc = -EINVAL; goto exit; } pr_debug("recvd %s from TZ at %dms\n", - hdcp_lib_message_name((int)rsp_buf->message[0]), - jiffies_to_msecs(jiffies)); + hdcp_lib_message_name((int)rsp_buf->message[0]), + jiffies_to_msecs(jiffies)); /* send the response to HDMI driver */ memset(handle->listener_buf, 0, MAX_TX_MESSAGE_SIZE); memcpy(handle->listener_buf, (unsigned char *)rsp_buf->message, - rsp_buf->msglen); + rsp_buf->msglen); handle->msglen = rsp_buf->msglen; handle->hdcp_timeout = rsp_buf->timeout; @@ -666,7 +1115,7 @@ static int hdcp_lib_txmtr_deinit(struct hdcp_lib_handle *handle) struct hdcp_deinit_rsp *rsp_buf; if (!handle || !handle->qseecom_handle || - !handle->qseecom_handle->sbuf) { + !handle->qseecom_handle->sbuf) { pr_err("invalid handle\n"); rc = -EINVAL; goto exit; @@ -684,22 +1133,23 @@ static int hdcp_lib_txmtr_deinit(struct hdcp_lib_handle *handle) } /* send command to TZ */ - req_buf = (struct hdcp_deinit_req *)handle-> - qseecom_handle->sbuf; + req_buf = (struct hdcp_deinit_req *)handle->qseecom_handle->sbuf; req_buf->commandid = HDCP_TXMTR_DEINIT; req_buf->ctxhandle = handle->tz_ctxhandle; - rsp_buf = (struct hdcp_deinit_rsp *)(handle-> - qseecom_handle->sbuf + QSEECOM_ALIGN(sizeof( - struct hdcp_deinit_req))); + rsp_buf = (struct hdcp_deinit_rsp *) + (handle->qseecom_handle->sbuf + + QSEECOM_ALIGN(sizeof(struct hdcp_deinit_req))); rc = qseecom_send_command(handle->qseecom_handle, req_buf, - QSEECOM_ALIGN(sizeof(struct hdcp_deinit_req)), rsp_buf, - QSEECOM_ALIGN(sizeof(struct hdcp_deinit_rsp))); + QSEECOM_ALIGN(sizeof(struct hdcp_deinit_req)), + rsp_buf, + QSEECOM_ALIGN(sizeof + (struct hdcp_deinit_rsp))); if ((rc < 0) || (rsp_buf->status < 0) || - (rsp_buf->commandid != HDCP_TXMTR_DEINIT)) { + (rsp_buf->commandid != HDCP_TXMTR_DEINIT)) { pr_err("qseecom cmd failed with err = %d status = %d\n", - rc, rsp_buf->status); + rc, rsp_buf->status); rc = -EINVAL; goto exit; } @@ -710,6 +1160,71 @@ exit: return rc; } +static int hdcp_lib_start_auth(struct hdcp_lib_handle *handle) +{ + int rc = 0; + struct hdcp_start_auth_req *req_buf; + struct hdcp_start_auth_rsp *rsp_buf; + + if (!handle || !handle->qseecom_handle || + !handle->qseecom_handle->sbuf) { + pr_err("invalid handle\n"); + rc = -EINVAL; + goto exit; + } + + if (!(handle->hdcp_state & HDCP_STATE_SESSION_INIT)) { + pr_err("session not initialized\n"); + goto exit; + } + + if (!(handle->hdcp_state & HDCP_STATE_TXMTR_INIT)) { + pr_err("txmtr not initialized\n"); + goto exit; + } + + /* send HDCP_Txmtr_Start_Auth command to TZ */ + req_buf = (struct hdcp_start_auth_req *)handle->qseecom_handle->sbuf; + req_buf->commandid = HDCP_TXMTR_START_AUTHENTICATE; + req_buf->ctxHandle = handle->tz_ctxhandle; + rsp_buf = (struct hdcp_start_auth_rsp *) + (handle->qseecom_handle->sbuf + + QSEECOM_ALIGN(sizeof(struct hdcp_start_auth_req))); + + rc = qseecom_send_command(handle->qseecom_handle, req_buf, + QSEECOM_ALIGN(sizeof + (struct hdcp_start_auth_req)), + rsp_buf, + QSEECOM_ALIGN(sizeof + (struct hdcp_start_auth_rsp))); + + if ((rc < 0) || (rsp_buf->status != HDCP_SUCCESS) || + (rsp_buf->commandid != HDCP_TXMTR_START_AUTHENTICATE) || + (rsp_buf->msglen <= 0) || (rsp_buf->message == NULL)) { + pr_err("qseecom cmd failed with err = %d, status = %d\n", + rc, rsp_buf->status); + rc = -EINVAL; + goto exit; + } + + pr_debug("recvd %s from TZ at %dms\n", + hdcp_lib_message_name((int)rsp_buf->message[0]), + jiffies_to_msecs(jiffies)); + + /* send the response to HDMI driver */ + memset(handle->listener_buf, 0, MAX_TX_MESSAGE_SIZE); + memcpy(handle->listener_buf, (unsigned char *)rsp_buf->message, + rsp_buf->msglen); + handle->msglen = rsp_buf->msglen; + handle->hdcp_timeout = rsp_buf->timeout; + + handle->tz_ctxhandle = rsp_buf->ctxhandle; + + pr_debug("success\n"); +exit: + return rc; +} + static void hdcp_lib_stream(struct hdcp_lib_handle *handle) { int rc = 0; @@ -717,7 +1232,7 @@ static void hdcp_lib_stream(struct hdcp_lib_handle *handle) struct hdcp_query_stream_type_rsp *rsp_buf; if (!handle || !handle->qseecom_handle || - !handle->qseecom_handle->sbuf) { + !handle->qseecom_handle->sbuf) { pr_err("invalid handle\n"); return; } @@ -733,33 +1248,38 @@ static void hdcp_lib_stream(struct hdcp_lib_handle *handle) } /* send command to TZ */ - req_buf = (struct hdcp_query_stream_type_req *)handle-> - qseecom_handle->sbuf; + req_buf = + (struct hdcp_query_stream_type_req *)handle->qseecom_handle->sbuf; req_buf->commandid = HDCP_TXMTR_QUERY_STREAM_TYPE; req_buf->ctxhandle = handle->tz_ctxhandle; - rsp_buf = (struct hdcp_query_stream_type_rsp *)(handle-> - qseecom_handle->sbuf + QSEECOM_ALIGN(sizeof( - struct hdcp_query_stream_type_req))); + rsp_buf = (struct hdcp_query_stream_type_rsp *) + (handle->qseecom_handle->sbuf + + QSEECOM_ALIGN(sizeof(struct hdcp_query_stream_type_req))); rc = qseecom_send_command(handle->qseecom_handle, req_buf, - QSEECOM_ALIGN(sizeof(struct hdcp_query_stream_type_req)), rsp_buf, - QSEECOM_ALIGN(sizeof(struct hdcp_query_stream_type_rsp))); + QSEECOM_ALIGN(sizeof + (struct + hdcp_query_stream_type_req)), + rsp_buf, + QSEECOM_ALIGN(sizeof + (struct + hdcp_query_stream_type_rsp))); if ((rc < 0) || (rsp_buf->status < 0) || (rsp_buf->msglen <= 0) || - (rsp_buf->commandid != HDCP_TXMTR_QUERY_STREAM_TYPE) || - (rsp_buf->msg == NULL)) { + (rsp_buf->commandid != HDCP_TXMTR_QUERY_STREAM_TYPE) || + (rsp_buf->msg == NULL)) { pr_err("qseecom cmd failed with err=%d status=%d\n", - rc, rsp_buf->status); + rc, rsp_buf->status); rc = -EINVAL; goto exit; } pr_debug("message received from TZ: %s\n", - hdcp_lib_message_name((int)rsp_buf->msg[0])); + hdcp_lib_message_name((int)rsp_buf->msg[0])); memset(handle->listener_buf, 0, MAX_TX_MESSAGE_SIZE); memcpy(handle->listener_buf, (unsigned char *)rsp_buf->msg, - rsp_buf->msglen); + rsp_buf->msglen); handle->hdcp_timeout = rsp_buf->timeout; handle->msglen = rsp_buf->msglen; exit: @@ -770,7 +1290,8 @@ exit: static void hdcp_lib_query_stream_work(struct kthread_work *work) { struct hdcp_lib_handle *handle = container_of(work, - struct hdcp_lib_handle, wk_stream); + struct hdcp_lib_handle, + wk_stream); hdcp_lib_stream(handle); } @@ -885,12 +1406,12 @@ static void hdcp_lib_update_exec_type(void *ctx, bool tethered) if (handle->tethered == tethered) { pr_debug("exec mode same as %s\n", - tethered ? "tethered" : "threaded"); + tethered ? "tethered" : "threaded"); } else { handle->tethered = tethered; pr_debug("exec mode changed to %s\n", - tethered ? "tethered" : "threaded"); + tethered ? "tethered" : "threaded"); } mutex_unlock(&handle->wakeup_mutex); @@ -914,8 +1435,8 @@ static int hdcp_lib_wakeup(struct hdcp_lib_wakeup_data *data) handle->timeout_left = data->timeout; pr_debug("%s, timeout left: %dms, tethered %d\n", - hdcp_lib_cmd_to_str(handle->wakeup_cmd), - handle->timeout_left, handle->tethered); + hdcp_lib_cmd_to_str(handle->wakeup_cmd), + handle->timeout_left, handle->tethered); rc = hdcp_lib_check_valid_state(handle); if (rc) @@ -927,7 +1448,7 @@ static int hdcp_lib_wakeup(struct hdcp_lib_wakeup_data *data) handle->last_msg_recvd_len = data->recvd_msg_len; handle->last_msg_recvd_buf = kzalloc(data->recvd_msg_len, - GFP_KERNEL); + GFP_KERNEL); if (!handle->last_msg_recvd_buf) { rc = -ENOMEM; mutex_unlock(&handle->msg_lock); @@ -935,7 +1456,7 @@ static int hdcp_lib_wakeup(struct hdcp_lib_wakeup_data *data) } memcpy(handle->last_msg_recvd_buf, data->recvd_msg_buf, - data->recvd_msg_len); + data->recvd_msg_len); } mutex_unlock(&handle->msg_lock); @@ -950,6 +1471,7 @@ static int hdcp_lib_wakeup(struct hdcp_lib_wakeup_data *data) handle->last_msg_sent = 0; handle->hdcp_timeout = 0; handle->timeout_left = 0; + handle->legacy_app = false; atomic_set(&handle->hdcp_off, 0); handle->hdcp_state = HDCP_STATE_INIT; @@ -989,7 +1511,7 @@ exit: static void hdcp_lib_msg_sent(struct hdcp_lib_handle *handle) { - struct hdmi_hdcp_wakeup_data cdata = {HDMI_HDCP_WKUP_CMD_INVALID}; + struct hdmi_hdcp_wakeup_data cdata = { HDMI_HDCP_WKUP_CMD_INVALID }; if (!handle) { pr_err("invalid handle\n"); @@ -1003,7 +1525,7 @@ static void hdcp_lib_msg_sent(struct hdcp_lib_handle *handle) if (handle->repeater_flag) { if (!atomic_read(&handle->hdcp_off)) queue_kthread_work(&handle->worker, - &handle->wk_topology); + &handle->wk_topology); } if (!hdcp_lib_enable_encryption(handle)) { @@ -1038,7 +1560,8 @@ static void hdcp_lib_msg_sent(struct hdcp_lib_handle *handle) static void hdcp_lib_msg_sent_work(struct kthread_work *work) { struct hdcp_lib_handle *handle = container_of(work, - struct hdcp_lib_handle, wk_msg_sent); + struct hdcp_lib_handle, + wk_msg_sent); if (handle->wakeup_cmd != HDCP_LIB_WKUP_CMD_MSG_SEND_SUCCESS) { pr_err("invalid wakeup command %d\n", handle->wakeup_cmd); @@ -1066,10 +1589,27 @@ static void hdcp_lib_init(struct hdcp_lib_handle *handle) if (rc) goto exit; - rc = hdcp_lib_txmtr_init(handle); + if (!handle->legacy_app) { + rc = hdcp_lib_session_init(handle); + if (rc) + goto exit; + } + + if (handle->hdcp_txmtr_init == NULL) { + pr_err("invalid txmtr init function pointer\n"); + return; + } + + rc = handle->hdcp_txmtr_init(handle); if (rc) goto exit; + if (!handle->legacy_app) { + rc = hdcp_lib_start_auth(handle); + if (rc) + goto exit; + } + hdcp_lib_send_message(handle); return; @@ -1080,7 +1620,8 @@ exit: static void hdcp_lib_init_work(struct kthread_work *work) { struct hdcp_lib_handle *handle = container_of(work, - struct hdcp_lib_handle, wk_init); + struct hdcp_lib_handle, + wk_init); hdcp_lib_init(handle); } @@ -1092,7 +1633,7 @@ static void hdcp_lib_timeout(struct hdcp_lib_handle *handle) struct hdcp_send_timeout_rsp *rsp_buf; if (!handle || !handle->qseecom_handle || - !handle->qseecom_handle->sbuf) { + !handle->qseecom_handle->sbuf) { pr_debug("invalid handle\n"); return; } @@ -1103,21 +1644,25 @@ static void hdcp_lib_timeout(struct hdcp_lib_handle *handle) } req_buf = (struct hdcp_send_timeout_req *) - (handle->qseecom_handle->sbuf); + (handle->qseecom_handle->sbuf); req_buf->commandid = HDCP_TXMTR_SEND_MESSAGE_TIMEOUT; req_buf->ctxhandle = handle->tz_ctxhandle; - rsp_buf = (struct hdcp_send_timeout_rsp *)(handle-> - qseecom_handle->sbuf + QSEECOM_ALIGN(sizeof( - struct hdcp_send_timeout_req))); + rsp_buf = (struct hdcp_send_timeout_rsp *) + (handle->qseecom_handle->sbuf + + QSEECOM_ALIGN(sizeof(struct hdcp_send_timeout_req))); rc = qseecom_send_command(handle->qseecom_handle, req_buf, - QSEECOM_ALIGN(sizeof(struct hdcp_send_timeout_req)), rsp_buf, - QSEECOM_ALIGN(sizeof(struct hdcp_send_timeout_rsp))); + QSEECOM_ALIGN(sizeof + (struct hdcp_send_timeout_req)), + rsp_buf, + QSEECOM_ALIGN(sizeof + (struct + hdcp_send_timeout_rsp))); if ((rc < 0) || (rsp_buf->status != HDCP_SUCCESS)) { pr_err("qseecom cmd failed for with err = %d status = %d\n", - rc, rsp_buf->status); + rc, rsp_buf->status); rc = -EINVAL; goto error; } @@ -1133,14 +1678,14 @@ static void hdcp_lib_timeout(struct hdcp_lib_handle *handle) * send the message again to TZ */ if ((rsp_buf->commandid == HDCP_TXMTR_PROCESS_RECEIVED_MESSAGE) && - ((int)rsp_buf->message[0] == LC_INIT_MESSAGE_ID) && - (rsp_buf->msglen == LC_INIT_MESSAGE_SIZE)) { + ((int)rsp_buf->message[0] == LC_INIT_MESSAGE_ID) && + (rsp_buf->msglen == LC_INIT_MESSAGE_SIZE)) { if (!atomic_read(&handle->hdcp_off)) { /* keep local copy of TZ response */ memset(handle->listener_buf, 0, MAX_TX_MESSAGE_SIZE); memcpy(handle->listener_buf, - (unsigned char *)rsp_buf->message, - rsp_buf->msglen); + (unsigned char *)rsp_buf->message, + rsp_buf->msglen); handle->hdcp_timeout = rsp_buf->timeout; handle->msglen = rsp_buf->msglen; @@ -1157,14 +1702,15 @@ error: static void hdcp_lib_manage_timeout_work(struct kthread_work *work) { struct hdcp_lib_handle *handle = container_of(work, - struct hdcp_lib_handle, wk_timeout); + struct hdcp_lib_handle, + wk_timeout); hdcp_lib_timeout(handle); } static void hdcp_lib_clean(struct hdcp_lib_handle *handle) { - struct hdmi_hdcp_wakeup_data cdata = {HDMI_HDCP_WKUP_CMD_INVALID}; + struct hdmi_hdcp_wakeup_data cdata = { HDMI_HDCP_WKUP_CMD_INVALID }; if (!handle) { pr_err("invalid input\n"); @@ -1172,6 +1718,8 @@ static void hdcp_lib_clean(struct hdcp_lib_handle *handle) }; hdcp_lib_txmtr_deinit(handle); + if (!handle->legacy_app) + hdcp_lib_session_deinit(handle); hdcp_lib_library_unload(handle); cdata.context = handle->client_ctx; @@ -1183,11 +1731,12 @@ static void hdcp_lib_clean(struct hdcp_lib_handle *handle) atomic_set(&handle->hdcp_off, 1); } - static void hdcp_lib_cleanup_work(struct kthread_work *work) { + struct hdcp_lib_handle *handle = container_of(work, - struct hdcp_lib_handle, wk_clean); + struct hdcp_lib_handle, + wk_clean); hdcp_lib_clean(handle); } @@ -1195,14 +1744,14 @@ static void hdcp_lib_cleanup_work(struct kthread_work *work) static void hdcp_lib_msg_recvd(struct hdcp_lib_handle *handle) { int rc = 0; - struct hdmi_hdcp_wakeup_data cdata = {HDMI_HDCP_WKUP_CMD_INVALID}; + struct hdmi_hdcp_wakeup_data cdata = { HDMI_HDCP_WKUP_CMD_INVALID }; struct hdcp_rcvd_msg_req *req_buf; struct hdcp_rcvd_msg_rsp *rsp_buf; uint32_t msglen; char *msg = NULL; if (!handle || !handle->qseecom_handle || - !handle->qseecom_handle->sbuf) { + !handle->qseecom_handle->sbuf) { pr_err("invalid handle\n"); return; } @@ -1236,31 +1785,34 @@ static void hdcp_lib_msg_recvd(struct hdcp_lib_handle *handle) mutex_unlock(&handle->msg_lock); pr_debug("msg received: %s from sink\n", - hdcp_lib_message_name((int)msg[0])); + hdcp_lib_message_name((int)msg[0])); /* send the message to QSEECOM */ - req_buf = (struct hdcp_rcvd_msg_req *)(handle-> - qseecom_handle->sbuf); + req_buf = (struct hdcp_rcvd_msg_req *)(handle->qseecom_handle->sbuf); req_buf->commandid = HDCP_TXMTR_PROCESS_RECEIVED_MESSAGE; memcpy(req_buf->msg, msg, msglen); req_buf->msglen = msglen; req_buf->ctxhandle = handle->tz_ctxhandle; - rsp_buf = (struct hdcp_rcvd_msg_rsp *)(handle-> - qseecom_handle->sbuf + QSEECOM_ALIGN(sizeof( - struct hdcp_rcvd_msg_req))); + rsp_buf = + (struct hdcp_rcvd_msg_rsp *)(handle->qseecom_handle->sbuf + + QSEECOM_ALIGN(sizeof + (struct + hdcp_rcvd_msg_req))); pr_debug("writing %s to TZ at %dms\n", - hdcp_lib_message_name((int)msg[0]), - jiffies_to_msecs(jiffies)); + hdcp_lib_message_name((int)msg[0]), jiffies_to_msecs(jiffies)); rc = qseecom_send_command(handle->qseecom_handle, req_buf, - QSEECOM_ALIGN(sizeof(struct hdcp_rcvd_msg_req)), rsp_buf, - QSEECOM_ALIGN(sizeof(struct hdcp_rcvd_msg_rsp))); + QSEECOM_ALIGN(sizeof + (struct hdcp_rcvd_msg_req)), + rsp_buf, + QSEECOM_ALIGN(sizeof + (struct hdcp_rcvd_msg_rsp))); /* get next message from sink if we receive H PRIME on no store km */ if ((msg[0] == AKE_SEND_H_PRIME_MESSAGE_ID) && - handle->no_stored_km_flag) { + handle->no_stored_km_flag) { handle->hdcp_timeout = rsp_buf->timeout; cdata.cmd = HDMI_HDCP_WKUP_CMD_RECV_MESSAGE; @@ -1270,25 +1822,25 @@ static void hdcp_lib_msg_recvd(struct hdcp_lib_handle *handle) } if ((msg[0] == REPEATER_AUTH_STREAM_READY_MESSAGE_ID) && - (rc == 0) && (rsp_buf->status == 0)) { + (rc == 0) && (rsp_buf->status == 0)) { pr_debug("Got Auth_Stream_Ready, nothing sent to rx\n"); cdata.cmd = HDMI_HDCP_WKUP_CMD_LINK_POLL; goto exit; } - if ((rc < 0) || (rsp_buf->status < 0) || (rsp_buf->msglen <= 0) || - (rsp_buf->commandid != HDCP_TXMTR_PROCESS_RECEIVED_MESSAGE) || - (rsp_buf->msg == NULL)) { + if ((rc < 0) || (rsp_buf->status != 0) || (rsp_buf->msglen <= 0) || + (rsp_buf->commandid != HDCP_TXMTR_PROCESS_RECEIVED_MESSAGE) || + (rsp_buf->msg == NULL)) { pr_err("qseecom cmd failed with err=%d status=%d\n", - rc, rsp_buf->status); + rc, rsp_buf->status); rc = -EINVAL; goto exit; } pr_debug("recvd %s from TZ at %dms\n", - hdcp_lib_message_name((int)rsp_buf->msg[0]), - jiffies_to_msecs(jiffies)); + hdcp_lib_message_name((int)rsp_buf->msg[0]), + jiffies_to_msecs(jiffies)); /* set the flag if response is AKE_No_Stored_km */ if (((int)rsp_buf->msg[0] == AKE_NO_STORED_KM_MESSAGE_ID)) { @@ -1300,17 +1852,17 @@ static void hdcp_lib_msg_recvd(struct hdcp_lib_handle *handle) /* check if it's a repeater */ if ((rsp_buf->msg[0] == SKE_SEND_EKS_MESSAGE_ID) && - (rsp_buf->msglen == SKE_SEND_EKS_MESSAGE_SIZE)) { + (rsp_buf->msglen == SKE_SEND_EKS_MESSAGE_SIZE)) { if ((rsp_buf->flag == - HDCP_TXMTR_SUBSTATE_WAITING_FOR_RECIEVERID_LIST) && - (rsp_buf->timeout > 0)) + HDCP_TXMTR_SUBSTATE_WAITING_FOR_RECIEVERID_LIST) && + (rsp_buf->timeout > 0)) handle->repeater_flag = true; - handle->update_stream = true; + handle->update_stream = true; } memset(handle->listener_buf, 0, MAX_TX_MESSAGE_SIZE); memcpy(handle->listener_buf, (unsigned char *)rsp_buf->msg, - rsp_buf->msglen); + rsp_buf->msglen); handle->hdcp_timeout = rsp_buf->timeout; handle->msglen = rsp_buf->msglen; @@ -1333,7 +1885,8 @@ exit: static void hdcp_lib_msg_recvd_work(struct kthread_work *work) { struct hdcp_lib_handle *handle = container_of(work, - struct hdcp_lib_handle, wk_msg_recvd); + struct hdcp_lib_handle, + wk_msg_recvd); hdcp_lib_msg_recvd(handle); } @@ -1342,7 +1895,8 @@ static void hdcp_lib_topology_work(struct kthread_work *work) { u32 timeout; struct hdcp_lib_handle *handle = container_of(work, - struct hdcp_lib_handle, wk_topology); + struct hdcp_lib_handle, + wk_topology); if (!handle) { pr_err("invalid input\n"); @@ -1366,7 +1920,7 @@ bool hdcp1_check_if_supported_load_app(void) /* start hdcp1 app */ if (hdcp1_supported && !hdcp1_handle) { rc = qseecom_start_app(&hdcp1_handle, HDCP1_APP_NAME, - QSEECOM_SBUFF_SIZE); + QSEECOM_SBUFF_SIZE); if (rc) { pr_err("qseecom_start_app failed %d\n", rc); hdcp1_supported = false; @@ -1374,7 +1928,7 @@ bool hdcp1_check_if_supported_load_app(void) } pr_debug("hdcp1 app %s loaded\n", - hdcp1_supported ? "successfully" : "not"); + hdcp1_supported ? "successfully" : "not"); return hdcp1_supported; } @@ -1396,10 +1950,13 @@ int hdcp1_set_keys(uint32_t *aksv_msb, uint32_t *aksv_lsb) key_set_req = (struct hdcp1_key_set_req *)hdcp1_handle->sbuf; key_set_req->commandid = HDCP1_SET_KEY_MESSAGE_ID; key_set_rsp = (struct hdcp1_key_set_rsp *)(hdcp1_handle->sbuf + - QSEECOM_ALIGN(sizeof(struct hdcp1_key_set_req))); - rc = qseecom_send_command(hdcp1_handle, - key_set_req, QSEECOM_ALIGN(sizeof(struct hdcp1_key_set_req)), - key_set_rsp, QSEECOM_ALIGN(sizeof(struct hdcp1_key_set_rsp))); + QSEECOM_ALIGN(sizeof(struct hdcp1_key_set_req))); + rc = qseecom_send_command(hdcp1_handle, key_set_req, + QSEECOM_ALIGN(sizeof + (struct hdcp1_key_set_req)), + key_set_rsp, + QSEECOM_ALIGN(sizeof + (struct hdcp1_key_set_rsp))); if (rc < 0) { pr_err("qseecom cmd failed err=%d\n", rc); @@ -1408,8 +1965,7 @@ int hdcp1_set_keys(uint32_t *aksv_msb, uint32_t *aksv_lsb) rc = key_set_rsp->ret; if (rc) { - pr_err("set key cmd failed, rsp=%d\n", - key_set_rsp->ret); + pr_err("set key cmd failed, rsp=%d\n", key_set_rsp->ret); return -ENOKEY; } @@ -1441,9 +1997,12 @@ int hdcp1_set_enc(bool enable) set_enc_req->enable = enable; set_enc_rsp = (struct hdcp1_set_enc_rsp *)(hdcp1_handle->sbuf + QSEECOM_ALIGN(sizeof(struct hdcp1_set_enc_req))); - rc = qseecom_send_command(hdcp1_handle, - set_enc_req, QSEECOM_ALIGN(sizeof(struct hdcp1_set_enc_req)), - set_enc_rsp, QSEECOM_ALIGN(sizeof(struct hdcp1_set_enc_rsp))); + rc = qseecom_send_command(hdcp1_handle, set_enc_req, + QSEECOM_ALIGN(sizeof + (struct hdcp1_set_enc_req)), + set_enc_rsp, + QSEECOM_ALIGN(sizeof + (struct hdcp1_set_enc_rsp))); if (rc < 0) { pr_err("qseecom cmd failed err=%d\n", rc); @@ -1452,8 +2011,7 @@ int hdcp1_set_enc(bool enable) rc = set_enc_rsp->ret; if (rc) { - pr_err("enc cmd failed, rsp=%d\n", - set_enc_rsp->ret); + pr_err("enc cmd failed, rsp=%d\n", set_enc_rsp->ret); return -EINVAL; } @@ -1500,6 +2058,8 @@ int hdcp_library_register(struct hdcp_register_data *data) handle->client_ctx = data->client_ctx; handle->client_ops = data->client_ops; handle->tethered = data->tethered; + handle->hdcp_app_init = NULL; + handle->hdcp_txmtr_init = NULL; pr_debug("tethered %d\n", handle->tethered); @@ -1510,13 +2070,13 @@ int hdcp_library_register(struct hdcp_register_data *data) init_kthread_worker(&handle->worker); - init_kthread_work(&handle->wk_init, hdcp_lib_init_work); - init_kthread_work(&handle->wk_msg_sent, hdcp_lib_msg_sent_work); + init_kthread_work(&handle->wk_init, hdcp_lib_init_work); + init_kthread_work(&handle->wk_msg_sent, hdcp_lib_msg_sent_work); init_kthread_work(&handle->wk_msg_recvd, hdcp_lib_msg_recvd_work); - init_kthread_work(&handle->wk_timeout, hdcp_lib_manage_timeout_work); - init_kthread_work(&handle->wk_clean, hdcp_lib_cleanup_work); - init_kthread_work(&handle->wk_topology, hdcp_lib_topology_work); - init_kthread_work(&handle->wk_stream, hdcp_lib_query_stream_work); + init_kthread_work(&handle->wk_timeout, hdcp_lib_manage_timeout_work); + init_kthread_work(&handle->wk_clean, hdcp_lib_cleanup_work); + init_kthread_work(&handle->wk_topology, hdcp_lib_topology_work); + init_kthread_work(&handle->wk_stream, hdcp_lib_query_stream_work); init_completion(&handle->topo_wait); @@ -1529,7 +2089,7 @@ int hdcp_library_register(struct hdcp_register_data *data) *data->hdcp_ctx = handle; handle->thread = kthread_run(kthread_worker_fn, - &handle->worker, "hdcp_tz_lib"); + &handle->worker, "hdcp_tz_lib"); if (IS_ERR(handle->thread)) { pr_err("unable to start lib thread\n"); @@ -1547,6 +2107,7 @@ error: unlock: return rc; } +EXPORT_SYMBOL(hdcp_library_register); void hdcp_library_deregister(void *phdcpcontext) { @@ -1565,3 +2126,4 @@ void hdcp_library_deregister(void *phdcpcontext) kzfree(handle->listener_buf); kzfree(handle); } +EXPORT_SYMBOL(hdcp_library_deregister); |